source-controller/controllers/helmchart_controller_test.go

1332 lines
47 KiB
Go

/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controllers
import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/gittestserver"
"github.com/fluxcd/pkg/helmtestserver"
"github.com/fluxcd/pkg/runtime/conditions"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
helmchart "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/yaml"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
)
var _ = FDescribe("HelmChartReconciler", func() {
const (
timeout = time.Second * 30
interval = time.Second * 1
indexInterval = time.Second * 2
pullInterval = time.Second * 3
)
Context("HelmChart from HelmRepository", func() {
var (
namespace *corev1.Namespace
helmServer *helmtestserver.HelmServer
err error
)
BeforeEach(func() {
namespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: "helm-chart-test-" + randStringRunes(5)},
}
err = k8sClient.Create(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
helmServer, err = helmtestserver.NewTempHelmServer()
Expect(err).To(Succeed())
helmServer.Start()
})
AfterEach(func() {
helmServer.Stop()
os.RemoveAll(helmServer.Root())
err = k8sClient.Delete(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace")
})
It("Creates artifacts for", func() {
Expect(helmServer.PackageChart(path.Join("testdata/charts/helmchart"))).Should(Succeed())
Expect(helmServer.GenerateIndex()).Should(Succeed())
repositoryKey := types.NamespacedName{
Name: "helmrepository-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
Expect(k8sClient.Create(context.Background(), &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.HelmRepositorySpec{
URL: helmServer.URL(),
Interval: metav1.Duration{Duration: indexInterval},
},
})).Should(Succeed())
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
created := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: "helmchart",
Version: "",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.HelmRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), created)).Should(Succeed())
By("Expecting artifact")
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact != nil && ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(helmChart.Values["testDefault"]).To(BeTrue())
Expect(helmChart.Values["testOverride"]).To(BeFalse())
By("Packaging a new chart version and regenerating the index")
Expect(helmServer.PackageChartWithVersion(path.Join("testdata/charts/helmchart"), "0.2.0")).Should(Succeed())
Expect(helmServer.GenerateIndex()).Should(Succeed())
By("Expecting new artifact revision and GC")
Eventually(func() bool {
now := &sourcev1.HelmChart{}
_ = k8sClient.Get(context.Background(), key, now)
// Test revision change and garbage collection
return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
!ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
_, exists := helmChart.Values["testDefault"]
Expect(exists).To(BeFalse())
Expect(helmChart.Values["testOverride"]).To(BeTrue())
})
When("Setting identical valuesFile attribute", func() {
updated := &sourcev1.HelmChart{}
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
updated.Spec.ValuesFile = "duplicate.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(helmChart.Values["testDefault"]).To(BeTrue())
Expect(helmChart.Values["testOverride"]).To(BeFalse())
})
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 && got.GetArtifact() != nil &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(helmChart.Values["testDefault"]).To(BeTrue())
Expect(helmChart.Values["testOverride"]).To(BeFalse())
})
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)
for _, c := range updated.Status.Conditions {
fmt.Fprintf(GinkgoWriter, "condition type: %s\n", c.Type)
fmt.Fprintf(GinkgoWriter, "condition reason: %s\n", c.Reason)
fmt.Fprintf(GinkgoWriter, "condition message: %s\n", c.Message)
if c.Reason == sourcev1.ChartPullFailedReason &&
strings.Contains(c.Message, "failed to retrieve source") {
return true
}
}
return false
}, timeout, interval).Should(BeTrue())
Expect(updated.Status.Artifact).ToNot(BeNil())
By("Expecting to delete successfully")
got = &sourcev1.HelmChart{}
Eventually(func() error {
_ = k8sClient.Get(context.Background(), key, got)
return k8sClient.Delete(context.Background(), got)
}, timeout, interval).Should(Succeed())
By("Expecting delete to finish")
Eventually(func() error {
c := &sourcev1.HelmChart{}
return k8sClient.Get(context.Background(), key, c)
}, timeout, interval).ShouldNot(Succeed())
exists := func(path string) bool {
// wait for tmp sync on macOS
time.Sleep(time.Second)
_, err := os.Stat(path)
return err == nil
}
By("Expecting GC on delete")
Eventually(exists(got.Status.Artifact.Path), timeout, interval).ShouldNot(BeTrue())
})
It("Filters versions", func() {
versions := []string{"0.1.0", "0.1.1", "0.2.0", "0.3.0-rc.1", "1.0.0-alpha.1", "1.0.0"}
for k := range versions {
Expect(helmServer.PackageChartWithVersion(path.Join("testdata/charts/helmchart"), versions[k])).Should(Succeed())
}
Expect(helmServer.GenerateIndex()).Should(Succeed())
repositoryKey := types.NamespacedName{
Name: "helmrepository-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
repository := &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.HelmRepositorySpec{
URL: helmServer.URL(),
Interval: metav1.Duration{Duration: 1 * time.Hour},
},
}
Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), repository)
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
chart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: "helmchart",
Version: "*",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.HelmRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: 1 * time.Hour},
},
}
Expect(k8sClient.Create(context.Background(), chart)).Should(Succeed())
defer k8sClient.Delete(context.Background(), chart)
Eventually(func() string {
_ = k8sClient.Get(context.Background(), key, chart)
if chart.Status.Artifact != nil {
return chart.Status.Artifact.Revision
}
return ""
}, timeout, interval).Should(Equal("1.0.0"))
chart.Spec.Version = "<0.2.0"
Expect(k8sClient.Update(context.Background(), chart)).Should(Succeed())
Eventually(func() string {
_ = k8sClient.Get(context.Background(), key, chart)
if chart.Status.Artifact != nil {
return chart.Status.Artifact.Revision
}
return ""
}, timeout, interval).Should(Equal("0.1.1"))
chart.Spec.Version = "invalid"
Expect(k8sClient.Update(context.Background(), chart)).Should(Succeed())
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, chart)
return conditions.GetReason(chart, sourcev1.FetchFailedCondition) == "InvalidChartReference" &&
conditions.IsStalled(chart)
}, timeout, interval).Should(BeTrue())
Expect(chart.GetArtifact()).NotTo(BeNil())
Expect(chart.Status.Artifact.Revision).Should(Equal("0.1.1"))
})
It("Authenticates when credentials are provided", func() {
helmServer.Stop()
var username, password = "john", "doe"
helmServer.WithMiddleware(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, p, ok := r.BasicAuth()
if !ok || username != u || password != p {
w.WriteHeader(401)
return
}
handler.ServeHTTP(w, r)
})
})
helmServer.Start()
Expect(helmServer.PackageChartWithVersion(path.Join("testdata/charts/helmchart"), "0.1.0")).Should(Succeed())
Expect(helmServer.GenerateIndex()).Should(Succeed())
secretKey := types.NamespacedName{
Name: "helmrepository-auth-" + randStringRunes(5),
Namespace: namespace.Name,
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretKey.Name,
Namespace: secretKey.Namespace,
},
Data: map[string][]byte{
"username": []byte(username),
"password": []byte(password),
},
}
Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed())
By("Creating repository and waiting for artifact")
repositoryKey := types.NamespacedName{
Name: "helmrepository-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
repository := &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.HelmRepositorySpec{
URL: helmServer.URL(),
SecretRef: &meta.LocalObjectReference{
Name: secretKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), repository)
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), repositoryKey, repository)
return repository.Status.Artifact != nil
}, timeout, interval).Should(BeTrue())
By("Deleting secret before applying HelmChart")
Expect(k8sClient.Delete(context.Background(), secret)).Should(Succeed())
By("Applying HelmChart")
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
chart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: "helmchart",
Version: "*",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.HelmRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), chart)).Should(Succeed())
defer k8sClient.Delete(context.Background(), chart)
By("Expecting missing secret error")
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return conditions.GetReason(got, sourcev1.FetchFailedCondition) == sourcev1.AuthenticationFailedReason
}, timeout, interval).Should(BeTrue())
By("Applying secret with missing keys")
secret.ResourceVersion = ""
secret.Data["username"] = []byte{}
secret.Data["password"] = []byte{}
Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed())
By("Expecting 401")
Eventually(func() bool {
got := &sourcev1.HelmChart{}
_ = k8sClient.Get(context.Background(), key, got)
for _, c := range got.Status.Conditions {
if c.Reason == "ChartPullError" &&
strings.Contains(c.Message, "401 Unauthorized") {
return true
}
}
return false
}, timeout, interval).Should(BeTrue())
By("Adding username key")
secret.Data["username"] = []byte(username)
Expect(k8sClient.Update(context.Background(), secret)).Should(Succeed())
By("Expecting missing field error")
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
for _, c := range got.Status.Conditions {
if c.Reason == sourcev1.AuthenticationFailedReason {
return true
}
}
return false
}, timeout, interval).Should(BeTrue())
By("Adding password key")
secret.Data["password"] = []byte(password)
Expect(k8sClient.Update(context.Background(), secret)).Should(Succeed())
By("Expecting artifact")
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return apimeta.IsStatusConditionTrue(got.Status.Conditions, meta.ReadyCondition)
}, timeout, interval).Should(BeTrue())
Expect(got.Status.Artifact).ToNot(BeNil())
})
})
Context("HelmChart from GitRepository", func() {
var (
namespace *corev1.Namespace
gitServer *gittestserver.GitServer
err error
)
BeforeEach(func() {
namespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: "test-git-repository-" + randStringRunes(5)},
}
err = k8sClient.Create(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
gitServer, err = gittestserver.NewTempGitServer()
Expect(err).NotTo(HaveOccurred())
gitServer.AutoCreate()
Expect(gitServer.StartHTTP()).To(Succeed())
})
AfterEach(func() {
gitServer.StopHTTP()
os.RemoveAll(gitServer.Root())
err = k8sClient.Delete(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace")
})
It("Creates artifacts for", func() {
fs := memfs.New()
gitrepo, err := git.Init(memory.NewStorage(), fs)
Expect(err).NotTo(HaveOccurred())
wt, err := gitrepo.Worktree()
Expect(err).NotTo(HaveOccurred())
u, err := url.Parse(gitServer.HTTPAddress())
Expect(err).NotTo(HaveOccurred())
u.Path = path.Join(u.Path, fmt.Sprintf("repository-%s.git", randStringRunes(5)))
_, err = gitrepo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{u.String()},
})
Expect(err).NotTo(HaveOccurred())
chartDir := "testdata/charts"
Expect(filepath.Walk(chartDir, func(p string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
switch {
case fi.Mode().IsDir():
return fs.MkdirAll(p, os.ModeDir)
case !fi.Mode().IsRegular():
return nil
}
b, err := os.ReadFile(p)
if err != nil {
return err
}
ff, err := fs.Create(p)
if err != nil {
return err
}
if _, err := ff.Write(b); err != nil {
return err
}
_ = ff.Close()
_, err = wt.Add(p)
return err
})).To(Succeed())
_, err = wt.Commit("Helm charts", &git.CommitOptions{Author: &object.Signature{
Name: "John Doe",
Email: "john@example.com",
When: time.Now(),
}})
Expect(err).NotTo(HaveOccurred())
err = gitrepo.Push(&git.PushOptions{})
Expect(err).NotTo(HaveOccurred())
repositoryKey := types.NamespacedName{
Name: fmt.Sprintf("git-repository-sample-%s", randStringRunes(5)),
Namespace: namespace.Name,
}
repository := &sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: u.String(),
Interval: metav1.Duration{Duration: indexInterval},
},
}
Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), repository)
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
chart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: "testdata/charts/helmchartwithdeps",
Version: "*",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.GitRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), chart)).Should(Succeed())
defer k8sClient.Delete(context.Background(), chart)
By("Expecting artifact")
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact != nil &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
By("Committing a new version in the chart metadata")
f, err := fs.OpenFile(fs.Join(chartDir, "helmchartwithdeps", chartutil.ChartfileName), os.O_RDWR, os.FileMode(0600))
Expect(err).NotTo(HaveOccurred())
b := make([]byte, 2048)
n, err := f.Read(b)
Expect(err).NotTo(HaveOccurred())
b = b[0:n]
y := new(helmchart.Metadata)
err = yaml.Unmarshal(b, y)
Expect(err).NotTo(HaveOccurred())
y.Version = "0.2.0"
b, err = yaml.Marshal(y)
Expect(err).NotTo(HaveOccurred())
_, err = f.Write(b)
Expect(err).NotTo(HaveOccurred())
err = f.Close()
Expect(err).NotTo(HaveOccurred())
commit, err := wt.Commit("Chart version bump", &git.CommitOptions{
Author: &object.Signature{
Name: "John Doe",
Email: "john@example.com",
When: time.Now(),
},
All: true,
})
Expect(err).NotTo(HaveOccurred())
err = gitrepo.Push(&git.PushOptions{})
Expect(err).NotTo(HaveOccurred())
By("Expecting new artifact revision and GC")
now := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, now)
// Test revision change and garbage collection
return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
!ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*now.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(helmChart.Values).ToNot(BeNil())
Expect(helmChart.Values["testDefault"]).To(BeTrue())
Expect(helmChart.Values["testOverride"]).To(BeFalse())
When("Setting reconcileStrategy to Revision", func() {
updated := &sourcev1.HelmChart{}
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
updated.Spec.ReconcileStrategy = sourcev1.ReconcileStrategyRevision
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact.Revision != updated.Status.Artifact.Revision &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
Expect(got.Status.Artifact.Revision).To(ContainSubstring(updated.Status.Artifact.Revision))
Expect(got.Status.Artifact.Revision).To(ContainSubstring(commit.String()[0:12]))
})
When("Setting valid valuesFiles attribute", func() {
updated := &sourcev1.HelmChart{}
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
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 {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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{
"./testdata/charts/helmchart/values.yaml",
"./testdata/charts/helmchart/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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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)
// Since a lot of chart updates took place above, checking
// artifact checksum isn't the most reliable way to find out
// if the artifact was changed due to the current update.
// Use status condition to be sure.
for _, condn := range got.Status.Conditions {
if strings.Contains(condn.Message, "merged values files [./testdata/charts/helmchart/override.yaml]") &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact) {
return true
}
}
return false
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
_, exists := helmChart.Values["testDefault"]
Expect(exists).To(BeFalse())
Expect(helmChart.Values["testOverride"]).To(BeTrue())
})
})
It("Creates artifacts with .tgz file", func() {
fs := memfs.New()
gitrepo, err := git.Init(memory.NewStorage(), fs)
Expect(err).NotTo(HaveOccurred())
wt, err := gitrepo.Worktree()
Expect(err).NotTo(HaveOccurred())
u, err := url.Parse(gitServer.HTTPAddress())
Expect(err).NotTo(HaveOccurred())
u.Path = path.Join(u.Path, fmt.Sprintf("repository-%s.git", randStringRunes(5)))
_, err = gitrepo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{u.String()},
})
Expect(err).NotTo(HaveOccurred())
chartDir := "testdata/charts/helmchart"
helmChart, err := loader.LoadDir(chartDir)
Expect(err).NotTo(HaveOccurred())
chartPackagePath, err := os.MkdirTemp("", fmt.Sprintf("chartpackage-%s-%s", helmChart.Name(), randStringRunes(5)))
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(chartPackagePath)
pkg, err := chartutil.Save(helmChart, chartPackagePath)
Expect(err).NotTo(HaveOccurred())
b, err := os.ReadFile(pkg)
Expect(err).NotTo(HaveOccurred())
tgz := filepath.Base(pkg)
ff, err := fs.Create(tgz)
Expect(err).NotTo(HaveOccurred())
_, err = ff.Write(b)
Expect(err).NotTo(HaveOccurred())
ff.Close()
_, err = wt.Add(tgz)
Expect(err).NotTo(HaveOccurred())
_, err = wt.Commit("Helm chart", &git.CommitOptions{Author: &object.Signature{
Name: "John Doe",
Email: "john@example.com",
When: time.Now(),
}})
Expect(err).NotTo(HaveOccurred())
err = gitrepo.Push(&git.PushOptions{})
Expect(err).NotTo(HaveOccurred())
repositoryKey := types.NamespacedName{
Name: fmt.Sprintf("git-repository-sample-%s", randStringRunes(5)),
Namespace: namespace.Name,
}
repository := &sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: u.String(),
Interval: metav1.Duration{Duration: indexInterval},
},
}
Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), repository)
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
chart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: tgz,
Version: "*",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.GitRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), chart)).Should(Succeed())
defer k8sClient.Delete(context.Background(), chart)
By("Expecting artifact")
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact != nil &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
})
})
Context("HelmChart from GitRepository with HelmRepository dependency", func() {
var (
namespace *corev1.Namespace
gitServer *gittestserver.GitServer
helmServer *helmtestserver.HelmServer
err error
)
BeforeEach(func() {
namespace = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: "test-git-repository-" + randStringRunes(5)},
}
err = k8sClient.Create(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
gitServer, err = gittestserver.NewTempGitServer()
Expect(err).NotTo(HaveOccurred())
gitServer.AutoCreate()
Expect(gitServer.StartHTTP()).To(Succeed())
helmServer, err = helmtestserver.NewTempHelmServer()
Expect(err).To(Succeed())
helmServer.Start()
})
AfterEach(func() {
gitServer.StopHTTP()
os.RemoveAll(gitServer.Root())
helmServer.Stop()
os.RemoveAll(helmServer.Root())
err = k8sClient.Delete(context.Background(), namespace)
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace")
})
It("Creates artifacts for", func() {
helmServer.Stop()
var username, password = "john", "doe"
helmServer.WithMiddleware(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, p, ok := r.BasicAuth()
if !ok || username != u || password != p {
w.WriteHeader(401)
return
}
handler.ServeHTTP(w, r)
})
})
helmServer.Start()
Expect(helmServer.PackageChart(path.Join("testdata/charts/helmchart"))).Should(Succeed())
Expect(helmServer.GenerateIndex()).Should(Succeed())
secretKey := types.NamespacedName{
Name: "helmrepository-auth-" + randStringRunes(5),
Namespace: namespace.Name,
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretKey.Name,
Namespace: secretKey.Namespace,
},
StringData: map[string]string{
"username": username,
"password": password,
},
}
Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed())
By("Creating repository and waiting for artifact")
helmRepositoryKey := types.NamespacedName{
Name: "helmrepository-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
helmRepository := &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{
Name: helmRepositoryKey.Name,
Namespace: helmRepositoryKey.Namespace,
},
Spec: sourcev1.HelmRepositorySpec{
URL: helmServer.URL(),
SecretRef: &meta.LocalObjectReference{
Name: secretKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), helmRepository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), helmRepository)
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), helmRepositoryKey, helmRepository)
return helmRepository.Status.Artifact != nil
}, timeout, interval).Should(BeTrue())
fs := memfs.New()
gitrepo, err := git.Init(memory.NewStorage(), fs)
Expect(err).NotTo(HaveOccurred())
wt, err := gitrepo.Worktree()
Expect(err).NotTo(HaveOccurred())
u, err := url.Parse(gitServer.HTTPAddress())
Expect(err).NotTo(HaveOccurred())
u.Path = path.Join(u.Path, fmt.Sprintf("repository-%s.git", randStringRunes(5)))
_, err = gitrepo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{u.String()},
})
Expect(err).NotTo(HaveOccurred())
chartDir := "testdata/charts/helmchartwithdeps"
Expect(filepath.Walk(chartDir, func(p string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
switch {
case fi.Mode().IsDir():
return fs.MkdirAll(p, os.ModeDir)
case !fi.Mode().IsRegular():
return nil
}
b, err := os.ReadFile(p)
if err != nil {
return err
}
ff, err := fs.Create(p)
if err != nil {
return err
}
if _, err := ff.Write(b); err != nil {
return err
}
_ = ff.Close()
_, err = wt.Add(p)
return err
})).To(Succeed())
By("Configuring the chart dependency")
filePath := fs.Join(chartDir, chartutil.ChartfileName)
f, err := fs.OpenFile(filePath, os.O_RDWR, os.FileMode(0600))
Expect(err).NotTo(HaveOccurred())
b := make([]byte, 2048)
n, err := f.Read(b)
Expect(err).NotTo(HaveOccurred())
b = b[0:n]
err = f.Close()
Expect(err).NotTo(HaveOccurred())
y := new(helmchart.Metadata)
err = yaml.Unmarshal(b, y)
Expect(err).NotTo(HaveOccurred())
y.Dependencies = []*helmchart.Dependency{
{
Name: "helmchart",
Version: ">=0.1.0",
Repository: helmRepository.Spec.URL,
},
}
b, err = yaml.Marshal(y)
Expect(err).NotTo(HaveOccurred())
ff, err := fs.Create(filePath)
Expect(err).NotTo(HaveOccurred())
_, err = ff.Write(b)
Expect(err).NotTo(HaveOccurred())
err = ff.Close()
Expect(err).NotTo(HaveOccurred())
_, err = wt.Commit("Helm charts", &git.CommitOptions{
Author: &object.Signature{
Name: "John Doe",
Email: "john@example.com",
When: time.Now(),
},
All: true,
})
Expect(err).NotTo(HaveOccurred())
err = gitrepo.Push(&git.PushOptions{})
Expect(err).NotTo(HaveOccurred())
repositoryKey := types.NamespacedName{
Name: fmt.Sprintf("git-repository-sample-%s", randStringRunes(5)),
Namespace: namespace.Name,
}
repository := &sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: repositoryKey.Name,
Namespace: repositoryKey.Namespace,
},
Spec: sourcev1.GitRepositorySpec{
URL: u.String(),
Interval: metav1.Duration{Duration: indexInterval},
},
}
Expect(k8sClient.Create(context.Background(), repository)).Should(Succeed())
defer k8sClient.Delete(context.Background(), repository)
key := types.NamespacedName{
Name: "helmchart-sample-" + randStringRunes(5),
Namespace: namespace.Name,
}
chart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: sourcev1.HelmChartSpec{
Chart: "testdata/charts/helmchartwithdeps",
Version: "*",
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourcev1.GitRepositoryKind,
Name: repositoryKey.Name,
},
Interval: metav1.Duration{Duration: pullInterval},
},
}
Expect(k8sClient.Create(context.Background(), chart)).Should(Succeed())
defer k8sClient.Delete(context.Background(), chart)
By("Expecting artifact")
got := &sourcev1.HelmChart{}
Eventually(func() bool {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact != nil &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(helmChart.Values["testDefault"]).To(BeTrue())
Expect(helmChart.Values["testOverride"]).To(BeFalse())
When("Setting valid valuesFiles attribute", func() {
updated := &sourcev1.HelmChart{}
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
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 {
_ = k8sClient.Get(context.Background(), key, got)
return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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{
"./testdata/charts/helmchartwithdeps/values.yaml",
"./testdata/charts/helmchartwithdeps/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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.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 &&
ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
}, timeout, interval).Should(BeTrue())
f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
Expect(f.Size()).To(BeNumerically(">", 0))
helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
Expect(err).NotTo(HaveOccurred())
_, exists := helmChart.Values["testDefault"]
Expect(exists).To(BeFalse())
Expect(helmChart.Values["testOverride"]).To(BeTrue())
})
})
})
})