-
Notifications
You must be signed in to change notification settings - Fork 230
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
Add templateValues
to HelmApp, Bundle, etc
#3267
base: main
Are you sure you want to change the base?
Add templateValues
to HelmApp, Bundle, etc
#3267
Conversation
21e3d46
to
5dbcbc0
Compare
With this change I was able to deploy helm chart with proper modifications: apiversion: fleet.cattle.io/v1alpha1
kind: HelmApp
metadata:
finalizers:
- fleet.cattle.io/helmapp-finalizer
generation: 3
name: sample1
namespace: default
resourceVersion: "23694"
uid: 511580b5-733a-4304-9cbb-229448989a3a
spec:
helm:
chart: tigera-operator
releaseName: projectcalico
repo: https://docs.tigera.io/calico/charts
templateValues:
installation: |-
cni:
type: Calico
ipam:
type: HostLocal
calicoNetwork:
bgp: Disabled
mtu: 1350
ipPools:
${- range $cidr := .ClusterValues.Cluster.spec.clusterNetwork.pods.cidrBlocks }
- cidr: "${ $cidr }"
encapsulation: None
natOutgoing: Enabled
nodeSelector: all()${- end}
ignore: {}
insecureSkipTLSVerify: true
targets:
- clusterName: docker-demo created correct apiversion: fleet.cattle.io/v1alpha1
kind: BundleDeployment
metadata:
creationTimestamp: "2025-01-28T15:00:20Z"
finalizers:
- fleet.cattle.io/bundle-deployment-finalizer
generation: 1
labels:
fleet.cattle.io/bundle-name: sample1
fleet.cattle.io/bundle-namespace: default
fleet.cattle.io/cluster: docker-demo
fleet.cattle.io/cluster-namespace: default
fleet.cattle.io/fleet-helm-name: sample1
fleet.cattle.io/managed: "true"
name: sample1
namespace: cluster-default-docker-demo-9a1d57cc2ad8
resourceVersion: "22820"
uid: 37600a86-c9e4-4445-a757-5611c5d27ace
spec:
deploymentID: :fb788a089566f35d87c7d4b2ed4a499a2d3e36315b44cfa9446f66996b6a7c82
helmChartOptions:
helmAppInsecureSkipTLSVerify: true
options:
helm:
chart: tigera-operator
releaseName: projectcalico
repo: https://docs.tigera.io/calico/charts
templateValues:
installation: |-
cni:
type: Calico
ipam:
type: HostLocal
calicoNetwork:
bgp: Disabled
mtu: 1350
ipPools:
${- range $cidr := .ClusterValues.Cluster.spec.clusterNetwork.pods.cidrBlocks }
- cidr: "${ $cidr }"
encapsulation: None
natOutgoing: Enabled
nodeSelector: all()${- end}
values:
installation:
calicoNetwork:
bgp: Disabled
ipPools:
- cidr: 10.1.0.0/16
encapsulation: None
natOutgoing: Enabled
nodeSelector: all()
mtu: 1350
cni:
ipam:
type: HostLocal
type: Calico
version: v3.29.1
ignore: {}
stagedDeploymentID: :fb788a089566f35d87c7d4b2ed4a499a2d3e36315b44cfa9446f66996b6a7c82
… |
templateValues
to HelmApp, Bundle, etc
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 like the idea, but I wonder if we really need both values and templateValues
; perhaps we could template each member of the existing value
field before serialising it to YAML, WDYT?
if opts.Helm.Values.Data == nil { | ||
opts.Helm.Values.Data = map[string]interface{}{} | ||
} |
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.
Why do we still need this block? My understanding is that cmp.Or
would populate the Data
field if needed 🤔
opts.Helm.Values.Data = map[string]interface{}{} | ||
} | ||
|
||
if opts.Helm.TemplateValues == nil && (opts.Helm.Values == nil || opts.Helm.Values.Data == nil) { |
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.
Since we've ensured that opts.Helm.Values.Data
exists, wouldn't the following be enough?
if opts.Helm.TemplateValues == nil && (opts.Helm.Values == nil || opts.Helm.Values.Data == nil) { | |
if opts.Helm.TemplateValues == nil && opts.Helm.Values.Data == nil { |
return err | ||
} | ||
|
||
maps.Copy(opts.Helm.Values.Data, templatedData) |
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.
This effectively means that, if both a value and a template value exist with the same key, the latter will overwrite the former. Not a problem, but something we'll want to document, and ideally test :)
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 updated the doc message on the field. Not sure we need to test this, since the method is a part of standard lib, but added a scenario
var value interface{} | ||
err = kyaml.Unmarshal(b.Bytes(), &value) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to interpret rendered template as helm values: %#v, %v", renderedValues, err) |
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.
Why output the whole set of rendered values here? Is the rationale to enable the user to understand where successful processing stopped? Otherwise, how about outputting b.String()
(or rather a string conversion of the previous b.Bytes()
)?
@@ -314,6 +329,70 @@ func TestProcessTemplateValues(t *testing.T) { | |||
t.Fatal("join func was not right") | |||
} | |||
|
|||
templatedValuesData, err := processTemplateValuesData(bundle.Helm.TemplateValues, values) | |||
if err != nil { | |||
t.Fatalf("error during label processing %v", err) |
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.
🤨 Not sure why that error message is phrased this way (same for processTemplateValues
)
t.Fatalf("error during label processing %v", err) | |
t.Fatalf("error during templated values processing %v", err) |
I also thought about it, but that has the same problem as previous solution. As the value in the map is interface{}, what type it actually contains is unknown. Template processing requires string data, which is only achievable after serialization - so it has to go through yaml decoder. These template expressions do not render as valid yaml, so we can't do anything. Even if the interface is initially checked to be string, and we can skip yaml pre-processing, it is unclear if the templated result needs to stay a sting, or it has to be a map/list. Maybe there is a way around the issue I'm not seeing here. |
126b010
to
f308721
Compare
Signed-off-by: Danil-Grigorev <danil.grigorev@suse.com>
f308721
to
86be9f3
Compare
Refers to #3266
Implement new field inside
Helm
options:templateValues
, which performs templating of each individual value before converting data to yaml. This allows to use more complex template expressions then currently available to template string data, like creation of maps and lists.