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

feat(helm): helm values can be either a string or a map (#2936) #11538

Merged
merged 23 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion assets/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -4953,6 +4953,17 @@
}
}
},
"runtimeRawExtension": {
"description": "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned\nstruct, and Object in your internal struct. You also need to register your\nvarious plugin types.\n\n// Internal package:\ntype MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.Object `json:\"myPlugin\"`\n}\ntype PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// External package:\ntype MyAPIObject struct {\n\truntime.TypeMeta `json:\",inline\"`\n\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n}\ntype PluginA struct {\n\tAOption string `json:\"aOption\"`\n}\n\n// On the wire, the JSON will look something like this:\n{\n\t\"kind\":\"MyAPIObject\",\n\t\"apiVersion\":\"v1\",\n\t\"myPlugin\": {\n\t\t\"kind\":\"PluginA\",\n\t\t\"aOption\":\"foo\",\n\t},\n}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into\nyour external MyAPIObject. That causes the raw JSON to be stored, but not unpacked.\nThe next step is to copy (using pkg/conversion) into the internal struct. The runtime\npackage's DefaultScheme has conversion functions installed which will unpack the\nJSON stored in RawExtension, turning it into the correct object type, and storing it\nin the Object. (TODO: In the case where the object is of an unknown type, a\nruntime.Unknown object will be created and stored.)\n\n+k8s:deepcopy-gen=true\n+protobuf=true\n+k8s:openapi-gen=true",
"type": "object",
"properties": {
"raw": {
"description": "Raw is the underlying serialization of this object.\n\nTODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.",
"type": "string",
"format": "byte"
}
}
},
"runtimeStreamError": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -6165,7 +6176,10 @@
},
"values": {
"type": "string",
"title": "Values specifies Helm values to be passed to helm template, typically defined as a block"
"title": "Values specifies Helm values to be passed to helm template, typically defined as a block. ValuesObject takes precedence over Values, so use one or the other.\n+patchStrategy=replace"
},
"valuesObject": {
"$ref": "#/definitions/runtimeRawExtension"
},
"version": {
"type": "string",
Expand Down
8 changes: 5 additions & 3 deletions cmd/argocd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,9 +794,11 @@ func unset(source *argoappv1.ApplicationSource, opts unsetOpts) (updated bool, n
}
}
}
if opts.valuesLiteral && source.Helm.Values != "" {
source.Helm.Values = ""
updated = true
if opts.valuesLiteral && !source.Helm.ValuesIsEmpty() {
err := source.Helm.SetValuesString("")
if err == nil {
updated = true
}
}
for _, valuesFile := range opts.valuesFiles {
specValueFiles := source.Helm.ValueFiles
Expand Down
7 changes: 4 additions & 3 deletions cmd/argocd/commands/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
)

Expand Down Expand Up @@ -778,7 +779,7 @@ func Test_unset(t *testing.T) {
},
},
PassCredentials: true,
Values: "some: yaml",
ValuesObject: &runtime.RawExtension{Raw: []byte("some: yaml")},
ValueFiles: []string{
"values-1.yaml",
"values-2.yaml",
Expand Down Expand Up @@ -864,9 +865,9 @@ func Test_unset(t *testing.T) {
assert.False(t, updated)
assert.False(t, nothingToUnset)

assert.Equal(t, "some: yaml", helmSource.Helm.Values)
assert.Equal(t, "some: yaml", helmSource.Helm.ValuesString())
updated, nothingToUnset = unset(helmSource, unsetOpts{valuesLiteral: true})
assert.Equal(t, "", helmSource.Helm.Values)
assert.Equal(t, "", helmSource.Helm.ValuesString())
assert.True(t, updated)
assert.False(t, nothingToUnset)
updated, nothingToUnset = unset(helmSource, unsetOpts{valuesLiteral: true})
Expand Down
5 changes: 4 additions & 1 deletion cmd/util/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,10 @@ func setHelmOpt(src *argoappv1.ApplicationSource, opts helmOpts) {
src.Helm.IgnoreMissingValueFiles = opts.ignoreMissingValueFiles
}
if len(opts.values) > 0 {
src.Helm.Values = opts.values
err := src.Helm.SetValuesString(opts.values)
if err != nil {
log.Fatal(err)
}
}
if opts.releaseName != "" {
src.Helm.ReleaseName = opts.releaseName
Expand Down
18 changes: 17 additions & 1 deletion docs/operator-manual/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ spec:
# Ignore locally missing valueFiles when installing Helm chart. Defaults to false
ignoreMissingValueFiles: false

# Values file as block file
# Values file as block file. Prefer to use valuesObject if possible (see below)
values: |
ingress:
enabled: true
Expand All @@ -67,6 +67,22 @@ spec:
hosts:
- mydomain.example.com

# Values file as block file. This takes precedence over values
valuesObject:
ingress:
enabled: true
path: /
hosts:
- mydomain.example.com
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
labels: {}
tls:
- secretName: mydomain-tls
hosts:
- mydomain.example.com

# Skip custom resource definition installation if chart contains custom resource definitions. Defaults to false
skipCrds: false

Expand Down
23 changes: 22 additions & 1 deletion docs/user-guide/helm.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,28 @@ source:

## Values

Argo CD supports the equivalent of a values file directly in the Application manifest using the `source.helm.values` key.
Argo CD supports the equivalent of a values file directly in the Application manifest using the `source.helm.valuesObject` key.

```
source:
helm:
valuesObject:
ingress:
enabled: true
path: /
hosts:
- mydomain.example.com
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
labels: {}
tls:
- secretName: mydomain-tls
hosts:
- mydomain.example.com
```

Alternatively, values can be passed in as a string using the `source.helm.values` key.

```
source:
Expand Down
Loading
Loading