From 5709f7105b5ccc3a612c6481650adb3955795638 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 25 Jan 2023 23:48:00 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20documentation=20of=20the=20add?= =?UTF-8?q?=20features?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 551 +++++++++++++++++- tests/.gitignore | 1 + .../expected/sish-client.yaml | 25 + tests/multi-replacement/expected/traefik.yaml | 62 ++ .../functions/multi-transformation.yaml | 74 +++ .../original/sish-client.yaml | 26 + tests/multi-replacement/original/traefik.yaml | 60 ++ .../functions/02_replacement-transformer.yaml | 2 +- tests/test_krmfnbuiltin.sh | 12 +- 9 files changed, 779 insertions(+), 34 deletions(-) create mode 100644 tests/.gitignore create mode 100644 tests/multi-replacement/expected/sish-client.yaml create mode 100644 tests/multi-replacement/expected/traefik.yaml create mode 100644 tests/multi-replacement/functions/multi-transformation.yaml create mode 100644 tests/multi-replacement/original/sish-client.yaml create mode 100644 tests/multi-replacement/original/traefik.yaml diff --git a/README.md b/README.md index b570752..bbea0f0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ krmfnbuiltin is a [kustomize plugin](https://kubectl.docs.kubernetes.io/guides/extending_kustomize/) -that you can use to perform in place transformation in your kustomize projects. +providing a set of [KRM Functions] that you can use to perform in place +transformation in your kustomize projects. @@ -15,6 +16,14 @@ that you can use to perform in place transformation in your kustomize projects.
  • Rationale
  • Usage Example
  • Use of generators
  • +
  • Keeping or deleting generated resources
  • +
  • Extensions + +
  • Installation
  • Argo CD integration
  • Related projects
  • @@ -25,20 +34,21 @@ that you can use to perform in place transformation in your kustomize projects. ## Rationale `kustomize fn run` allows performing _in place_ transformation of KRM -(kubernetes Resource Model) resources. This is handy to perform modification -operations on GitOps repositories (see the [functions tutorial]). Unfortunately, -the builtin transformers are not available to `kustomize fn run`, as it expects -a `container` or `exec` annotation in the transformer resource pointing to a krm -function docker image or executable. +(Kubernetes Resource Model) resources. This is handy to perform structured +modification operations on GitOps repositories (aka _shift left_, see the +[functions tutorial] and the [KRM Functions Specification][krm functions]). +Unfortunately, the builtin transformers are not available to `kustomize fn run`, +as it expects the function to be contained in an external `container` or +`exec`utable . `krmfnbuiltin` provides both the image and executable allowing the use of any -builtin transformer or generator. +kustomize builtin transformer or generator, along with some additional goodies. ## Usage Example -Let's imagine that you have a GitOps repository containing in the `applications` -folder a list of **10** Argo CD applications. The following is the manifest for -one of them: +Let's imagine that you have a GitOps repository containing **10** Argo CD +applications in the `applications` folder. The following is the manifest for one +of them: ```yaml apiVersion: argoproj.io/v1alpha1 @@ -80,14 +90,14 @@ source: ``` Let's imagine now that you want to fork this repository for developing on -another cluster. Now you get a new repository, +another cluster. You obtain a new repository, `https://github.com/myname/autocloud.git`, on which you create a branch named `feature/experiment` for development. For the deployment to the development cluster to use the right repository and branch, you need to change `repoURL` and `targetRevision` for all the applications. You can do that by hand, but this is -**error prone**. +cumbersome and **error prone**. -This is where KRM functions shine. on a Kustomization, you would have done: +On a Kustomization, you would have done: ```yaml patches: @@ -107,8 +117,9 @@ patches: ``` But here you don't want to add a new kustomization nesting level. You just want -to modify the actual application manifests on your branch. To do that, you can -write a function: +to modify the actual application manifests on your branch. This is where KRM +functions shine. To do that, you can write a function file in a `functions` +directory: ```yaml # functions/fn-change-repo-and-branch.yaml @@ -122,7 +133,7 @@ metadata: path: krmfnbuiltin # Can also be: # container: - # image: ghcr.io/kaweezle/krmfnbuiltin:v0.0.2 + # image: ghcr.io/kaweezle/krmfnbuiltin:v0.2.0 patch: |- - op: replace path: /spec/source/repoURL @@ -138,7 +149,7 @@ target: annotationSelector: "autocloud/local-application=true" ``` -And then you can apply your modification with the following: +And then you can apply your modification with the following command: ```console > kustomize fn run --enable-exec --fn-path functions applications @@ -160,6 +171,9 @@ applications. ## Use of generators +`krmfnbuiltin` provides all the +[builtin generators](https://kubectl.docs.kubernetes.io/references/kustomize/builtins/). + Let's imagine that one or more of your applications use an Helm chart that in turn creates applications. You pass the repo URL and target branch as values to the Helm Chart with the following: @@ -227,7 +241,7 @@ metadata: namespace: argocd annotations: # Put this annotation in the last transformation to remove generated resources - config.kubernetes.io/prune-local: "true" + config.kaweezle.com/prune-local: "true" config.kubernetes.io/function: | exec: path: krmfnbuiltin @@ -257,15 +271,18 @@ replacements: Some remarks: -- ✔️ The actual values (repo url and revision) are only specified once. -- ✔️ `spec.source.helm.parameters.[name=common.repoURL].value` is path more - specific than `/spec/source/helm/parameters/1/value`. +- ✔️ The actual values (repo url and revision) are only specified once in the + config map generator. +- ✔️ `spec.source.helm.parameters.[name=common.repoURL].value` is a path more + specific than `/spec/source/helm/parameters/1/value`. The transformation would + survive reordering. - ✔️ The functions file names are prefixed with a number prefix (`01_`, `02_`) - in order to ensure that the functions are executed in the right order. + in order to ensure that the functions are executed in the right order. Note + that you can group the two functions in one file separated by `---`. - ✔️ In the last transformation, we add the following annotation: ```yaml - config.kubernetes.io/prune-local: "true" + config.kaweezle.com/prune-local: "true" ``` In order to avoid saving the generated resources. This is due to an issue in @@ -273,9 +290,476 @@ Some remarks: `config.kubernetes.io/local-config` in the case you are using `kustomize fn run` (although it works with `kustomize build`). -As a convenience, for this specific use case, we have added a -`GitConfigMapGenerator` that automatically adds the relevant resources, while -some people may consider this overkill. +## Keeping or deleting generated resources + +As said above, generated resources are saved by default beside being marked with +the `config.kubernetes.io/local-config` annotation. To prevent that, adding: + +```yaml +config.kaweezle.com/prune-local: "true" +``` + +On the last transformation will remove those resources. If the annotation is not +present, all the generated resources will be saved in a file named +`.generated.yaml` located in the configuration directory. You may want to add +this file name to your `.gitignore` file in order to avoid committing it. + +In some cases however, we want to _inject_ new resources in the configuration. +This can be done by adding the following annotations to the generator: + +- `config.kaweezle.com/keep-local` prevents the deletion of the resource when + reaching the transformation annotated with `config.kaweezle.com/prune-local`. +- `config.kaweezle.com/path` allows specifying the filename of the saved file. +- `config.kaweezle.com/index` allows specifying the position of the resource in + the file. + +Example: + +```yaml +apiVersion: builtin +kind: ConfigMapGenerator +metadata: + name: configuration-map + annotations: + config.kaweezle.com/keep-local: "true" + config.kaweezle.com/path: local-config.yaml + config.kubernetes.io/function: | + exec: + path: krmfnbuiltin +``` + +With these annotations, the generated config map will be saved in the +`local-config.yaml` file in the configuration directory. + +## Extensions + +### ConfigMap generator with git properties + +`GitConfigMapGenerator` work identically to `ConfigMapGenerator` except it adds +two properties of the current git repository to the generated config map: + +- `repoURL` contains the URL or the remote specified by `remoteName`. by + default, it takes the URL of the remote named `origin`. +- `targetRevision` contains the name of the current branch. + +This generator is useful in transformations that use those values, like for +instance Argo CD application customization. Information about the configuration +of the generator can be found in the [ConfigMapGenerator kustomize +documentation]. + +The following function configuration: + +```yaml +# 01_configmap-generator.yaml +apiVersion: builtin +kind: GitConfigMapGenerator +metadata: + name: configuration-map + annotations: + config.kubernetes.io/function: | + exec: + path: krmfnbuiltin +remoteName: origin # default +``` + +produces the following config map (comments mine): + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: configuration-map + namespace: argocd + annotations: + # add config.kaweezle.com/prune-local: "true" to last transformer to remove + config.kubernetes.io/local-config: "true" + # Add .generated.yaml to .gitignore to avoid mistakes + internal.config.kubernetes.io/path: .generated.yaml + config.kubernetes.io/path: .generated.yaml +data: + repoURL: git@github.com:kaweezle/krmfnbuiltin.git + targetRevision: feature/extended-replacement-transformer +``` + +### Heredoc generator + +Using `ConfigMapGenerator` to _inject_ values in the transformation is fine but +has some limitations, due to its _flat nature_. It cannot be used for _object_ +replacement and it's difficult to organize replacement variables. For object +replacement, you can use `PatchStrategicMergeTransformer` but then you loose the +`ReplacementTransformer` advantage of using the same source for several targets. + +`krmfnbuiltin` allows injecting any KRM resource in the transformation. Just add +the `config.kaweezle.com/inject-local: "true"` annotation. For instance: + +```yaml +apiVersion: builtin +kind: LocalConfiguration +metadata: + name: traefik-customization + annotations: + # This will inject this resource. like a ConfigMapGenerator, but with hierarchical + # properties + config.kaweezle.com/inject-local: "true" + config.kubernetes.io/function: | + exec: + path: krmfnbuiltin +data: + # kustomization + traefik: + dashboard_enabled: true + expose: true + sish: + # New properties + server: target.link + hostname: myhost.target.link + host_key: AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAID+4/eqtPTLC18TE8ZP7NeF4ZP68/wnY2d7mhH/KVs79AAAABHNzaDo= +``` + +When the function configuration contains the `config.kaweezle.com/inject-local`, +annotation, `krmfnbuiltin` bypasses the generation/transformation process for +this function and return the content of the function config _as if_ it had been +generated. Its content can then be used in the following transformations, in +particular in replacements, and be deleted by the last transformation (with the +help of the `config.kaweezle.com/prune-local` annotation). + +This injection mechanism, along with the `config.kaweezle.com/keep-local` +annotation (see +[Keeping or deleting generated resources](#keeping-or-deleting-generated-resources)) +allows adding new resources to an existing configuration. + +### Extended replacement in structured content + +The `ReplacementTransformer` provided in `krmfnbuiltin` is _extended_ compared +to the standard one because it allows structured replacements in properties +containing a string representation of some structured content. It currently +supports the following structured formats: + +- YAML +- JSON +- TOML +- INI + +It also provides helpers for changing content in base64 encoded properties as +well as a simple regexp based replacer for edge cases. The standard +configuration of the transformer can be found in the [replacements kustomize +documentation]. + +The typical use case for this is when you have an Argo CD application using a +Helm chart as source with some custom values: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: traefik + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: traefik + server: https://kubernetes.default.svc + project: default + source: + chart: traefik + repoURL: https://helm.traefik.io/traefik + targetRevision: "10.19.5" + helm: + parameters: [] + values: |- + ingressClass: + enabled: true + isDefaultClass: true + ingressRoute: + dashboard: + enabled: false + providers: + kubernetesCRD: + allowCrossNamespace: true + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true + publishedService: + enabled: true + logs: + general: + level: ERROR + access: + enabled: true + tracing: + instana: false + gobalArguments: {} + # BEWARE: use only for debugging + additionalArguments: + - --api.insecure=false + ports: + # BEWARE: use only for debugging + # traefik: + # expose: false + web: + redirectTo: websecure + websecure: + tls: + enabled: true + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + ignoreDifferences: [] +``` + +And that you want your KRM function to personalize the values of the Helm chart. +What you would want is having your replacement path _follow inside_ the values +property by specifying: + +```yaml +- spec.source.helm.values..ingressRoute.dashboard.enabled +``` + +This is not possible with the standard `ReplacementTransformer`, but this is is +possible with the one provided by `krmfnbuiltin`. Consider the following +function configurations: + +```yaml +# fn-traefik-customization.yaml +apiVersion: builtin +kind: LocalConfiguration +metadata: + name: traefik-customization + annotations: + # This will inject this resource. like a ConfigMapGenerator, but with hierarchical + # properties + config.kaweezle.com/inject-local: "true" + config.kubernetes.io/function: | + exec: + path: krmfnbuiltin +data: + # kustomization + traefik: + dashboard_enabled: true + expose: true +--- +apiVersion: builtin +kind: ReplacementTransformer +metadata: + name: replacement-transformer + annotations: + # remove LocalConfiguration after + config.kaweezle.com/prune-local: "true" + config.kubernetes.io/function: | + exec: + path: krmfnbuiltin +replacements: + - source: + kind: LocalConfiguration + fieldPath: data.traefik.dashboard_enabled + targets: + - select: + kind: Application + name: traefik + fieldPaths: + # !!yaml tells the transformer that the property contains YAML + - spec.source.helm.values.!!yaml.ingressRoute.dashboard.enabled + - source: + kind: LocalConfiguration + fieldPath: data.traefik.expose + targets: + - select: + kind: Application + name: traefik + fieldPaths: + - spec.source.helm.values.!!yaml.ports.traefik.expose +``` + +If you apply this to the directory containing the application, you will obtain a +new application: + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: traefik + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io + annotations: + config.kubernetes.io/path: traefik.yaml + internal.config.kubernetes.io/path: traefik.yaml +spec: + destination: + namespace: traefik + server: https://kubernetes.default.svc + project: default + source: + chart: traefik + helm: + parameters: [] + values: | + ... + ingressRoute: + dashboard: + enabled: true + ... + ports: + # BEWARE: use only for debugging + # traefik: + # expose: false + web: + redirectTo: websecure + websecure: + tls: + enabled: true + traefik: + expose: true + repoURL: https://helm.traefik.io/traefik + targetRevision: "10.19.5" + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + ignoreDifferences: [] +``` + +As you can see, inside the `values` property, the yaml has been modified. +`ingressRoute.dashboard.enabled` is now `true` and `port.traefik.expose` is also +`true`. Notice that this last property, also present as a comment, has been +inserted at the end of the `ports` section. + +Now for a more _extreme_ use case involving regular expressions, imagine you +have the following configuration map defining two files: + +```yaml +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: sish-client + namespace: traefik + labels: + app.kubernetes.io/name: "sish-client" + app.kubernetes.io/component: edge + app.kubernetes.io/part-of: autocloud +data: + # ~/.ssh/config file + config: | + PubkeyAcceptedKeyTypes +ssh-rsa + Host sishserver + HostName holepunch.in + Port 2222 + BatchMode yes + IdentityFile ~/.ssh_keys/id_rsa + IdentitiesOnly yes + LogLevel ERROR + ServerAliveInterval 10 + ServerAliveCountMax 2 + RemoteCommand sni-proxy=true + RemoteForward citest.holepunch.in:443 traefik.traefik.svc:443 + # ~/.ssh/known_hosts with the server key + known_hosts: | + [holepunch.in]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+3abW2y3T5dodnI5O1Z/2KlIdH3bwnbGDvCFf13zlh +``` + +And imagine you want to modify it to access a different server on another domain +name. You need to change: + +- `HostName` in `~/.ssh/config` from `holepunch.in` to the new server address. +- `RemoteForward` in `~/.ssh/config` by changing the address forwarded from + `citest.holepunch.in` to the new address. +- In `~/.ssh/known_hosts` the name of the host and the key fingerprint of the + new server. + +You can do this by hand, but you may forget something now and the next time. +This is where the regexp transformer comes into play with the following +configuration: + +```yaml +apiVersion: builtin +kind: LocalConfiguration +metadata: + name: configuration-map + annotations: + config.kaweezle.com/inject-local: "true" + config.kubernetes.io/function: | + exec: + path: ../../krmfnbuiltin +data: + sish: + # New properties + server: target.link + hostname: myhost.target.link + host_key: AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAID+4/eqtPTLC18TE8ZP7NeF4ZP68/wnY2d7mhH/KVs79AAAABHNzaDo= +--- +apiVersion: builtin +kind: ReplacementTransformer +metadata: + name: replacement-transformer + annotations: + config.kaweezle.com/prune-local: "true" + config.kubernetes.io/function: | + exec: + path: ../../krmfnbuiltin +replacements: + - source: + kind: LocalConfiguration + fieldPath: data.sish.server + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.config.!!regex.^\s+HostName\s+(\S+)\s*$.1 + - data.known_hosts.!!regex.^\[(\S+)\].1 + - source: + kind: LocalConfiguration + fieldPath: data.sish.hostname + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.config.!!regex.^\s+RemoteForward\s+(\S+):.1 + - source: + kind: LocalConfiguration + fieldPath: data.sish.host_key + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.known_hosts.!!regex.ssh-ed25519\s(\S+).1 +``` + +The _path_ after `!!regex` is composed of two elements. The first one is the +regexp to match. The second one is the the capture group that needs to be +replaced with the source. In the first replacement, the regexp: + +```regexp +^\s+HostName\s+(\S+)\s*$ +``` + +can be interpreted as: + +> a line starting with one or more spaces followed by `HostName`, then one or +> more spaces and a sequence of non space characters, captured as a group; then +> optional spaces till the end of the line. + +The second part of the path, `1`, tells to replace the first capturing group +with the source. With the above, the line: + +```sshconfig + HostName holepunch.in +``` + +will become + +```sshconfig + HostName target.link +``` ## Installation @@ -284,14 +768,15 @@ provide binaries for most platforms as well as Alpine based packages. Typically, you would install it on linux with the following command: ```console -> KRMFNBUILTIN_VERSION="v0.1.0" +> KRMFNBUILTIN_VERSION="v0.2.0" > curl -sLo /usr/local/bin/krmfnbuiltin https://github.com/kaweezle/krmfnbuiltin/releases/download/${KRMFNBUILTIN_VERSION}/krmfnbuiltin_${KRMFNBUILTIN_VERSION}_linux_amd64 ``` ## Argo CD integration `krmfnbuiltin` is **NOT** primarily meant to be used inside Argo CD, but instead -to perform _structural_ modifications to the source **BEFORE** the commit. +to perform _structural_ modifications to the configuration **BEFORE** it's +committed and provided to GitOps. Anyway, to use `krmfnbuiltin` with Argo CD, you need to: @@ -312,7 +797,7 @@ summarize: ```Dockerfile FROM argoproj/argocd:latest -ARG KRMFNBUILTIN_VERSION=v0.1.0 +ARG KRMFNBUILTIN_VERSION=v0.2.0 # Switch to root for the ability to perform install USER root @@ -352,9 +837,17 @@ new configuration after transformation. While it has not been tested, krmfnbuiltin should work with [kpt]. +[knot8] lenses have provided the idea of extended paths. + +[KRM Functions]: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md [kpt]: https://kpt.dev/guides/rationale [functions tutorial]: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/tutorials/function-basics.md +[knot8]: https://knot8.io/ +[ConfigMapGenerator kustomize documentation]: + https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#_configmapgenerator_ +[replacements kustomize documentation]: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/replacements/ + diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..6109723 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +applications/ diff --git a/tests/multi-replacement/expected/sish-client.yaml b/tests/multi-replacement/expected/sish-client.yaml new file mode 100644 index 0000000..885cb26 --- /dev/null +++ b/tests/multi-replacement/expected/sish-client.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: sish-client + namespace: traefik + labels: + app.kubernetes.io/name: "sish-client" + app.kubernetes.io/component: edge + app.kubernetes.io/part-of: autocloud +data: + config: | + PubkeyAcceptedKeyTypes +ssh-rsa + Host sishserver + HostName target.link + Port 2222 + BatchMode yes + IdentityFile ~/.ssh_keys/id_rsa + IdentitiesOnly yes + LogLevel ERROR + ServerAliveInterval 10 + ServerAliveCountMax 2 + RemoteCommand sni-proxy=true + RemoteForward myhost.target.link:443 traefik.traefik.svc:443 + known_hosts: | + [target.link]:2222 ssh-ed25519 AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAID+4/eqtPTLC18TE8ZP7NeF4ZP68/wnY2d7mhH/KVs79AAAABHNzaDo= diff --git a/tests/multi-replacement/expected/traefik.yaml b/tests/multi-replacement/expected/traefik.yaml new file mode 100644 index 0000000..65073ae --- /dev/null +++ b/tests/multi-replacement/expected/traefik.yaml @@ -0,0 +1,62 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: traefik + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: traefik + server: https://kubernetes.default.svc + project: default + source: + chart: traefik + helm: + parameters: [] + values: | + ingressClass: + enabled: true + isDefaultClass: true + ingressRoute: + dashboard: + enabled: true + providers: + kubernetesCRD: + allowCrossNamespace: true + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true + publishedService: + enabled: true + logs: + general: + level: ERROR + access: + enabled: true + tracing: + instana: false + gobalArguments: {} + # BEWARE: use only for debugging + additionalArguments: + - --api.insecure=false + ports: + # BEWARE: use only for debugging + # traefik: + # expose: false + web: + redirectTo: websecure + websecure: + tls: + enabled: true + traefik: + expose: true + repoURL: https://helm.traefik.io/traefik + targetRevision: "10.19.5" + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + ignoreDifferences: [] diff --git a/tests/multi-replacement/functions/multi-transformation.yaml b/tests/multi-replacement/functions/multi-transformation.yaml new file mode 100644 index 0000000..a29ede4 --- /dev/null +++ b/tests/multi-replacement/functions/multi-transformation.yaml @@ -0,0 +1,74 @@ +apiVersion: builtin +kind: LocalConfiguration +metadata: + name: configuration-map + annotations: + config.kaweezle.com/inject-local: "true" + config.kubernetes.io/function: | + exec: + path: ../../krmfnbuiltin +data: + sish: + server: target.link + hostname: myhost.target.link + host_key: AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAID+4/eqtPTLC18TE8ZP7NeF4ZP68/wnY2d7mhH/KVs79AAAABHNzaDo= + traefik: + dashboard_enabled: true + expose: true +--- +apiVersion: builtin +kind: ReplacementTransformer +metadata: + name: replacement-transformer + annotations: + config.kubernetes.io/prune-local: "true" + config.kubernetes.io/function: | + exec: + path: ../../krmfnbuiltin +replacements: + - source: + kind: LocalConfiguration + fieldPath: data.sish.server + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.config.!!regex.^\s+HostName\s+(\S+)\s*$.1 + - data.known_hosts.!!regex.^\[(\S+)\].1 + - source: + kind: LocalConfiguration + fieldPath: data.sish.hostname + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.config.!!regex.^\s+RemoteForward\s+(\S+):.1 + - source: + kind: LocalConfiguration + fieldPath: data.sish.host_key + targets: + - select: + kind: ConfigMap + name: sish-client + fieldPaths: + - data.known_hosts.!!regex.ssh-ed25519\s(\S+).1 + - source: + kind: LocalConfiguration + fieldPath: data.traefik.dashboard_enabled + targets: + - select: + kind: Application + name: traefik + fieldPaths: + - spec.source.helm.values.!!yaml.ingressRoute.dashboard.enabled + - source: + kind: LocalConfiguration + fieldPath: data.traefik.expose + targets: + - select: + kind: Application + name: traefik + fieldPaths: + - spec.source.helm.values.!!yaml.ports.traefik.expose diff --git a/tests/multi-replacement/original/sish-client.yaml b/tests/multi-replacement/original/sish-client.yaml new file mode 100644 index 0000000..8ea4619 --- /dev/null +++ b/tests/multi-replacement/original/sish-client.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: sish-client + namespace: traefik + labels: + app.kubernetes.io/name: "sish-client" + app.kubernetes.io/component: edge + app.kubernetes.io/part-of: autocloud +data: + config: | + PubkeyAcceptedKeyTypes +ssh-rsa + Host sishserver + HostName holepunch.in + Port 2222 + BatchMode yes + IdentityFile ~/.ssh_keys/id_rsa + IdentitiesOnly yes + LogLevel ERROR + ServerAliveInterval 10 + ServerAliveCountMax 2 + RemoteCommand sni-proxy=true + RemoteForward citest.holepunch.in:443 traefik.traefik.svc:443 + known_hosts: | + [holepunch.in]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+3abW2y3T5dodnI5O1Z/2KlIdH3bwnbGDvCFf13zlh diff --git a/tests/multi-replacement/original/traefik.yaml b/tests/multi-replacement/original/traefik.yaml new file mode 100644 index 0000000..4d40f31 --- /dev/null +++ b/tests/multi-replacement/original/traefik.yaml @@ -0,0 +1,60 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: traefik + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + destination: + namespace: traefik + server: https://kubernetes.default.svc + project: default + source: + chart: traefik + helm: + parameters: [] + values: |- + ingressClass: + enabled: true + isDefaultClass: true + ingressRoute: + dashboard: + enabled: false + providers: + kubernetesCRD: + allowCrossNamespace: true + allowExternalNameServices: true + kubernetesIngress: + allowExternalNameServices: true + publishedService: + enabled: true + logs: + general: + level: ERROR + access: + enabled: true + tracing: + instana: false + gobalArguments: {} + # BEWARE: use only for debugging + additionalArguments: + - --api.insecure=false + ports: + # BEWARE: use only for debugging + # traefik: + # expose: false + web: + redirectTo: websecure + websecure: + tls: + enabled: true + repoURL: https://helm.traefik.io/traefik + targetRevision: "10.19.5" + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + ignoreDifferences: [] diff --git a/tests/replacement/functions/02_replacement-transformer.yaml b/tests/replacement/functions/02_replacement-transformer.yaml index 1f56b17..264810f 100644 --- a/tests/replacement/functions/02_replacement-transformer.yaml +++ b/tests/replacement/functions/02_replacement-transformer.yaml @@ -4,7 +4,7 @@ metadata: name: replacement-transformer namespace: argocd annotations: - config.kubernetes.io/prune-local: "true" + config.kaweezle.com/prune-local: "true" config.kubernetes.io/function: | exec: path: ../../krmfnbuiltin diff --git a/tests/test_krmfnbuiltin.sh b/tests/test_krmfnbuiltin.sh index ff78ecb..cf90fd7 100755 --- a/tests/test_krmfnbuiltin.sh +++ b/tests/test_krmfnbuiltin.sh @@ -7,16 +7,20 @@ #set -uexo pipefail set -e pipefail -trap "rm -rf {patch,replacement}/applications" EXIT +trap "find . -type d -name 'applications' -exec rm -rf {} +" EXIT -for d in patch replacement; do +for d in $(ls -d */); do echo "Running Test in $d..." cd $d - rm -rf appllications + rm -rf applications cp -r original applications + echo " > Performing kustomizations..." kustomize fn run --enable-exec --fn-path functions applications - diff <(yq eval -P expected/argocd.yaml) <(yq eval -P applications/argocd.yaml) + for f in $(ls -1 expected); do + echo " > Checking $f..." + diff <(yq eval -P expected/$f) <(yq eval -P applications/$f) + done cd .. done echo "Done ok 🎉"