Merge pull request #305 from arbourd/values-files
This commit is contained in:
commit
f56c96fff6
|
@ -45,9 +45,19 @@ type HelmChartSpec struct {
|
|||
// +required
|
||||
Interval metav1.Duration `json:"interval"`
|
||||
|
||||
// Alternative values file to use as the default chart values, expected to be a
|
||||
// relative path in the SourceRef. Ignored when omitted.
|
||||
// Alternative list of values files to use as the chart values (values.yaml
|
||||
// is not included by default), expected to be a relative path in the SourceRef.
|
||||
// Values files are merged in the order of this list with the last file overriding
|
||||
// the first. Ignored when omitted.
|
||||
// +optional
|
||||
ValuesFiles []string `json:"valuesFiles,omitempty"`
|
||||
|
||||
// Alternative values file to use as the default chart values, expected to
|
||||
// be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
|
||||
// for backwards compatibility the file defined here is merged before the
|
||||
// ValuesFiles items. Ignored when omitted.
|
||||
// +optional
|
||||
// +deprecated
|
||||
ValuesFile string `json:"valuesFile,omitempty"`
|
||||
|
||||
// This flag tells the controller to suspend the reconciliation of this source.
|
||||
|
@ -168,6 +178,17 @@ func (in *HelmChart) GetInterval() metav1.Duration {
|
|||
return in.Spec.Interval
|
||||
}
|
||||
|
||||
// GetValuesFiles returns a merged list of ValuesFiles.
|
||||
func (in *HelmChart) GetValuesFiles() []string {
|
||||
valuesFiles := in.Spec.ValuesFiles
|
||||
|
||||
// Prepend the deprecated ValuesFile to the list
|
||||
if in.Spec.ValuesFile != "" {
|
||||
valuesFiles = append([]string{in.Spec.ValuesFile}, valuesFiles...)
|
||||
}
|
||||
return valuesFiles
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +genclient:Namespaced
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
@ -324,7 +324,7 @@ func (in *HelmChart) DeepCopyInto(out *HelmChart) {
|
|||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
|
@ -383,6 +383,11 @@ func (in *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) {
|
|||
*out = *in
|
||||
out.SourceRef = in.SourceRef
|
||||
out.Interval = in.Interval
|
||||
if in.ValuesFiles != nil {
|
||||
in, out := &in.ValuesFiles, &out.ValuesFiles
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartSpec.
|
||||
|
|
|
@ -94,8 +94,19 @@ spec:
|
|||
type: boolean
|
||||
valuesFile:
|
||||
description: Alternative values file to use as the default chart values,
|
||||
expected to be a relative path in the SourceRef. Ignored when omitted.
|
||||
expected to be a relative path in the SourceRef. Deprecated in favor
|
||||
of ValuesFiles, for backwards compatibility the file defined here
|
||||
is merged before the ValuesFiles items. Ignored when omitted.
|
||||
type: string
|
||||
valuesFiles:
|
||||
description: Alternative list of values files to use as the chart
|
||||
values (values.yaml is not included by default), expected to be
|
||||
a relative path in the SourceRef. Values files are merged in the
|
||||
order of this list with the last file overriding the first. Ignored
|
||||
when omitted.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
version:
|
||||
default: '*'
|
||||
description: The chart version semver expression, ignored for charts
|
||||
|
|
|
@ -8,4 +8,6 @@ spec:
|
|||
kind: GitRepository
|
||||
name: podinfo
|
||||
chart: charts/podinfo
|
||||
valuesFile: charts/podinfo/values-prod.yaml
|
||||
valuesFile: charts/podinfo/values.yaml
|
||||
valuesFiles:
|
||||
- charts/podinfo/values-prod.yaml
|
||||
|
|
|
@ -8,4 +8,6 @@ spec:
|
|||
kind: HelmRepository
|
||||
name: podinfo
|
||||
chart: podinfo
|
||||
valuesFile: values-prod.yaml
|
||||
valuesFile: values.yaml
|
||||
valuesFiles:
|
||||
- values-prod.yaml
|
||||
|
|
|
@ -49,11 +49,13 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/runtime/events"
|
||||
"github.com/fluxcd/pkg/runtime/metrics"
|
||||
"github.com/fluxcd/pkg/runtime/predicates"
|
||||
"github.com/fluxcd/pkg/runtime/transform"
|
||||
"github.com/fluxcd/pkg/untar"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
|
@ -380,11 +382,13 @@ func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context,
|
|||
readyMessage = fmt.Sprintf("Fetched revision: %s", newArtifact.Revision)
|
||||
)
|
||||
switch {
|
||||
case chart.Spec.ValuesFile != "" && chart.Spec.ValuesFile != chartutil.ValuesfileName:
|
||||
case len(chart.GetValuesFiles()) > 0:
|
||||
var (
|
||||
tmpDir string
|
||||
pkgPath string
|
||||
)
|
||||
valuesMap := make(map[string]interface{})
|
||||
|
||||
// Load the chart
|
||||
helmChart, err := loader.LoadArchive(res)
|
||||
if err != nil {
|
||||
|
@ -392,18 +396,43 @@ func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context,
|
|||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
// Find override file and retrieve contents
|
||||
var valuesData []byte
|
||||
cfn := filepath.Clean(chart.Spec.ValuesFile)
|
||||
for _, f := range helmChart.Files {
|
||||
if f.Name == cfn {
|
||||
valuesData = f.Data
|
||||
break
|
||||
for _, v := range chart.GetValuesFiles() {
|
||||
if v == "values.yaml" {
|
||||
valuesMap = transform.MergeMaps(valuesMap, helmChart.Values)
|
||||
continue
|
||||
}
|
||||
|
||||
var valuesData []byte
|
||||
cfn := filepath.Clean(v)
|
||||
for _, f := range helmChart.Files {
|
||||
if f.Name == cfn {
|
||||
valuesData = f.Data
|
||||
break
|
||||
}
|
||||
}
|
||||
if valuesData == nil {
|
||||
err = fmt.Errorf("invalid values file path: %s", v)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
yamlMap := make(map[string]interface{})
|
||||
err = yaml.Unmarshal(valuesData, &yamlMap)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unmarshaling values from %s failed: %w", v, err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
valuesMap = transform.MergeMaps(valuesMap, yamlMap)
|
||||
}
|
||||
|
||||
yamlBytes, err := yaml.Marshal(valuesMap)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("marshaling values failed: %w", err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPackageFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
// Overwrite values file
|
||||
if changed, err := helm.OverwriteChartDefaultValues(helmChart, valuesData); err != nil {
|
||||
if changed, err := helm.OverwriteChartDefaultValues(helmChart, yamlBytes); err != nil {
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPackageFailedReason, err.Error()), err
|
||||
} else if !changed {
|
||||
// No changes, skip to write original package to storage
|
||||
|
@ -508,22 +537,41 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context,
|
|||
// or write the chart directly to storage.
|
||||
pkgPath := chartPath
|
||||
isValuesFileOverriden := false
|
||||
if chart.Spec.ValuesFile != "" {
|
||||
srcPath, err := securejoin.SecureJoin(tmpDir, chart.Spec.ValuesFile)
|
||||
if err != nil {
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
if f, err := os.Stat(srcPath); os.IsNotExist(err) || !f.Mode().IsRegular() {
|
||||
err = fmt.Errorf("invalid values file path: %s", chart.Spec.ValuesFile)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
if len(chart.GetValuesFiles()) > 0 {
|
||||
valuesMap := make(map[string]interface{})
|
||||
for _, v := range chart.GetValuesFiles() {
|
||||
srcPath, err := securejoin.SecureJoin(tmpDir, v)
|
||||
if err != nil {
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
if f, err := os.Stat(srcPath); os.IsNotExist(err) || !f.Mode().IsRegular() {
|
||||
err = fmt.Errorf("invalid values file path: %s", v)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
valuesData, err := ioutil.ReadFile(srcPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to read from values file '%s': %w", v, err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
yamlMap := make(map[string]interface{})
|
||||
err = yaml.Unmarshal(valuesData, &yamlMap)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unmarshaling values from %s failed: %w", v, err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
}
|
||||
|
||||
valuesMap = transform.MergeMaps(valuesMap, yamlMap)
|
||||
}
|
||||
|
||||
valuesData, err := ioutil.ReadFile(srcPath)
|
||||
yamlBytes, err := yaml.Marshal(valuesMap)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to read from values file '%s': %w", chart.Spec.ValuesFile, err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
|
||||
err = fmt.Errorf("marshaling values failed: %w", err)
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPackageFailedReason, err.Error()), err
|
||||
}
|
||||
isValuesFileOverriden, err = helm.OverwriteChartDefaultValues(helmChart, valuesData)
|
||||
|
||||
isValuesFileOverriden, err = helm.OverwriteChartDefaultValues(helmChart, yamlBytes)
|
||||
if err != nil {
|
||||
return sourcev1.HelmChartNotReady(chart, sourcev1.ChartPackageFailedReason, err.Error()), err
|
||||
}
|
||||
|
|
|
@ -151,10 +151,125 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
!storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
|
||||
When("Setting valid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"values.yaml",
|
||||
"override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"values.yaml",
|
||||
"invalid.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFiles and valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "values.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "override.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "invalid.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
By("Expecting missing HelmRepository error")
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).Should(Succeed())
|
||||
updated.Spec.SourceRef.Name = "invalid"
|
||||
updated.Spec.ValuesFile = ""
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).Should(Succeed())
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, updated)
|
||||
|
@ -601,10 +716,13 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeFalse())
|
||||
|
||||
When("Setting valid valuesFile attribute", func() {
|
||||
When("Setting valid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchart/override.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchart/values.yaml",
|
||||
"./testdata/charts/helmchart/override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
|
@ -617,13 +735,17 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFile attribute", func() {
|
||||
When("Setting invalid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchart/invalid.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchart/values.yaml",
|
||||
"./testdata/charts/helmchart/invalid.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
|
@ -636,6 +758,74 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFiles and valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchart/values.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchart/override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchart/override.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchart/invalid.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
@ -987,10 +1177,13 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeFalse())
|
||||
|
||||
When("Setting valid valuesFile attribute", func() {
|
||||
When("Setting valid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchartwithdeps/override.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchartwithdeps/values.yaml",
|
||||
"./testdata/charts/helmchartwithdeps/override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
|
@ -1003,13 +1196,17 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFile attribute", func() {
|
||||
When("Setting invalid valuesFiles attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchartwithdeps/invalid.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchartwithdeps/values.yaml",
|
||||
"./testdata/charts/helmchartwithdeps/invalid.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
|
@ -1022,6 +1219,74 @@ var _ = Describe("HelmChartReconciler", func() {
|
|||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFiles and valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchartwithdeps/values.yaml"
|
||||
updated.Spec.ValuesFiles = []string{
|
||||
"./testdata/charts/helmchartwithdeps/override.yaml",
|
||||
}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(helmChart.Values["testDefault"]).To(BeTrue())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting valid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchartwithdeps/override.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
|
||||
When("Setting invalid valuesFile attribute", func() {
|
||||
updated := &sourcev1.HelmChart{}
|
||||
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
|
||||
updated.Spec.ValuesFile = "./testdata/charts/helmchartwithdeps/invalid.yaml"
|
||||
updated.Spec.ValuesFiles = []string{}
|
||||
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
|
||||
got := &sourcev1.HelmChart{}
|
||||
Eventually(func() bool {
|
||||
_ = k8sClient.Get(context.Background(), key, got)
|
||||
return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
|
||||
storage.ArtifactExist(*got.Status.Artifact)
|
||||
}, timeout, interval).Should(BeTrue())
|
||||
f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(f.Size()).To(BeNumerically(">", 0))
|
||||
helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, exists := helmChart.Values["testDefault"]
|
||||
Expect(exists).To(BeFalse())
|
||||
Expect(helmChart.Values["testOverride"]).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -542,6 +542,21 @@ Kubernetes meta/v1.Duration
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>valuesFiles</code><br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Alternative list of values files to use as the chart values (values.yaml
|
||||
is not included by default), expected to be a relative path in the SourceRef.
|
||||
Values files are merged in the order of this list with the last file overriding
|
||||
the first. Ignored when omitted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>valuesFile</code><br>
|
||||
<em>
|
||||
string
|
||||
|
@ -549,8 +564,10 @@ string
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Alternative values file to use as the default chart values, expected to be a
|
||||
relative path in the SourceRef. Ignored when omitted.</p>
|
||||
<p>Alternative values file to use as the default chart values, expected to
|
||||
be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
|
||||
for backwards compatibility the file defined here is merged before the
|
||||
ValuesFiles items. Ignored when omitted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -1481,6 +1498,21 @@ Kubernetes meta/v1.Duration
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>valuesFiles</code><br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Alternative list of values files to use as the chart values (values.yaml
|
||||
is not included by default), expected to be a relative path in the SourceRef.
|
||||
Values files are merged in the order of this list with the last file overriding
|
||||
the first. Ignored when omitted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>valuesFile</code><br>
|
||||
<em>
|
||||
string
|
||||
|
@ -1488,8 +1520,10 @@ string
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Alternative values file to use as the default chart values, expected to be a
|
||||
relative path in the SourceRef. Ignored when omitted.</p>
|
||||
<p>Alternative values file to use as the default chart values, expected to
|
||||
be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
|
||||
for backwards compatibility the file defined here is merged before the
|
||||
ValuesFiles items. Ignored when omitted.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -28,9 +28,19 @@ type HelmChartSpec struct {
|
|||
// +required
|
||||
Interval metav1.Duration `json:"interval"`
|
||||
|
||||
// Alternative values file to use as the default chart values, expected to be a
|
||||
// relative path in the SourceRef. Ignored when omitted.
|
||||
// Alternative list of values files to use as the chart values (values.yaml
|
||||
// is not included by default), expected to be a relative path in the SourceRef.
|
||||
// Values files are merged in the order of this list with the last file overriding
|
||||
// the first. Ignored when omitted.
|
||||
// +optional
|
||||
ValuesFiles []string `json:"valuesFiles,omitempty"`
|
||||
|
||||
// Alternative values file to use as the default chart values, expected to
|
||||
// be a relative path in the SourceRef. Deprecated in favor of ValuesFiles,
|
||||
// for backwards compatibility the file defined here is merged before the
|
||||
// ValuesFiles items. Ignored when omitted.
|
||||
// +optional
|
||||
// +deprecated
|
||||
ValuesFile string `json:"valuesFile,omitempty"`
|
||||
|
||||
// This flag tells the controller to suspend the reconciliation of this source.
|
||||
|
@ -182,6 +192,44 @@ spec:
|
|||
interval: 10m
|
||||
```
|
||||
|
||||
Override default values with alternative values files relative to the
|
||||
path in the SourceRef:
|
||||
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: default
|
||||
spec:
|
||||
chart: redis
|
||||
version: 10.5.7
|
||||
sourceRef:
|
||||
name: stable
|
||||
kind: HelmRepository
|
||||
interval: 5m
|
||||
valuesFiles:
|
||||
- values.yaml
|
||||
- values-production.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: HelmChart
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: default
|
||||
spec:
|
||||
chart: ./charts/podinfo
|
||||
sourceRef:
|
||||
name: podinfo
|
||||
kind: GitRepository
|
||||
interval: 10m
|
||||
valuesFiles:
|
||||
- ./charts/podinfo/values.yaml
|
||||
- ./charts/podinfo/values-production.yaml
|
||||
```
|
||||
|
||||
## Status examples
|
||||
|
||||
Successful chart pull:
|
||||
|
|
Loading…
Reference in New Issue