{"id":17621226,"url":"https://github.com/michaelfig/k8s-copier","last_synced_at":"2025-10-13T13:39:45.684Z","repository":{"id":64302100,"uuid":"184622764","full_name":"michaelfig/k8s-copier","owner":"michaelfig","description":"Kubernetes dynamic resource-to-resource copier","archived":false,"fork":false,"pushed_at":"2019-05-14T20:31:39.000Z","size":13823,"stargazers_count":8,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-13T13:39:45.151Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/michaelfig.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":"2019-05-02T17:26:15.000Z","updated_at":"2024-03-01T07:00:43.000Z","dependencies_parsed_at":"2023-01-15T09:30:38.267Z","dependency_job_id":null,"html_url":"https://github.com/michaelfig/k8s-copier","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/michaelfig/k8s-copier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelfig%2Fk8s-copier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelfig%2Fk8s-copier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelfig%2Fk8s-copier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelfig%2Fk8s-copier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michaelfig","download_url":"https://codeload.github.com/michaelfig/k8s-copier/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelfig%2Fk8s-copier/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279015352,"owners_count":26085684,"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-13T02:00:06.723Z","response_time":61,"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-10-22T20:11:56.835Z","updated_at":"2025-10-13T13:39:45.638Z","avatar_url":"https://github.com/michaelfig.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# K8S-Copier\n\n*NOTE: This project is probably not ready for production, but it does work for my purposes.*\n\nk8s-copier watches and updates specially-annotated Kubernetes resources with values from other resources.  It can also update resources with data specified in the annotation (useful if another controller is regenerating a resource and an override needs to be applied).\n\nThere is a prebuilt [Docker image](https://hub.docker.com/r/michaelfig/k8s-copier).\n\n## Annotations\n\nAnnotations on a target resource (one whose singular or plural form is passed as a `--target=`*RESOURCE* to k8s-copier, with optional appended dot-separated *VERSION* and *GROUP*) can be one of the following:\n\n| Annotation | Value | Description |\n| --- | --- | --- |\n| k8s-copier.fig.org/replace-*DST-PATH* | *RESOURCE*:*INSTANCE*:*SRC-PATH* | Replace *DST-PATH* on the current resource with the contents of *SRC-PATH* from *INSTANCE* (of kind *RESOURCE*) |\n| k8s-copier.fig.org/replace-*DST-PATH* | json:*JSON-STRING* | Replace *DST-PATH* on the current resource with the stringified JSON data *JSON-STRING* |\n\nStrategic merge ([relevant issue](https://github.com/michaelfig/k8s-copier/issues/1)) and JSON Merge Patch ([relevant issue](https://github.com/michaelfig/k8s-copier/issues/2)) annotations are planned, but not yet implemented.  Please add a thumbs-up or note explaining your use case to the relevant issue if the feature would be useful to you.\n\nThe *DST-PATH* and *SRC-PATH* are JSON paths, such as `spec.template.data` or `spec`.\n\nEach *INSTANCE* to copy from can be either a *NAME* (for the current namespace), or *NAMESPACE*`/`*NAME*, such as `my-secret`, or `ns/my-secret`.\n\nThe *RESOURCE* is the singular or plural form of the resource to copy from, with an optional dot-separated *VERSION* and *GROUP* if necessary.  If there is no *VERSION*, k8s-copier will try to discover the *VERSION* and *GROUP*, so *RESOURCE* can be something like `secret` or `deployment` or `deployments.v1beta1.extensions`.\n\n# Kubernetes Federation V2\n\nThe main use case for k8s-copier is to update [Federation v2](https://github.com/kubernetes-sigs/federation-v2) `Federated*` resources with values from the host cluster.\n\n**IMPORTANT: To run any of the following examples, you will first need to label your master cluster (the one which is the synchronization source for the other clusters)!**  This prevents Federation and k8s-copier from flapping when trying to update the same resource.\n\n```\n# kubectl label federatedcluster mymaster cluster-master=true\n```\n\nThis is assuming your master cluster, which has been added with `kubefedctl join` and is also running the Federation control plane, is named `mymaster`.\n\n## Cert-Manager integration\n\nIf you use [cert-manager](https://github.com/jetstack/cert-manager) and you want to update a FederatedSecret with values from a Secret that is created by cert-manager, first make sure that k8s-copier has the `--target=federatedsecret` flag set and the `cluster-master=true` label has been applied as above.\n\nThen, you can do something like this:\n\n```yaml\n---\napiVersion: certmanager.k8s.io/v1alpha1\nkind: Certificate\nmetadata:\n  name: cloud-secret-master\n  namespace: cloud\nspec:\n  acme:\n    config:\n    - dns01:\n        provider: dns\n      domains:\n      - cloud.example.com\n  dnsNames:\n  - cloud.example.com\n  issuerRef:\n    kind: ClusterIssuer\n    name: letsencrypt-prod\n  secretName: cloud-secret-master\n---\napiVersion: types.federation.k8s.io/v1alpha1\nkind: FederatedSecret\nmetadata:\n  name: cloud-secret\n  namespace: cloud\n  annotations:\n    flux.weave.works/ignore: \"true\" # Needed to prevent flapping.\n    # The k8s-copier specification.\n    k8s-copier.fig.org/replace-spec.template.data: \"secret:cloud-secret-master:data\"\nspec:\n  placement:\n    clusterSelector:\n      matchExpressions:\n      # Don't update the master cluster, as cert-manager does that.\n      - key: cluster-master\n        operator: DoesNotExist\n  template:\n    type: kubernetes.io/tls\n    data: \n```\n\nAfter these resources are added, cert-manager should pick up the Certificate and create the Secret named `cloud-secret-master`.  Then, k8s-copier will detect the Secret, and add its\n`data` values to the FederatedSecret's `spec.template.data` path.  Finally, Federation will propagate the FederatedSecret to Secrets in the other clusters.\n\nWhenever the Secret changes (such as when a new Certificate is ordered by cert-manager), the FederatedSecret will also be updated, and Federation will propagate the Secret to the other clusters.\n\n## Flux integration\n\nIf you use [Weave Flux](https://github.com/weaveworks/flux) you can use the following patterns for updating federated workloads with values from a Flux-managed workload.\n\n### Deployment\n\nIf you want to update a FederatedDeployment with values from a Deployment that is managed by Flux, first make sure that k8s-copier has the `--target=federateddeployment` flag set and the `cluster-master=true` label has been applied as above.\n\nThen you can add a Deployment to your Flux GitOps repository:\n\n```yaml\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  annotations:\n    # These are not strictly necessary... you could also update images with fluxctl.\n    flux.weave.works/automated: \"true\"\n    flux.weave.works/tag.my-container: semver:~1.0\n  name: cloud-deployment-master\n  namespace: cloud\nspec:\n  template:\n    spec:\n      containers:\n      - name: my-container\n      # ... whatever you want.\n```\n\nAfter, manually apply the FederatedDeployment (it must not be managed by Flux, or k8s-copier and Flux will flap between updating it):\n\n```yaml\napiVersion: types.federation.k8s.io/v1alpha1\nkind: FederatedDeployment\nmetadata:\n  name: cloud-deployment\n  namespace: cloud\n  annotations:\n    flux.weave.works/ignore: \"true\" # Needed to prevent flapping.\n    # The k8s-copier specification.\n    k8s-copier.fig.org/replace-spec.template.spec: \"deployment:cloud-deployment-master:spec\"\nspec:\n  placement:\n    clusterSelector:\n      matchExpressions:\n      # Don't update the master cluster, as Flux does that.\n      - key: cluster-master\n        operator: DoesNotExist\n```\n\nAfter these resources are added, Flux should manage GitOps changes and update the Deployment named `cloud-deployment-master`.  Then, k8s-copier will detect the Deployment changes, and add its\n`spec` values to the FederatedDeployment's `spec.template.spec` path.  Finally, Federation will propagate the FederatedDeployment to `cloud-deployment` Deployments in the other clusters.\n\nWhenever the `cloud-deployment-master` Deployment changes (such as when Flux detects image changes, or GitOps changes to the Deployment), the FederatedDeployment will also be updated, and Federation will propagate the Deployment to the other clusters.\n\n### HelmRelease\n\nIf you want to update a FederatedHelmRelease with values from a HelmRelease that is managed by Flux (which in turn generates an actual `helm` installation via the `flux-helm-operator`), first enable federation for HelmReleases:\n\n```\n$ kubefedctl enable helmrelease\n```\n\nNext, make sure that k8s-copier has the `--target=federatedhelmrelease` flag set and the `cluster-master=true` label has been applied as above.\n\nThen you can add a HelmRelease to your Flux GitOps repository:\n\n```yaml\napiVersion: flux.weave.works/v1beta1\nkind: HelmRelease\nmetadata:\n  annotations:\n    # These are not strictly necessary... you could also update images with fluxctl.\n    flux.weave.works/automated: \"true\"\n    flux.weave.works/tag.chart-image: semver:~1.0\n  name: cloud-release-master\n  namespace: cloud\nspec:\n  releaseName: cloud-release\n  values:\n    image:\n      repository: example.com/cloud-image\n      tag: 1.0.1\n  # ... whatever you want.\n```\n\nAfter, manually apply the FederatedHelmRelease (it must not be managed by Flux, or k8s-copier and Flux will flap between updating it):\n\n```yaml\napiVersion: types.federation.k8s.io/v1alpha1\nkind: FederatedHelmRelease\nmetadata:\n  name: cloud-release\n  namespace: cloud\n  annotations:\n    flux.weave.works/ignore: \"true\" # Needed to prevent flapping.\n    # The k8s-copier specification.\n    k8s-copier.fig.org/replace-spec.template.spec: \"helmrelease:cloud-release:spec\"\nspec:\n  placement:\n    clusterSelector:\n      matchExpressions:\n      # Don't update the master cluster, as Flux does that.\n      - key: cluster-master\n        operator: DoesNotExist\n  template:\n    spec: # ... Your default spec for the helmrelease\n```\n\nAfter these resources are added, Flux should manage GitOps changes and update the HelmRelease named `cloud-release`.  Then, k8s-copier will detect the HelmRelease changes, and add its\n`spec` values to the FederatedHelmRelease's `spec.template.spec` path.  Finally, Federation will propagate the FederatedHelmRelease to HelmReleases in the other clusters.\n\nWhenever the HelmRelease changes (such as when Flux detects image changes, or GitOps changes to the HelmRelease), the FederatedHelmRelease will also be updated, and Federation will propagate the HelmRelease to the other clusters.\n\n# Acknowledgments\n\nThanks to James Munnelly at [Jetstack](https://www.jetstack.io/) for starting me in the direction of creating an orthogonal controller, rather than patching [cert-manager](https://github.com/jetstack/cert-manager) and [Weave Flux](https://github.com/weaveworks/flux).\n\nMichael FIG \u003cmichael+k8s-copier@fig.org\u003e, 2019-05-02\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelfig%2Fk8s-copier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichaelfig%2Fk8s-copier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelfig%2Fk8s-copier/lists"}