Skip to content
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

Merged
merged 1 commit into from Dec 1, 2022

Conversation

rajiteh
Copy link
Contributor

@rajiteh rajiteh commented Dec 4, 2021

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 existing global.fleet.clusterLabels.FOO users.

Cluster specific template variables can be added to Cluster CR under a new optional key in spec.templateContext

Related issues/PRs

return nil, err
}

tpl, err := template.New("values").Funcs(tplFuncMap()).Option("missingkey=error").Parse(string(valuesMapStr))

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.


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.

Copy link
Contributor Author

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?

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.

Copy link
Contributor Author

@rajiteh rajiteh Feb 16, 2022

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.

Copy link
Contributor Author

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.

@rajiteh
Copy link
Contributor Author

rajiteh commented Mar 11, 2022

@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.

https://github.com/rajiteh/fleet/pull/3/files

@rajiteh rajiteh mentioned this pull request Mar 14, 2022
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo pre-processing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@prachidamle
Copy link
Member

@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.

@rajiteh
Copy link
Contributor Author

rajiteh commented Mar 29, 2022

@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!

@gregsidelinger
Copy link

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.

@superseb superseb removed their request for review April 8, 2022 14:39
@rajiteh
Copy link
Contributor Author

rajiteh commented Apr 14, 2022

@prachidamle hello! sorry for the delay, please have a look when you get a chance. I believe I address all the requested feedback.

@MKlimuszka MKlimuszka added this to the v2.6.6 milestone May 10, 2022
@mattfarina mattfarina self-assigned this Jul 6, 2022
@zube zube bot added the team/fleet label Jul 26, 2022
@k0da
Copy link

k0da commented Aug 31, 2022

Hello, any updates?

@manno
Copy link
Member

manno commented Nov 23, 2022

@rajiteh Let's get this merged. Do you want to rename the context variable and rebase this PR against current master, or should we try to schedule this?

@rajiteh
Copy link
Contributor Author

rajiteh commented Nov 25, 2022

@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?

@manno
Copy link
Member

manno commented Nov 29, 2022

@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. templateSubstitutions and processLabelValues should probably be limited to a depth of, I don't know, 50?
However, I don't think that has to happen in this PR.

@rajiteh rajiteh force-pushed the template_values branch 2 times, most recently from abe5228 to b531671 Compare November 29, 2022 18:06
manno
manno previously approved these changes Nov 30, 2022
@thardeck
Copy link
Contributor

@rajiteh There is still a small linting issue: https://github.com/rancher/fleet/actions/runs/3576792840/jobs/6029393464

  Error: `getClusterAndBundle` - `clusterYaml` always receives `clusterYamlWithTemplateValues` (`"apiVersion: fleet.cattle.io/v1alpha1\nkind: Cluster\nmetadata:\n  na...`) (unparam)

@manno manno merged commit 20705b6 into rancher:master Dec 1, 2022
@zube zube bot added [zube]: Done and removed [zube]: Review labels Dec 1, 2022
@manno
Copy link
Member

manno commented Dec 1, 2022

Thanks! 🎉

@rajiteh
Copy link
Contributor Author

rajiteh commented Dec 1, 2022

@manno the relevant documentation for this PR can be found here: rancher/fleet-docs#17

@rajiteh rajiteh deleted the template_values branch December 1, 2022 20:53
@manno
Copy link
Member

manno commented Dec 2, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

10 participants