|
| 1 | +--- |
| 2 | +date: 2024-02-15 |
| 3 | +title: Kyverno Chainsaw 0.1.4 - Awesome new features! |
| 4 | +linkTitle: Kyverno Chainsaw 0.1.4 - Awesome new features |
| 5 | +author: Charles-Edouard Brétéché |
| 6 | +description: What's new in chainsaw v0.1.4! |
| 7 | +--- |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +The [latest release of Kyverno Chainsaw](https://github.com/kyverno/chainsaw/releases/tag/v0.1.4) came out yesterday. Let's look at the new features included in this release. |
| 12 | + |
| 13 | +- Resource diff in assertion failures |
| 14 | +- Resource templating support |
| 15 | + |
| 16 | +## Resource diff in assertion failures |
| 17 | + |
| 18 | +This is a relatively straightforward one but it brings a lot of context to assertion failures. |
| 19 | + |
| 20 | +Suppose an assertion fails, before `v0.1.4` the output would have looked like this: |
| 21 | + |
| 22 | +```sh |
| 23 | + | 09:52:19 | deployment | step-1 | ASSERT | RUN | v1/Pod @ chainsaw-full-llama/* |
| 24 | + | 09:52:49 | deployment | step-1 | ASSERT | ERROR | v1/Pod @ chainsaw-full-llama/* |
| 25 | + === ERROR |
| 26 | + v1/Pod/chainsaw-full-llama/example-5477b4ff8c-vrzs8 - metadata.annotations.foo: Invalid value: "null": Expected value: "bar" |
| 27 | + | 09:52:49 | deployment | step-1 | TRY | DONE | |
| 28 | +``` |
| 29 | + |
| 30 | +While the message contains a description of the failure (`metadata.annotations.foo: Invalid value: "null": Expected value: "bar"`) and the offending resource (`v1/Pod/chainsaw-full-llama/example-5477b4ff8c-vrzs8`), it's not easy to understand where the resource comes from. |
| 31 | + |
| 32 | +The same error in `v0.1.4` will be reported including a resource diff: |
| 33 | + |
| 34 | +```sh |
| 35 | + | 09:55:50 | deployment | step-1 | ASSERT | RUN | v1/Pod @ chainsaw-rare-liger/* |
| 36 | + | 09:56:20 | deployment | step-1 | ASSERT | ERROR | v1/Pod @ chainsaw-rare-liger/* |
| 37 | + === ERROR |
| 38 | + --------------------------------------------------- |
| 39 | + v1/Pod/chainsaw-rare-liger/example-5477b4ff8c-tnhd9 |
| 40 | + --------------------------------------------------- |
| 41 | + * metadata.annotations.foo: Invalid value: "null": Expected value: "bar" |
| 42 | + |
| 43 | + --- expected |
| 44 | + +++ actual |
| 45 | + @@ -1,10 +1,16 @@ |
| 46 | + apiVersion: v1 |
| 47 | + kind: Pod |
| 48 | + metadata: |
| 49 | + - annotations: |
| 50 | + - foo: bar |
| 51 | + labels: |
| 52 | + app: nginx |
| 53 | + + name: example-5477b4ff8c-tnhd9 |
| 54 | + namespace: chainsaw-rare-liger |
| 55 | + + ownerReferences: |
| 56 | + + - apiVersion: apps/v1 |
| 57 | + + blockOwnerDeletion: true |
| 58 | + + controller: true |
| 59 | + + kind: ReplicaSet |
| 60 | + + name: example-5477b4ff8c |
| 61 | + + uid: 118abe16-ec42-4894-83db-64479c4aac6f |
| 62 | + spec: {} |
| 63 | + | 09:56:20 | deployment | step-1 | TRY | DONE | |
| 64 | +``` |
| 65 | + |
| 66 | +The additional diff now gives a lot more context about the offending resource. Showing the `ownerReferences` field tells us who is responsible for the resource existence. |
| 67 | + |
| 68 | +The diff complements complex assertion failures (`metadata.annotations.foo: Invalid value: "null": Expected value: "bar"`) to provide everything needed to get a solid understanding of what failed in an assertion operation. |
| 69 | + |
| 70 | +Thank you [vfarcic](https://github.com/vfarcic) for the [feature request](https://github.com/kyverno/chainsaw/issues/775). |
| 71 | + |
| 72 | +## Resource templating support |
| 73 | + |
| 74 | +This second new feature is probably a game changer in the e2e testing tools ecosystem. |
| 75 | + |
| 76 | +Anyone serious with e2e testing faced this issue at least once. How can I make my resource manifest slightly different, depending on the test being executed? |
| 77 | + |
| 78 | +Without resource templating, we always end up using workarounds like templating in a pre-processing step or relying on scripts invoking `envsubst` with a bunch of environment variables to perform substitutions. Those workarounds are error-prone, often limiting, and hard to maintain |
| 79 | + |
| 80 | +Chainsaw `v0.1.4` now offers a better solution for that, thanks to resource templating! |
| 81 | + |
| 82 | +### Bad example (before chainsaw v0.1.4) |
| 83 | + |
| 84 | +Suppose you want to create a resource having a field that must be set to the URL of a service. This URL will be different depending on the namespace the service is installed in. |
| 85 | + |
| 86 | +Without resource templating, this could be done with something like this. |
| 87 | + |
| 88 | +Given the resource below: |
| 89 | + |
| 90 | +```yaml |
| 91 | +apiVersion: metrics.keptn.sh/v1beta1 |
| 92 | +kind: KeptnMetricsProvider |
| 93 | +metadata: |
| 94 | + name: my-mocked-provider |
| 95 | +spec: |
| 96 | + type: prometheus |
| 97 | + targetServer: "http://mockserver.$NAMESPACE.svc.cluster.local:1080" |
| 98 | +``` |
| 99 | +
|
| 100 | +We can use a script to perform namespace substitution with `envsubst` and pipe the result to `kubectl`: |
| 101 | + |
| 102 | +```yaml |
| 103 | +apiVersion: chainsaw.kyverno.io/v1alpha1 |
| 104 | +kind: Test |
| 105 | +metadata: |
| 106 | + name: example |
| 107 | +spec: |
| 108 | + steps: |
| 109 | + - try: |
| 110 | + - script: |
| 111 | + content: | |
| 112 | + envsubst < resource.yaml | kubectl apply -f - -n $NAMESPACE |
| 113 | +``` |
| 114 | + |
| 115 | +This is bad because Chainsaw doesn't know anything about this resource and won't be able to clean it up when tearing down the test. |
| 116 | + |
| 117 | +### Good example (the chainsaw v0.1.4 way) |
| 118 | + |
| 119 | +With resource templating this can become a regular `apply` operation, Chainsaw will now have full knowledge of the created resource. |
| 120 | + |
| 121 | +The resource can embed complex expressions as demonstrated below: |
| 122 | + |
| 123 | +```yaml |
| 124 | +apiVersion: metrics.keptn.sh/v1beta1 |
| 125 | +kind: KeptnMetricsProvider |
| 126 | +metadata: |
| 127 | + name: my-mocked-provider |
| 128 | +spec: |
| 129 | + type: prometheus |
| 130 | + # `targetServer` is configured using a complex jmespath expression |
| 131 | + targetServer: (join('.', ['http://mockserver', $namespace, 'svc.cluster.local:1080'])) |
| 132 | +``` |
| 133 | +
|
| 134 | +The resource definition above can be used in a regular `apply` operation: |
| 135 | + |
| 136 | +```yaml |
| 137 | +apiVersion: chainsaw.kyverno.io/v1alpha1 |
| 138 | +kind: Test |
| 139 | +metadata: |
| 140 | + name: example |
| 141 | +spec: |
| 142 | + # enable templating (at the test level) |
| 143 | + template: true |
| 144 | + steps: |
| 145 | + - try: |
| 146 | + - apply: |
| 147 | + # or enable templating (at the operation level) |
| 148 | + template: true |
| 149 | + file: resource.yaml |
| 150 | +``` |
| 151 | + |
| 152 | +### Supported operations |
| 153 | + |
| 154 | +Resource templating is supported in `apply`, `create` and `delete` operations without restriction (provided templating has been enabled at the configuration, test, step or operation level). |
| 155 | + |
| 156 | +Resource templating can also be used in `assert` and `error` operations with some restrictions. Because the content of an `assert` or `error` operation is already an assertion tree, only the elements used for looking up the resources to be processed by the operation will be considered for templating. That is, only `apiVersion`, `kind`, `name`, `namespace` and `labels` are considered for templating. Other fields are not, they are part of the assertion tree. |
| 157 | + |
| 158 | +Last but not least, the same level of templating can be applied to the ephemeral test namespace created by Chainsaw using the `namespaceTemplate` stanza. This can be particularly useful if you need the ephemeral namespace to be annotated or labeled in a certain way: |
| 159 | + |
| 160 | +```yaml |
| 161 | +apiVersion: chainsaw.kyverno.io/v1alpha1 |
| 162 | +kind: Test |
| 163 | +metadata: |
| 164 | + name: example |
| 165 | +spec: |
| 166 | + namespaceTemplate: |
| 167 | + metadata: |
| 168 | + annotations: |
| 169 | + keptn.sh/lifecycle-toolkit: enabled |
| 170 | + steps: |
| 171 | + # ... |
| 172 | +``` |
| 173 | + |
| 174 | +### Credits |
| 175 | + |
| 176 | +Thank you to the [Keptn](https://keptn.sh/) folks, especially [RealAnna](https://github.com/RealAnna) for helping with the design of this feature. |
| 177 | + |
| 178 | +## Conclusion |
| 179 | + |
| 180 | +Those two new features make Chainsaw a lot more flexible and improve usability a lot. |
| 181 | + |
| 182 | +The resource templating opens new testing opportunities. Combined with the capacity to provide arbitrary data to tests with the `--values` flag, Chainsaw offers a very dynamic way to define tests. |
| 183 | + |
| 184 | +Please keep in mind that resource templating is still experimental and could change slightly in future releases. Nonetheless, we encourage everyone to try it out and give us feedback to improve it as much as we can in the next versions. |
| 185 | + |
| 186 | +More infos 👇 |
| 187 | + |
| 188 | +- GitHub: https://github.com/kyverno/chainsaw |
| 189 | +- Docs: https://kyverno.github.io/chainsaw |
| 190 | +- Slack: https://kubernetes.slack.com/archives/C067LUFL43U |
0 commit comments