{"id":34774910,"url":"https://github.com/cloudtruth/kubetruth","last_synced_at":"2025-12-25T08:13:57.088Z","repository":{"id":40214941,"uuid":"318337703","full_name":"cloudtruth/kubetruth","owner":"cloudtruth","description":"The CloudTruth integration for kubernetes that pushes parameter updates into kubernetes config maps and secrets","archived":false,"fork":false,"pushed_at":"2023-11-10T18:12:42.000Z","size":1140,"stargazers_count":7,"open_issues_count":1,"forks_count":9,"subscribers_count":8,"default_branch":"main","last_synced_at":"2023-11-11T15:09:42.413Z","etag":null,"topics":["cloudtruth","configmaps","configuration-management","kubernetes","kubernetes-operator","secrets","secrets-management"],"latest_commit_sha":null,"homepage":"https://docs.cloudtruth.com/integrations/kubernetes#kubetruth","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudtruth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-12-03T22:35:15.000Z","updated_at":"2023-12-20T15:34:07.074Z","dependencies_parsed_at":"2022-08-24T20:30:21.013Z","dependency_job_id":"f329d82a-6573-4065-acf1-3ead336e4622","html_url":"https://github.com/cloudtruth/kubetruth","commit_stats":null,"previous_names":[],"tags_count":23,"template":null,"template_full_name":null,"purl":"pkg:github/cloudtruth/kubetruth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtruth%2Fkubetruth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtruth%2Fkubetruth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtruth%2Fkubetruth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtruth%2Fkubetruth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudtruth","download_url":"https://codeload.github.com/cloudtruth/kubetruth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtruth%2Fkubetruth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28024398,"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-12-25T02:00:05.988Z","response_time":58,"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":["cloudtruth","configmaps","configuration-management","kubernetes","kubernetes-operator","secrets","secrets-management"],"created_at":"2025-12-25T08:13:56.140Z","updated_at":"2025-12-25T08:13:57.076Z","avatar_url":"https://github.com/cloudtruth.png","language":"Ruby","readme":"[![Build Status](https://github.com/cloudtruth/kubetruth/workflows/CD/badge.svg)](https://github.com/cloudtruth/kubetruth/actions)\n[![Coverage Status](https://codecov.io/gh/cloudtruth/kubetruth/branch/main/graph/badge.svg)](https://codecov.io/gh/cloudtruth/kubetruth)\n[![Configured by CloudTruth](https://img.shields.io/badge/configured--by-CloudTruth-blue.svg?style=plastic\u0026labelColor=384047\u0026color=00A6C0\u0026link=https://cloudtruth.com)](https://cloudtruth.com)\n\n# Kubetruth\n\nThe [CloudTruth integration for kubernetes](https://docs.cloudtruth.com/integrations/kubernetes) that pushes parameter updates into\nkubernetes resources - usually ConfigMaps and Secrets, but any resource is\nallowed.  The goal is to provide you a mechanism that is as hands off as\npossible, using naming conventions to automate the delivery of configuration so\nthat you don't have to jump through setup hoops for each app/service/etc that\nyou would like to configure with CloudTruth.\n\n![CloudTruth Operator KubeTruth Workflow](docs/kubetruth_operator.png)\n\n## Installation\n\n```shell\nhelm repo add cloudtruth https://packages.cloudtruth.com/charts/\nhelm install \\\n    --set appSettings.apiKey=\u003capi_key\u003e \\\n    --set projectMappings.root.environment=\u003cenvironment\u003e \\\n    kubetruth cloudtruth/kubetruth\n```\n\nNote that the helm release name (`kubetruth` above) is used in generating the\nnames of the resources created at install time.  Thus in the examples below, a\nname like `kubetruth-root` for the default installed CRD would be different in\nyour system if you gave `helm install` a different release name.\n\n## Update\n\n```shell\nhelm repo update\nhelm upgrade kubetruth cloudtruth/kubetruth\n```\n\n## Uninstall\n\n```shell\nhelm delete kubetruth\nhelm repo remove cloudtruth\n```\n\n## Usage\n\nParameterize the helm install with `--set *` or `--values yourConfig.yaml` to control how kubetruth matches against your organization's naming conventions:\n\n| Parameter | Description | Type | Default | Required |\n|-----------|-------------|------|---------|:--------:|\n| appSettings.apiKey | The CloudTruth api key.  Read only access is sufficient | string | n/a | yes |\n| appSettings.pollingInterval | Interval to poll CloudTruth api for changes | integer | 300 | no |\n| appSettings.debug | Debug logging and behavior | flag | false | no |\n| secret.create | Create the kubernetes Secret containing the supplied api-key | boolean | true | no |\n| secret.name | The name of the kubernetes Secret to create | string | `\u003chelm fullname\u003e` | no |\n| projectMappings.root.environment | The CloudTruth environment to lookup parameter values for. | string | `default` | yes |\n| projectMappings.root.project_selector | A regexp to limit the projects acted against (client-side).  This performs a substring match, so use regexp anchors to match the entire string, e.g. `\"^myProject$\"`.  Supplies any named matches for template evaluation | string | \"\" | no |\n| projectMappings.root.key_selector | A regexp to limit the keys acted against (client-side).  This performs a substring match, so use regexp anchors to match the entire string, e.g. `\"^myKey$\"`. Supplies any named matches for template evaluation | string | \"\" | no |\n| projectMappings.root.tag | The version tag used when querying for parameters | string | `none` | no |\n| projectMappings.root.skip | Skips the generation of resources for the selected projects | flag | false | no |\n| projectMappings.root.suppress_namespace_inheritance | Prevents the CRD from the primary namespace from being [inherited by secondary namespaces](#multi-instance-config) | flag | false | no |\n| projectMappings.root.log_level | Sets the kubetruth logging level while handling the selected projects | enum(debug, info, warn, error, fatal) | `as set by cli` | no |\n| projectMappings.root.included_projects | Include the parameters from other projects into the selected ones.  This can be recursive in a depth first fashion, so if A imports B and B imports C, then A will get B's and C's parameters.  For key conflicts, if A includes B and B includes C, then the precendence is A overrides B overrides C.  If A includes \\[B, C], then the precendence is A overrides C overrides B. | list | [] | no |\n| projectMappings.root.context | Additional variables made available to the resource templates.  Can also be templates | map | [default](helm/kubetruth/values.yaml#L93-L129) | no |\n| projectMappings.root.active_templates | Selects the templates that should be active, includes all templates when nil, none when empty | list | nil | no |\n| projectMappings.root.resource_templates | The templates to use in generating kubernetes resources (ConfigMap/Secrets/other) | map | [default](helm/kubetruth/values.yaml#L93-L129) | no |\n| projectMappings.\u003coverride_name\u003e.* | Define override mappings to override settings from the root selector for specific projects. When doing this on the command-line (e.g. for `helm install`), it may be more convenient to use `--values \u003cfile\u003e` instead of `--set` for large data sets | map | {} | no |\n\nWith the default `resource_templates`, Kubetruth maps the parameters from\nCloudTruth Projects into ConfigMaps and Secrets of the same names as the\nProjects. Kubetruth will not overwrite any existing kubernetes resources that do\nnot have the label `app.kubernetes.io/managed-by: kubetruth`.  If you have some\nthat you want kubetruth to manage, then either add the label or delete them\nmanually.\n\nFor example, for a CloudTruth layout that looks like:\n\n`myProject`:\n```\noneParam=value1\ntwoParam=value2\n```\n\n`otherProject`:\n```\nsomeParam=value3\nmySecret=value4 (marked as a secret within CloudTruth)\n```\n\nKubetruth will generate the kubernetes resources:\n\nConfigMap named `myProject`:\n```yaml\n    oneParam: value1\n    twoParam: value2\n```\n\nConfigMap named `otherProject`:\n```yaml\n    someParam: value3\n```\n\nSecret named `otherProject`:\n```yaml\n    mySecret: value4\n```\n\nThese kubernetes resources can then be referenced in the standard ways.\n\nTo use them as environment variables in a pod:\n```yaml\n    envFrom:\n      - configMapRef:\n          name: otherProject\n    envFrom:\n      - secretRef:\n          name: otherProject\n```\n\nTo use them as files on disk in a pod:\n```yaml\n      containers:\n        - name: myProject\n          volumeMounts:\n            - name: config-volume\n              mountPath: /etc/myConfig\n      volumes:\n        - name: config-volume\n          configMap:\n            name: myProject\n```\n\nNote that config map updates don't get seen by a running pod.  You can use\nsomething like [Reloader](https://github.com/stakater/Reloader) to automate\nrestarting the pod on a ConfigMap change, or read config from mounted volumes\nfor configmaps/secrets, which do get updated automatically in a running pod.\nAlternatively, you make your ConfigMap's name include a checksum of its\ncontents, and [patch a pre-existing Deployment/Pod](examples/deploymentpatch)\nwhenever that name changes.  Similary, you can also make use of the checksum in\nthe name when [using kubetruth to deploy](examples/deployment)\n\n## Additional configuration\n\nKubetruth uses a CustomResourceDefinition called\n[ProjectMapping(.kubetruth.cloudtruth.com)](helm/kubetruth/crds/projectmapping.yaml)\nfor additional configuration.  The ProjectMapping CRD has two types identified\nby the `scope` property, the `root` scope and the `override` scope.  The `root`\nscope is required, and there can be only one per namespace (see\n[below](#multi-instance-config)).  It sets up the global behavior for mapping\nthe CloudTruth projects to kubernetes resources.  You can edit it in the\nstandard ways, e.g. `kubectl edit projectmapping kubetruth-root`.  The\n`override` scope allows you to override the root scope's behavior for those\nCloudTruth projects whose names match its `project_selector` pattern.\n\nFor the `project_selector`, which is defined under the *Usage* section, you use a regex to match against CloudTruth project names, e.g. `\"^service\"` will match any project that starts with `service`.  Since this does substring matching, if you want to match a specific CloudTruth project name you should use regex anchors to ensure you don't match more than expected.  For example, if you have a CloudTruth project called `kubernetes_secrets`, you'll want the `project_selector` value to be `\"^kubernetes_secrets$\"` so you don't accidentally match another project named `not_kubernetes_secrets`.\n\nNote that Kubetruth watches for changes to ProjectMappings, so touching any of\nthem wakes it up from a polling sleep.  This makes it quick and easy to test out\nconfiguration changes without having a short polling interval.  You can also\nforce a wakeup by execing the wakeup script in the running container:\n\n`kubectl exec deployment/kubetruth -- wakeup`\n\nTo customize how the kubernetes resources are generated, edit the\n`resource_templates` property in the ProjectMappings.  These templates are\nprocessed using the [Liquid template\nlanguage](https://shopify.github.io/liquid/), and can reference the following\nliquid variables:\n\n| Liquid Variables | Description |\n|-----------------|-------------|\n| `template` | The name of the template currently being rendered. |\n| `kubetruth_namespace` | The namespace kubetruth is installed in. |\n| `mapping_namespace` | The namespace that the current set of mappings exist in. |\n| `project` | The project name. |\n| `project_heirarchy` | The `included_projects` tree that this project includes. (useful to debug when using complex `included_projects`) |\n| `debug` | Indicates if kubetruth is operating in debug (logging) mode. |\n| `parameters` | The CloudTruth parameters from the project.|\n| `parameter_origins` | The projects each parameter originates from. (useful to debug when using complex `included_projects`) |\n| `secrets` | The CloudTruth secrets from the project. |\n| `secret_origins` | The projects each secret originates from. (useful to debug when using complex `included_projects`)\n| `templates` | The CloudTruth templates from the project keyed by their name, e.g. `templates.mytemplate` .  Evaluated with the environment from the active ProjectMapping\n| `templates.names` | The names of the CloudTruth templates for the project\n| `context` | A hash of context variables supplied from ProjectMappings. (useful to override portions of templates without having to replace them completely in an override) |\n\nIn addition to the built in liquid filters, kubetruth also define a few custom\nones:\n\n| Custom Filters  | Description |\n|-----------------|-------------|\n| `dns_safe` |  Ensures the string is safe for use as a kubernetes resource name (i.e. Namespace/ConfigMap/Secret names) |\n| `env_safe` |  Ensures the string is safe for setting as a shell environment variable |\n| `key_safe` |  Ensures the string is safe for use as a key inside a ConfigMap/Secret data hash |\n| `indent: count` |  Indents each line in the argument by count spaces |\n| `nindent: count` |  Adds a leading newline, then indents each line in the argument by count spaces |\n| `stringify` |  Converts argument to a string safe to use in yaml (escapes quotes and surrounds with the quote character) |\n| `parse_yaml` |  Parses yaml string into a structured representation |\n| `to_yaml` |  Converts object to a yaml representation |\n| `parse_json` |  Parses json string into a structured representation |\n| `to_json` |  Converts object to a json representation |\n| `encode64` |  The argument bas64 encoded |\n| `decode64` |  The argument bas64 decoded |\n| `sha256` |  The sha256 digest of the argument |\n| `inflate` |  Converts a map of key/values into a nested data structure based on a delimiter in the key name, e.g. `{foo.baz.bum: 2}` =\u003e `{foo: {bar: {baz: 2}}}` Inverse of deflate|\n| `deflate` |  Converts a nested data structure into a single level map using a delimiter to indicate level in the key name, e.g. `{foo: {bar: {baz: 2}}}` =\u003e `{foo.baz.bum: 2}`  Inverse of inflate |\n| `typify` |  Converts string values into primitive types (int, float, bool) where applicable for a nested data structure |\n| `merge` |  Combines two hashes into one, a.l.a ruby merge |\n| `re_replace` |  Regexp search and replace, a.l.a ruby gsub, e.g. `\"foo\" \\| re_replace: \"o+\", \"X\"` |\n| `re_contains` |  Returns a boolean for the regexp compare against the string target, e.g. `\"foo\" \\| re_contains: \"o+\"` =\u003e `true` |\n\nThe default `resource_templates` make use of the `context` attribute to allow\nsimpler modification of some common fields.  These include:\n| Context Variables | Description |\n|-------------------|-------------|\n| `context.resource_name` | set this in a ProjectMapping to supply a different name to the the default templates |\n| `context.resource_namespace` | set this in a ProjectMapping to supply a different namespace to the default templates |\n| `context.skip_secrets` | set this in a ProjectMapping to prevent output of a Secret resource even when secrets are present |\n\nSince the `context` is a freeform map type, you can add custom items to it, as\nwell as architect any custom templates to make use of those custom items in the\nsame way the default templates do.  If the value of a `context` entry is a\nstring, it is treated as a template, and can reference and set variables in the\nresource_template that is evaluating it.  If the value is of some other yaml\ntype (e.g. boolean/number/list/map), it will get passed through as that type to\nthe template that is referencing it, so you can use it in more complex template\nlogic like `{% foreach item in context.my_items %}`\n\nThe default `resource_templates` add the `parameter_origins` and `project_heirarchy`\nkey as annotations on each kubernetes resource under management.  This can be\ndisabled by removing them from the template, or wrapping them in a test for\n`debug`.  The data produced by these help to illustrate how project inclusion\naffects the project the resources were written for.   It currently shows the\nproject heirarchy and the project each parameter originates from, for example an\nentry like `timeout: myService (commonService -\u003e common)` indicates that the\ntimeout parameter is getting its value from the `myService` project, and if you\nremoved it from there, it would then get it from the `commonService` project,\nand if you removed that, it would then get it from the `common` project.\n\n### Multi Instance Config\n\nBy default, Kubetruth is setup with a single set of ProjectMapping CRDs\ninstalled into the same namespace it was installed to.  These are the `primary`\nCRDs.  For systems that use independent kubernetes clusters per environment,\nthis is all that you need.  If, however, you'd like to be able to run multiple\n`environments` in the same cluster, you can make use of the multi-instance\nfeature of kubetruth.\n\nTo do so, one simply needs to create ProjectMapping CRDs in namespaces other\nthan the primary.  These CRDs will automatically inherit the contents of the CRD\nof the same name from the primary namespace, and you can then selectively\noverride the attributes you need to change for the supplemental instance.  This\nallows you to reuse all the templates/logic/etc that you setup in the primary,\nand only have to change the differing dimension.  See the `environment` [example\nbelow](#environment-per-namespace)\n\n### Example Config\n\nThe `projectmapping` resource has a shortname of `pm` for convenience when using kubectl.\n\n#### Namespace per Project\n\nTo create kubernetes Resources in namespaces named after each Project:\n```\nkubectl edit pm kubetruth-root\n```\nand set the `context.resource_namespace` field:\n```\nspec:\n    context:\n        resource_namespace: '{{ project | dns_safe }}'\n```\n\nOr to do it with `kubectl patch`:\n\n```\nkubectl patch pm kubetruth-root --type json --patch '[{\"op\": \"replace\", \"path\": \"/spec/context/resource_namespace\", \"value\": \"{{ project | dns_safe }}\"}]'\n```\n\nOr to do it at install time, add the following to the `helm install` command:\n\n```\n--set projectMappings.root.context.resource_namespace=\"\\{\\{ project | dns_safe \\}\\}\"\n```\n\n#### Share common data\n\nTo include the parameters from a Project named `Base` into all other projects, without creating Resources for `Base` itself:\n```\n# Set the included_project in the root mapping\nkubectl patch pm kubetruth-root --type json --patch '[{\"op\": \"replace\", \"path\": \"/spec/included_projects\", \"value\": [\"Base\"]}]'\n\n# Exclude the Base project by creating an override mapping that skips it:\nkubectl apply -f - \u003c\u003cEOF\napiVersion: kubetruth.cloudtruth.com/v1\nkind: ProjectMapping\nmetadata:\n    name: exclude-base\nspec:\n    scope: override\n    project_selector: \"^Base$\"\n    skip: true\n    included_projects: []\nEOF\n```\n\n#### Customize naming of Resources\n\nTo override the naming of kubernetes Resources on a per-Project basis:\n```\nkubectl apply -f - \u003c\u003cEOF\napiVersion: kubetruth.cloudtruth.com/v1\nkind: ProjectMapping\nmetadata:\n  name: funkyproject-special-naming\nspec:\n    scope: override\n    project_selector: funkyProject\n    context:\n        resource_name: notSoFunkyConfigMap\n        resource_namespace: notSoFunkyNamespace\nEOF\n```\n\n#### Environment per namespace\n\nTo setup an environment per namespace:\n```\n# Optionally disable output from the primary.  This is only neccessary if\n# kubetruth is installed to a namespace that you don't want to generate\n# resources in\nkubectl patch pm kubetruth-root --type json --patch '[{\"op\": \"replace\", \"path\": \"/spec/skip\", \"value\": \"true\"}]'\n\n# Tag each namespace that you'd like to have its own environment\n# The name should be the same name as the primary root mapping created by the\n# kubetruth installer\nkubectl --namespace \u003cyour_namespace\u003e apply -f - \u003c\u003cEOF\napiVersion: kubetruth.cloudtruth.com/v1\nkind: ProjectMapping\nmetadata:\n  name: \u003cyour_root_mapping_name\u003e\nspec:\n  scope: root\n  environment: \u003cyour_environment\u003e\n  skip: false\nEOF\n```\n\n#### More specific project selection\n\nTo limit the Projects processed to those whose names start with `service`, except for `serviceOddball`:\n```\nkubectl patch pm kubetruth-root --type json --patch '[{\"op\": \"replace\", \"path\": \"/spec/project_selector\", \"value\": \"^service\"}]'\n\nkubectl apply -f - \u003c\u003cEOF\napiVersion: kubetruth.cloudtruth.com/v1\nkind: ProjectMapping\nmetadata:\n  name: funkyproject-special-naming\nspec:\n  scope: override\n  project_selector: serviceOddball\n  skip: true\nEOF\n```\n\nTo see the ProjectMappings that have been setup\n```\n$ kubectl get pm\nNAME                          SCOPE      PROJECT          AGE\nexclude-base                  override   ^Base$           7m6s\nfunkyproject-special-naming   override   serviceOddball   13s\nkubetruth-root                root       ^service         27m\n\n$ kubectl describe pm kubetruth-root\nName:         kubetruth-root\nNamespace:    default\n\u003csnipped\u003e\n```\n\n#### Additional examples\n\nMore examples are available in the [examples](./examples) directory\n\n## Development\n\nAfter checking out the repo, run `bundle` to install dependencies. Then, run\n`bundle exec rspec` to run the tests. You can also run `bundle exec rake console` for an\ninteractive prompt that will allow you to experiment.\n\nTo install and run via helm in a local cluster:\n```\nmkdir local\ncat \u003e local/values.yml \u003c\u003c-EOF\nimage:\n  repository: kubetruth\n  pullPolicy: Never\n  tag: latest\nappSettings:\n  debug: true\n  apiKey: \u003cyour_api_key\u003e\nEOF\n\n# requires minikube to be installed and running\nrake install\n\n# OR\n\n# If using minikube, ensure that docker builds the image into the minikube container\n# with the command:\n# eval $(minikube docker-env)\n#\ndocker build --release development -t kubetruth . \u0026\u0026 helm install \\\n    --set image.repository=kubetruth --set image.pullPolicy=Never --set image.tag=latest \\\n    --set appSettings.debug=true --set appSettings.apiKey=$CLOUDTRUTH_API_KEY \\\n    kubetruth ./helm/kubetruth/\n```\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/cloudtruth/kubetruth.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudtruth%2Fkubetruth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudtruth%2Fkubetruth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudtruth%2Fkubetruth/lists"}