Skip to content

Commit

Permalink
Merge pull request #55 from fluxcd/values-from-targetpaths
Browse files Browse the repository at this point in the history
Support targeting a path in ValuesReferences
  • Loading branch information
hiddeco authored Aug 20, 2020
2 parents 27a8da8 + f2f8b23 commit 6e1ab99
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
kubectl -n helm-system wait helmreleases/valuesfrom --for=condition=ready --timeout=4m
RESULT=$(helm -n helm-system get values valuesfrom)
EXPECTED=$(cat config/testdata/valuesfrom/result.txt)
EXPECTED=$(cat config/testdata/valuesfrom/golden.txt)
if [ "$RESULT" != "$EXPECTED" ]; then
echo -e "$RESULT\n\ndoes not equal\n\n$EXPECTED"
fi
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ all: manager

# Run tests
test: generate fmt vet manifests api-docs
find . -maxdepth 2 -type f -name 'go.mod' -execdir go test ./... \;
find . -maxdepth 2 -type f -name 'go.mod' -execdir go test ./... -coverprofile cover.out \;

# Build manager binary
manager: generate fmt vet
Expand Down
10 changes: 8 additions & 2 deletions api/v2alpha1/reference_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,16 @@ type ValuesReference struct {
// +required
Name string `json:"name"`

// ValuesKey is the key in the referent the values can be found at.
// Defaults to 'values.yaml'.
// ValuesKey is the data key where the values.yaml or a specific value can
// be found at. Defaults to 'values.yaml'.
// +optional
ValuesKey string `json:"valuesKey,omitempty"`

// TargetPath is the YAML dot notation path the value should be merged at.
// When set, the ValuesKey is expected to be a single flat value.
// Defaults to 'None', which results in the values getting merged at the root.
// +optional
TargetPath string `json:"targetPath,omitempty"`
}

