-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sprig Templating for Helm Values with Inputs from Cluster Resource #671
Conversation
61cb346
to
418dd05
Compare
pkg/target/target.go
Outdated
return nil, err | ||
} | ||
|
||
tpl, err := template.New("values").Funcs(tplFuncMap()).Option("missingkey=error").Parse(string(valuesMapStr)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm getting an error from the test suite when I started adding some longer lines to the test suite for variable substitution.
Here is the tested bundleYamlWithTemplate I was playing around with.
const bundleYamlWithTemplate = `namespace: default
helm:
releaseName: labels
values:
clusterName: "{{ .ClusterLabels.name }}"
fromAnnotation: "{{ .ClusterAnnotations.testAnnotation }}"
clusterNamespace: "{{ .ClusterNamespace }}"
fleetClusterName: "{{ .ClusterName }}"
workingLongClusterName: kubernets.io/cluster/{{ index .ClusterLabels "p-w" }}
brokenLongClusterName: kubernets.io/cluster/{{ index .ClusterLabels "not-working-for-some-reason" }}
customStruct:
- name: "{{ .Values.topLevel }}"
key1: value1
key2: value2
- element2: "{{ .Values.nested.secondTier.thirdTier }}"
- "element3_{{ .ClusterLabels.envType }}": "{{ .ClusterLabels.name }}"
funcs:
upper: "{{ .Values.topLevel | upper }}_test"
join: '{{ .Values.list | join "," }}'
diff:
comparePatches:
- apiVersion: networking.k8s.io/v1
kind: Ingress
name: labels-fleetlabelsdemo
namespace: default
operations:
- op: remove
path: /spec/rules/0/host
`
And here is the error I'm getting from my brokenLongClusterName: kubernets.io/cluster/{{ index .ClusterLabels "not-working-for-some-reason" }}
line.
--- FAIL: TestProcessTemplateValues (0.00s)
/home/gate/src/fleet/pkg/target/target_test.go:179: error during label processing template: values:1: unclosed action
FAIL
I've done a bit of digging and it appears to have something to do with the k8syam.Marshal conversion to a string. New lines are getting inserted into the line. So brokenLongClusterName: kubernets.io/cluster/{{ index .ClusterLabels "not-working-for-some-reason" }}
will end up like brokenLongClusterName: kubernets.io/cluster/{{ index .ClusterLabels "not-working-for-some-reason"\n }}
. I have not been able to explain why the new lines are getting inserted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kubernetes-sigs/yaml#68 has details about what is happening with lines over 80 chars. I can confirm using go-yaml v3 instead of the k8s sigs yaml library resolves the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an interesting catch. I will update the library and see if that will fix it. However, fundamentally, this issue is raised by the fact that I serialize the entire document and re-parse it as template string. Looking back at it, I can't help it but feel a little bit unhappy about this approach because a carefully crafted template variable could fundamentally change the yaml structure of the templated output. Perhaps a better approach would be to iterate on each individual key values and template them as strings instead. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really liked the idea of treating all of the values as a big template so you can start to do some fun if/then logic and not try to cram it all on one line. But this 80 char line break in the yaml libraries breaks that. My current use case is better variable substitute and not doing crazy logic inside the values so I'm happy with each line getting process separately like I'm doing in #507.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. That's what convinced me to consider it. However, an alternative approach would be to define a dedicated field in fleet.yaml like templatedValues:
and let the user define it as a multi-line string. This way it is implied that the entire structure is templated as a whole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interestingly enough, I couldn't reproduce the new line behaviour on my local system (go 1.17.6) -- but I switched to goyamlv3 just to be safe. I also refactored the templating function to be a lot more "structure" safe, as in only templating within the context of a specific string rather than the entire object.
ddb4e5e
to
b191284
Compare
f4e269e
to
d2fd7ae
Compare
@gregsidelinger in case you're interested I am planning to propose an enhancement on top of this templating system to introduce secret management via vals. I have a PR here with a basic implementation, docs pending. IMO this gives an elegant way to template and as well as resolve secrets per release/cluster basis. |
docs/gitrepo-structure.md
Outdated
key: values.yaml | ||
secretKeyRef: | ||
name: secret-values | ||
namespace: default | ||
key: values.yaml | ||
# Override immutable resources. This could be dangerous. | ||
force: false | ||
# Disable go template pre-prosessing on the fleet values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo pre-processing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@rajiteh I am not clear on how would the Cluster specific template variables be added to a Cluster CR under spec.templateContext? Is the idea that the cluster Admins need to add this data to the target clusters? I am wondering if this templateContext data added to the Fleet target cluster CRs will get overwritten when synced with the management.cattle.io.cluster objects in Rancher. |
Yes, the idea is that admins will add these values. I can't speak to Rancher use case unfortunately as I'm only using fleet standalone. PS: I will address your feedback over the weekend! |
I have not seen rancher touch the templateContext on the fleet cluster in my setup. Once set rancher left everything alone when it synced labels from the management cluster. |
25168d5
to
1454c20
Compare
@prachidamle hello! sorry for the delay, please have a look when you get a chance. I believe I address all the requested feedback. |
Hello, any updates? |
@manno I made all the changes and fixed the build! PS: Rebasing seems to be a little painful, we could squash the commits instead perhaps? |
Yes, that would be great. I also discussed this briefly with @mattfarina and we have some concerns regarding recursion depth. |
abe5228
to
b531671
Compare
@rajiteh There is still a small linting issue: https://github.com/rancher/fleet/actions/runs/3576792840/jobs/6029393464
|
b531671
to
65a91b0
Compare
65a91b0
to
9ee1b90
Compare
Thanks! 🎉 |
@manno the relevant documentation for this PR can be found here: rancher/fleet-docs#17 |
Documentation is live under https://fleet.rancher.io/next/gitrepo-add @thardeck created a new alpha release which includes the feature: https://github.com/rancher/fleet/releases/tag/v0.6.0-alpha4 |
This PR introduces the ability for fleet.yaml's
helm.values
object to contain go template strings in either the keys or values. The context of the go template also includes the cluster labels (for convenient migration from the existingglobal.fleet.clusterLabels.FOO
users.Cluster specific template variables can be added to
Cluster
CR under a new optional key inspec.templateContext
Related issues/PRs