From 8a656bcff8b29fa2fb3c6e3c1d9d86fbe21c7f29 Mon Sep 17 00:00:00 2001 From: Arturo Contreras Date: Tue, 9 Apr 2019 07:52:27 -0600 Subject: [PATCH] Adding chartFileRef option to valuesFrom. --- chart/flux/templates/helm-operator-crd.yaml | 9 +++++ deploy-helm/flux-helm-release-crd.yaml | 9 +++++ .../apis/flux.weave.works/v1beta1/types.go | 10 ++++++ .../v1beta1/zz_generated.deepcopy.go | 34 +++++++++++++++++++ integrations/helm/release/release.go | 33 ++++++++++++++++-- site/helm-integration.md | 15 ++++++++ 6 files changed, 108 insertions(+), 2 deletions(-) diff --git a/chart/flux/templates/helm-operator-crd.yaml b/chart/flux/templates/helm-operator-crd.yaml index fbb2658a4..e6bfdd6b1 100644 --- a/chart/flux/templates/helm-operator-crd.yaml +++ b/chart/flux/templates/helm-operator-crd.yaml @@ -83,10 +83,19 @@ spec: type: string optional: type: boolean + chartFileRef: + type: object + required: ['path'] + properties: + path: + type: string + optional: + type: boolean oneOf: - required: ['configMapKeyRef'] - required: ['secretKeyRef'] - required: ['externalSourceRef'] + - required: ['chartFileRef'] values: type: object chart: diff --git a/deploy-helm/flux-helm-release-crd.yaml b/deploy-helm/flux-helm-release-crd.yaml index 7c2b9c0e5..1a633bf3c 100644 --- a/deploy-helm/flux-helm-release-crd.yaml +++ b/deploy-helm/flux-helm-release-crd.yaml @@ -74,10 +74,19 @@ spec: type: string optional: type: boolean + chartFileRef: + type: object + required: ['path'] + properties: + path: + type: string + optional: + type: boolean oneOf: - required: ['configMapKeyRef'] - required: ['secretKeyRef'] - required: ['externalSourceRef'] + - required: ['chartFileRef'] values: type: object chart: diff --git a/integrations/apis/flux.weave.works/v1beta1/types.go b/integrations/apis/flux.weave.works/v1beta1/types.go index 8dd744b16..4dea9fcf1 100644 --- a/integrations/apis/flux.weave.works/v1beta1/types.go +++ b/integrations/apis/flux.weave.works/v1beta1/types.go @@ -43,6 +43,16 @@ type ValuesFromSource struct { // Selects an URL. // +optional ExternalSourceRef *ExternalSourceSelector `json:"externalSourceRef,omitempty"` + // Selects a file from git source helm chart. + // +optional + ChartFileRef *ChartFileSelector `json:"chartFileRef,omitempty"` +} + +type ChartFileSelector struct { + Path string `json:"path"` + // Do not fail if chart file could not be retrieved + // +optional + Optional *bool `json:"optional,omitempty"` } type ExternalSourceSelector struct { diff --git a/integrations/apis/flux.weave.works/v1beta1/zz_generated.deepcopy.go b/integrations/apis/flux.weave.works/v1beta1/zz_generated.deepcopy.go index 4c6f086b9..d37ef413f 100644 --- a/integrations/apis/flux.weave.works/v1beta1/zz_generated.deepcopy.go +++ b/integrations/apis/flux.weave.works/v1beta1/zz_generated.deepcopy.go @@ -25,6 +25,31 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChartFileSelector) DeepCopyInto(out *ChartFileSelector) { + *out = *in + if in.Optional != nil { + in, out := &in.Optional, &out.Optional + if *in == nil { + *out = nil + } else { + *out = new(bool) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChartFileSelector. +func (in *ChartFileSelector) DeepCopy() *ChartFileSelector { + if in == nil { + return nil + } + out := new(ChartFileSelector) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ChartSource) DeepCopyInto(out *ChartSource) { *out = *in @@ -297,6 +322,15 @@ func (in *ValuesFromSource) DeepCopyInto(out *ValuesFromSource) { (*in).DeepCopyInto(*out) } } + if in.ChartFileRef != nil { + in, out := &in.ChartFileRef, &out.ChartFileRef + if *in == nil { + *out = nil + } else { + *out = new(ChartFileSelector) + (*in).DeepCopyInto(*out) + } + } return } diff --git a/integrations/helm/release/release.go b/integrations/helm/release/release.go index d53cfa611..ef852f87f 100644 --- a/integrations/helm/release/release.go +++ b/integrations/helm/release/release.go @@ -3,9 +3,11 @@ package release import ( "context" "fmt" + "io/ioutil" "net/url" "os" "os/exec" + "path/filepath" "time" "github.com/ghodss/yaml" @@ -159,7 +161,7 @@ func (r *Release) Install(chartPath, releaseName string, fhr flux_v1beta1.HelmRe } valuesFrom = append(secretKeyRefs, valuesFrom...) } - vals, err := values(kubeClient.CoreV1(), fhr.Namespace, valuesFrom, fhr.Spec.Values) + vals, err := values(kubeClient.CoreV1(), fhr.Namespace, chartPath, valuesFrom, fhr.Spec.Values) if err != nil { r.logger.Log("error", fmt.Sprintf("Failed to compose values for Chart release [%s]: %v", fhr.Spec.ReleaseName, err)) return nil, err @@ -275,7 +277,7 @@ func fhrResourceID(fhr flux_v1beta1.HelmRelease) flux.ResourceID { // values tries to resolve all given value file sources and merges // them into one Values struct. It returns the merged Values. -func values(corev1 k8sclientv1.CoreV1Interface, ns string, valuesFromSource []flux_v1beta1.ValuesFromSource, values chartutil.Values) (chartutil.Values, error) { +func values(corev1 k8sclientv1.CoreV1Interface, ns string, chartPath string, valuesFromSource []flux_v1beta1.ValuesFromSource, values chartutil.Values) (chartutil.Values, error) { result := chartutil.Values{} for _, v := range valuesFromSource { @@ -352,6 +354,23 @@ func values(corev1 k8sclientv1.CoreV1Interface, ns string, valuesFromSource []fl } return result, fmt.Errorf("unable to yaml.Unmarshal %v from URL %s", b, url) } + case v.ChartFileRef != nil: + cf := v.ChartFileRef + filePath := cf.Path + optional := cf.Optional != nil && *cf.Optional + f, err := readLocalChartFile(filepath.Join(chartPath, filePath)) + if err != nil { + if optional { + continue + } + return result, fmt.Errorf("unable to read value file from path %s", filePath) + } + if err := yaml.Unmarshal(f, &valueFile); err != nil { + if optional { + continue + } + return result, fmt.Errorf("unable to yaml.Unmarshal %v from URL %s", f, filePath) + } } result = mergeValues(result, valueFile) @@ -415,6 +434,16 @@ func readURL(URL string) ([]byte, error) { return data.Bytes(), err } +// readLocalChartFile attempts to read a file from the chart path. +func readLocalChartFile(filePath string) ([]byte, error) { + f, err := ioutil.ReadFile(filePath) + if err != nil { + return []byte{}, err + } + + return f, nil +} + // releaseManifestToUnstructured turns a string containing YAML // manifests into an array of Unstructured objects. func releaseManifestToUnstructured(manifest string, logger log.Logger) []unstructured.Unstructured { diff --git a/site/helm-integration.md b/site/helm-integration.md index 69fd48761..97eb4d138 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -14,6 +14,7 @@ menu_order: 90 * [Config maps](#config-maps) * [Secrets](#secrets) * [External sources](#external-sources) + * [Chart files](#chart-files) * [Upgrading images in a `HelmRelease` using Flux](#upgrading-images-in-a-helmrelease-using-flux) + [Using annotations to control updates to HelmRelease resources](#using-annotations-to-control-updates-to-helmrelease-resources) * [Authentication](#authentication) @@ -214,6 +215,20 @@ spec: optional: true # optional; defaults to false ``` +#### Chart files + +```yaml +spec: + # chart: ... + valuesFrom: + - chartFileRef: + # path within the helm chart (from git repo) where environment-prod.yaml is located + path: overrides/environment-prod.yaml # mandatory + # If set to true successful retrieval of the values file is no + # longer mandatory + optional: true # optional; defaults to false +``` + ## Upgrading images in a `HelmRelease` using Flux If the chart you're using in a `HelmRelease` lets you specify the