// GetValuesKey returns the defined ValuesKey or the default ('values.yaml').
Expand Down
10 changes: 8 additions & 2 deletions config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,15 @@ spec:
description: Name of the values referent. Should reside in the
same namespace as the referring resource.
type: string
targetPath:
description: TargetPath is the YAML dot notation path the value
should be merged at. When set, the ValuesKey is expected to
be a single flat value. Defaults to 'None', which results
in the values getting merged at the root.
type: string
valuesKey:
description: ValuesKey is the key in the referent the values
can be found at. Defaults to 'values.yaml'.
description: ValuesKey is the data key where the values.yaml
or a specific value can be found at. Defaults to 'values.yaml'.
type: string
required:
- kind
Expand Down
4 changes: 4 additions & 0 deletions config/testdata/valuesfrom/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ data:
requests:
cpu: 100m
memory: 64Mi
resources.limits.cpu: 400m
list.example: "{a,b,c}"
list.example.overwrite: d
podAnnotation.example.value: demo
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
USER-SUPPLIED VALUES:
list:
example:
- a
- b
- d
podAnnotations:
some.k8s.annotation/env: demo
replicaCount: 2
resources:
limits:
cpu: 200m
cpu: 400m
memory: 128Mi
requests:
cpu: 100m
Expand Down
16 changes: 16 additions & 0 deletions config/testdata/valuesfrom/helmrelease.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ spec:
- kind: ConfigMap
name: valuesfrom-config
valuesKey: resources.requests
- kind: ConfigMap
name: valuesfrom-config
valuesKey: resources.limits.cpu
targetPath: resources.limits.cpu
- kind: ConfigMap
name: valuesfrom-config
valuesKey: list.example
targetPath: list.example
- kind: ConfigMap
name: valuesfrom-config
valuesKey: list.example.overwrite
targetPath: list.example[2]
- kind: ConfigMap
name: valuesfrom-config
valuesKey: podAnnotation.example.value
targetPath: podAnnotations.some\.k8s\.annotation\/env
- kind: Secret
name: valuesfrom-secret
values:
Expand Down
6 changes: 4 additions & 2 deletions config/testdata/valuesfrom/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ kind: Secret
metadata:
name: valuesfrom-secret
type: Opaque
data:
values.yaml: c2VydmljZUFjY291bnQ6CiAgZW5hYmxlZDogdHJ1ZQo=
stringData:
values.yaml: |
serviceAccount:
enabled: true
20 changes: 16 additions & 4 deletions controllers/helmrelease_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/storage/driver"
"helm.sh/helm/v3/pkg/strvals"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -472,11 +473,22 @@ func (r *HelmReleaseReconciler) composeValues(ctx context.Context, hr v2.HelmRel
default:
return nil, fmt.Errorf("unsupported ValuesReference kind '%s'", v.Kind)
}
values, err := chartutil.ReadValues(valsData)
if err != nil {
return nil, fmt.Errorf("unable to read values from key '%s' in %s '%s': %w", v.GetValuesKey(), v.Kind, namespacedName, err)
switch v.TargetPath {
case "":
values, err := chartutil.ReadValues(valsData)
if err != nil {
return nil, fmt.Errorf("unable to read values from key '%s' in %s '%s': %w", v.GetValuesKey(), v.Kind, namespacedName, err)
}
result = mergeMaps(result, values)
default:
// TODO(hidde): this is a bit of hack, as it mimics the way the option string is passed
// to Helm from a CLI perspective. Given the parser is however not publicly accessible
// while it contains all logic around parsing the target path, it is a fair trade-off.
singleVal := v.TargetPath + "=" + string(valsData)
if err := strvals.ParseInto(singleVal, result); err != nil {
return nil, fmt.Errorf("unable to merge value from key '%s' in %s '%s' into target path '%s': %w", v.GetValuesKey(), v.Kind, namespacedName, v.TargetPath, err)
}
}
result = mergeMaps(result, values)
}
return mergeMaps(result, hr.GetValues()), nil
}
Expand Down
18 changes: 16 additions & 2 deletions docs/api/helmrelease.md
Original file line number Diff line number Diff line change
Expand Up @@ -1362,8 +1362,22 @@ string
</td>
<td>
<em>(Optional)</em>
<p>ValuesKey is the key in the referent the values can be found at.
Defaults to &lsquo;values.yaml&rsquo;.</p>
<p>ValuesKey is the data key where the values.yaml or a specific value can
be found at. Defaults to &lsquo;values.yaml&rsquo;.</p>
</td>
</tr>
<tr>
<td>
<code>targetPath</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>TargetPath is the YAML dot notation path the value should be merged at.
When set, the ValuesKey is expected to be a single flat value.
Defaults to &lsquo;None&rsquo;, which results in the values getting merged at the root.</p>
</td>
</tr>
</tbody>
Expand Down
14 changes: 10 additions & 4 deletions docs/spec/v2alpha1/helmreleases.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type HelmReleaseSpec struct {

// ValuesFrom holds references to resources containing Helm values, and information
// about how they should be merged.
ValuesFrom []ValuesReference `json:"valuesFrom,omitempty"
ValuesFrom []ValuesReference `json:"valuesFrom,omitempty"`

// Values holds the values for this Helm release.
// +optional
Expand Down Expand Up @@ -281,11 +281,17 @@ type ValuesReference struct {
// referring resource.
// +required
Name string `json:"name"`
// ValuesKey is the key in the referent the values can be found at.
// Defaults to 'values.yaml'.

// ValuesKey is the data key where the values.yaml or a specific value can
// be found at. Defaults to 'values.yaml'.
// +optional
ValuesKey string `json:"valuesKey,omitempty"`

// TargetPath is the YAML dot notation path the value should be merged at.
// When set, the ValuesKey is expected to be a single flat value.
// Defaults to 'None', which results in the values getting merged at the root.
// +optional
TargetPath string `json:"targetPath,omitempty"`
}
```

Expand Down

0 comments on commit 6e1ab99

Please sign in to comment.