{"id":18731033,"url":"https://github.com/mcorbin/kvert","last_synced_at":"2025-10-29T04:18:55.103Z","repository":{"id":55068959,"uuid":"440656341","full_name":"mcorbin/kvert","owner":"mcorbin","description":"A powerful tool to generate YAML files","archived":false,"fork":false,"pushed_at":"2022-08-10T20:34:54.000Z","size":61,"stargazers_count":32,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T17:44:34.025Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcorbin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-21T21:35:53.000Z","updated_at":"2025-03-10T22:59:22.000Z","dependencies_parsed_at":"2022-08-14T11:00:44.009Z","dependency_job_id":null,"html_url":"https://github.com/mcorbin/kvert","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mcorbin/kvert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcorbin%2Fkvert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcorbin%2Fkvert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcorbin%2Fkvert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcorbin%2Fkvert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcorbin","download_url":"https://codeload.github.com/mcorbin/kvert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcorbin%2Fkvert/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281558823,"owners_count":26522003,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-29T02:00:06.901Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T14:52:39.841Z","updated_at":"2025-10-29T04:18:55.048Z","avatar_url":"https://github.com/mcorbin.png","language":"Clojure","funding_links":[],"categories":["Configuration Management"],"sub_categories":[],"readme":"# kvert: a powerful tool to generate YAML files\n\n`kvert` lets you generate yaml files in a declarative way. You can for example use it to manage your Kubernetes manifests.\n\nIt supports including parts of definitions into other ones, variables, generating files with a different shape based on a `profile`, reading values from environment variables... All of this allows you to manage your YAML files in an effective way.\n\nThe tool leverages the [EDN](https://github.com/edn-format/edn) format and the [Aero](https://github.com/juxt/aero) library.\n\nWhy `kvert` ? It's simple, powerful and extensible.\nI think neither templating or using YAML to generate more YAML are good solutions to manage Kubernetes resources and that's why I built this tool.\n\n## Install\n\nFor Linux (x86-64), download the `kvert` binary from the [release page](https://github.com/mcorbin/kvert/releases) and put it in your PATH. This binary is built using [GraalVM](https://www.graalvm.org/), more targets may be added soon (help welcome).\n\nYou can alternatively download the `jar` file and then run it with `java -jar kvert.jar` (Java 17 needed).\n\nA docker image is also provided. Note that this image uses `java` as well so executing it is a bit slower than the static binary built with GraalVM.\n\nAll example described below can be done using the Docker image by executing in the directory containing your templates `docker run -v $(pwd):/data mcorbin/kvert:v0.2.0 \u003ccommand\u003e`. The files will be availables in `/data`. Example: `docker run -v $(pwd):/data mcorbin/kvert:v0.2.0 yaml -t /data/example.edn`.\n\n## Quick start\n\n### Simple EDN example\n\nOnce `kvert` installed, you are ready to use it. Let's for example generate a yaml file from a simple EDN definition. Put in `pod.edn` this content:\n\n```clojure\n;; this is a comment\n{:apiVersion \"v1\"\n :kind \"Pod\"\n :metadata {:name \"dnsutils\"\n            :namespace \"default\"}\n :spec {:containers [{:name \"dnsutils\"\n                      :image \"k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3\"\n                      :command [\"sleep\" \"3600\"]\n                      :imagePullPolicy \"ifNotPresent\"}]\n        :restartPolicy \"Always\"}}\n```\n\nNow run `kvert yaml --template pod.edn`:\n\n```yaml\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: dnsutils\n  namespace: default\nspec:\n  containers:\n  - name: dnsutils\n    image: k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3\n    command:\n    - sleep\n    - '3600'\n    imagePullPolicy: ifNotPresent\n  restartPolicy: Always\n```\n\nYou can pass the `-o` (or `--output`) flag to save the output into a file.\n\nAs you can see, we can easily translate EDN to YAML. You can define multiple YAML resources into the same file as well:\n\n```clojure\n[{:name \"yaml-file-1\"}\n {:name \"yaml-file-2\"}]\n```\n\n`kvert` will output:\n\n```yaml\n---\nname: yaml-file-1\n---\nname: yaml-file-2\n```\n\n### Customizations\n\nEDN supports `readers`, which can be used to extend it. Let's now put in `pod.edn` this content:\n\n```clojure\n{:apiVersion \"v1\"\n :kind \"Pod\"\n :metadata {:name \"dnsutils\"\n            :namespace #kvert/var :namespace}\n :spec {:containers [{:name \"dnsutils\"\n                      :image #join [\"k8s.gcr.io/e2e-test-images/jessie-dnsutils:\" #kvert/var :container-version]\n                      :command [\"sleep\" #or [#env SLEEP_DURATION 3600]]\n                      :imagePullPolicy #profile {:production \"ifNotPresent\"\n                                                 :default \"Always\"}}]\n        :restartPolicy \"Always\"}}\n```\n\nAs you an see, we use a few readers (which start with `#`) in this file:\n\n- `#kvert/var` which will replace the next keyword (`:namespace` for example here) with a variable value\n- `#join` which will concatenate several values together\n- `#or` which allows you to define default values\n- `#env` to read values from environment variables\n- `#profile` which create a switch based on the value on the profile you used to run `kvert` (more on that later). This reader also supports default values in `:default`\n\nReaders can be combined together, like in `[\"sleep\" #or [#env SLEEP_DURATION 3600]]` in this example which will first read the SLEEP_DURATION environment variable and fallback to `3600` if it's not defined.\n\nLet's create a new file named `config.edn`:\n\n```clojure\n{:variables {:namespace \"default\"\n             :container-version \"1.3\"}\n :profile :production}\n```\n\nThis file defines variables (referenced by `#kvert/var` in the `pod.edn` file) and the profile (`:production`).\n\nLaunch `kvert yaml --template pod.edn -c config.edn`, the output is:\n\n```yaml\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: dnsutils\n  namespace: default\nspec:\n  containers:\n  - name: dnsutils\n    image: k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3\n    command:\n    - sleep\n    - 3600\n    imagePullPolicy: ifNotPresent\n  restartPolicy: Always\n```\n\nThank to the readers we are able to customize our manifest. We could for example use variables and the profile to have variation between environment, kubernetes clusters...\n\n## Profile\n\nWe configured in this example the profile into the `config.edn` file. You can also set it by configuring the `PROFILE` environment variable when running `kvert`.\n\n## More readers\n\n[Aero](https://github.com/juxt/aero), the library used by `kvert` to parse EDN files supports tons of readers out of the box. You can find them in the library [documentation](https://github.com/juxt/aero#tag-literals). Here are some interesting ones:\n\n**#include**\n\nFor example, the `#include` reader allows you to include an EDN file into another one. Let's create a file named `example.edn` containing:\n\n```clojure\n{:apiVersion \"v1\"\n :kind \"Pod\"\n :metadata {:labels #include \"labels.edn\"}}\n```\n\n`labels.edn` (which can also contain readers if you need to) being:\n\n```clojure\n{:foo \"bar\"\n :environment \"prod\"}\n```\n\nThe output of `kvert yaml --template example.edn` will be:\n\n```yaml\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    foo: bar\n    environment: prod\n```\n\n**#kvert/include**\n\nTHe `#kvert/include` reader works exactly like `#include` but allows you to pass additional variables and configure another profile to the included file:\n\n```clojure\n{:apiVersion \"v1\"\n :kind \"Pod\"\n :metadata {:labels #kvert/include {:path \"labels.edn\"\n                                     :variables {:foo \"bar\"}\n                                     :profile :prod}}}\n ```\n\nIn this example, the content of the `labels.edn` file will be included. Additional variables (`:foo` in this example) are also provided and the profile is also overrided.\n\n**#ref**\n\nAnother cool one is `#ref`, let's modify our `example.edn` with:\n\n```clojure\n{:apiVersion \"v1\"\n :kind \"Pod\"\n :metadata {:name \"foo\"\n            :labels {:name #ref [:metadata :name]}}}\n```\n\nThis file will produce using `kvert yaml --template example.edn`:\n\n```yaml\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: foo\n  labels:\n    name: foo\n```\n\nAs you can see, ref allows you to reference another part of your edn file.\n\nDon't hesitate to check the Aero [documentation](https://github.com/juxt/aero#tag-literals) for more examples !\n\n## Generate EDN from YAML\n\nYou can use `kvert` to convert an existing YAML file to EDN. This can help you to get started with the tool by using existing YAML files. An example with this file named `pod.yml`:\n\n```yaml\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: dnsutils\n  namespace: default\nspec:\n  containers:\n  - name: dnsutils\n    image: k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3\n    command:\n    - sleep\n    - '3600'\n    imagePullPolicy: ifNotPresent\n  restartPolicy: Always\n```\n\n`kvert edn --template pod.yaml` will produce:\n\n```clojure\n[{:apiVersion \"v1\",\n  :kind \"Pod\",\n  :metadata {:name \"dnsutils\", :namespace \"default\"},\n  :spec\n  {:containers\n   [{:name \"dnsutils\",\n     :image \"k8s.gcr.io/e2e-test-images/jessie-dnsutils:1.3\",\n     :command [\"sleep\" \"3600\"],\n     :imagePullPolicy \"ifNotPresent\"}],\n   :restartPolicy \"Always\"}}]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcorbin%2Fkvert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcorbin%2Fkvert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcorbin%2Fkvert/lists"}