Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions e2e/assets/gitrepo/helm-recreate-drift-gitrepo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
kind: GitRepo
apiVersion: fleet.cattle.io/v1alpha1
metadata:
name: {{ .Name }}
spec:
repo: {{ .Repo }}
branch: {{ .Branch }}
clientSecretName: git-auth
paths:
- helm-recreate-drift
6 changes: 6 additions & 0 deletions e2e/assets/helm-recreate-drift/chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: helm-v4-drift-test-chart
description: Test chart with RollingUpdate deployment strategy for Helm v4 drift detection
type: application
version: 0.1.0
appVersion: "1.0.0"
21 changes: 21 additions & 0 deletions e2e/assets/helm-recreate-drift/chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
replicas: {{ .Values.replicas | default 1 }}
selector:
matchLabels:
app: test-app
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: test-app
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
7 changes: 7 additions & 0 deletions e2e/assets/helm-recreate-drift/fleet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace: helm-recreate-drift-test

helm:
chart: chart
releaseName: recreate-strategy-test
values:
replicas: 1
146 changes: 146 additions & 0 deletions e2e/single-cluster/helm_recreate_drift_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package singlecluster_test

import (
"fmt"
"math/rand"
"os"
"path"
"strings"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/rancher/fleet/e2e/testenv"
"github.com/rancher/fleet/e2e/testenv/githelper"
"github.com/rancher/fleet/e2e/testenv/kubectl"
)

var _ = Describe("Helm v4 Null Field Drift Detection", Label("infra-setup"), func() {
var (
tmpDir string
clonedir string
k kubectl.Command
gh *githelper.Git
localRepoName string
inClusterRepoURL string
gitrepoName string
r = rand.New(rand.NewSource(GinkgoRandomSeed()))
gitServerPort int
gitProtocol string
)

BeforeEach(func() {
k = env.Kubectl.Namespace(env.Namespace)
gitServerPort = 8080
gitProtocol = "http"
localRepoName = "repo"
})

JustBeforeEach(func() {
// Build git repo URL reachable _within_ the cluster, for the GitRepo
host := githelper.BuildGitHostname()

addr, err := githelper.GetExternalRepoAddr(env, gitServerPort, localRepoName)
Expect(err).ToNot(HaveOccurred())
addr = strings.Replace(addr, "http://", fmt.Sprintf("%s://", gitProtocol), 1)
gh = githelper.NewHTTP(addr)

inClusterRepoURL = gh.GetInClusterURL(host, gitServerPort, localRepoName)

tmpDir, _ = os.MkdirTemp("", "fleet-")
clonedir = path.Join(tmpDir, localRepoName)

gitrepoName = testenv.RandomFilename("helm-recreate-drift", r)
})

AfterEach(func() {
_ = os.RemoveAll(tmpDir)

_, _ = k.Delete("gitrepo", gitrepoName)
_, _ = k.Delete("secret", "git-auth")
_, _ = k.Delete("namespace", "helm-recreate-drift-test")

// Check that the bundle deployment resource has been deleted
Eventually(func(g Gomega) {
out, _ := k.Get(
"bundledeployments",
"-A",
"-l",
fmt.Sprintf("fleet.cattle.io/repo-name=%s", gitrepoName),
)
g.Expect(out).To(ContainSubstring("No resources found"))
}).Should(Succeed())
})

When("deploying a Helm chart with fields omitted by Helm v4", func() {
JustBeforeEach(func() {
// Create git auth secret
_, err := k.Create(
"secret", "generic", "git-auth", "--type", "kubernetes.io/basic-auth",
"--from-literal=username="+os.Getenv("GIT_HTTP_USER"),
"--from-literal=password="+os.Getenv("GIT_HTTP_PASSWORD"),
)
Expect(err).ToNot(HaveOccurred())

err = testenv.ApplyTemplate(k, testenv.AssetPath("gitrepo/helm-recreate-drift-gitrepo.yaml"), struct {
Name string
Repo string
Branch string
}{
Name: gitrepoName,
Repo: inClusterRepoURL,
Branch: gh.Branch,
})
Expect(err).ToNot(HaveOccurred())

_, err = gh.Create(clonedir, testenv.AssetPath("helm-recreate-drift"), "helm-recreate-drift")
Expect(err).ToNot(HaveOccurred())
})

It("should not detect drift from Helm v4 rendering", func() {
By("checking the bundle is ready")
Eventually(func(g Gomega) {
out, err := k.Get("bundles", "-A", "-l", fmt.Sprintf("fleet.cattle.io/repo-name=%s", gitrepoName))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).To(ContainSubstring("fleet-local"))
}, testenv.MediumTimeout, testenv.ShortTimeout).Should(Succeed())

By("checking the bundle deployment is ready")
var bundleDeploymentName, bdNamespace string
Eventually(func(g Gomega) {
out, err := k.Get("bundledeployments", "-A", "-o", "jsonpath={.items[0]['metadata.name','metadata.namespace']}", "-l", fmt.Sprintf("fleet.cattle.io/repo-name=%s", gitrepoName))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).ToNot(BeEmpty())

data := strings.Split(out, " ")
g.Expect(data).To(HaveLen(2))
bundleDeploymentName, bdNamespace = data[0], data[1]
}, testenv.MediumTimeout, testenv.ShortTimeout).Should(Succeed())

Eventually(func(g Gomega) {
out, err := k.Namespace(bdNamespace).Get("bundledeployments", bundleDeploymentName, "-o", "jsonpath={.status.ready}")
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).To(Equal("true"))
}, testenv.MediumTimeout, testenv.ShortTimeout).Should(Succeed())

By("checking the deployment has RollingUpdate strategy")
Eventually(func(g Gomega) {
out, err := k.Namespace("helm-recreate-drift-test").Get("deployments", "test-deployment", "-o", "jsonpath={.spec.strategy.type}")
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).To(Equal("RollingUpdate"))
}, testenv.MediumTimeout, testenv.ShortTimeout).Should(Succeed())

By("verifying that no drift is detected")
Eventually(func(g Gomega) {
out, err := k.Namespace(bdNamespace).Get("bundledeployments", bundleDeploymentName, "-o", "jsonpath={.status.nonModified}")
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).To(Equal("true"), "BundleDeployment should not show drift from Helm v4 rendering")

// Also check that modifiedStatus is empty
out, err = k.Namespace(bdNamespace).Get("bundledeployments", bundleDeploymentName, "-o", "jsonpath={.status.modifiedStatus}")
g.Expect(err).ToNot(HaveOccurred())
g.Expect(out).To(BeEmpty(), "modifiedStatus should be empty when no drift is detected")
}, testenv.MediumTimeout, testenv.ShortTimeout).Should(Succeed())
})
})
})
Loading
Loading