Skip to content

Commit df9368a

Browse files
committed
helm(e2e): test helm plugin integration
this will test the usage and impact to an existing project by the kubebuilder edit command for the helm plugin. Signed-off-by: Mario Constanti <[email protected]>
1 parent 3074a10 commit df9368a

File tree

4 files changed

+277
-0
lines changed

4 files changed

+277
-0
lines changed

pkg/plugin/util/util_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,60 @@ var _ = Describe("Cover plugin util helpers", func() {
101101
Expect(lines).To(Equal([]string{"noemptylines"}))
102102
})
103103
})
104+
105+
Describe("HasFileContentWith", Ordered, func() {
106+
const (
107+
path = "testdata/PROJECT"
108+
content = `# Code generated by tool. DO NOT EDIT.
109+
# This file is used to track the info used to scaffold your project
110+
# and allow the plugins properly work.
111+
# More info: https://book.kubebuilder.io/reference/project-config.html
112+
domain: example.org
113+
layout:
114+
- go.kubebuilder.io/v4
115+
- helm.kubebuilder.io/v1-alpha
116+
plugins:
117+
helm.kubebuilder.io/v1-alpha: {}
118+
repo: github.com/example/repo
119+
version: "3"
120+
`
121+
)
122+
123+
BeforeAll(func() {
124+
err := os.MkdirAll("testdata", 0o755)
125+
Expect(err).NotTo(HaveOccurred())
126+
127+
if _, err = os.Stat(path); os.IsNotExist(err) {
128+
err = os.WriteFile(path, []byte(content), 0o644)
129+
Expect(err).NotTo(HaveOccurred())
130+
}
131+
})
132+
133+
AfterAll(func() {
134+
err := os.RemoveAll("testdata")
135+
Expect(err).NotTo(HaveOccurred())
136+
})
137+
138+
It("should return true when file contains the expected content", func() {
139+
content := "repo: github.com/example/repo"
140+
found, err := HasFileContentWith(path, content)
141+
Expect(err).NotTo(HaveOccurred())
142+
Expect(found).To(BeTrue())
143+
})
144+
145+
It("should return true when file contains multiline expected content", func() {
146+
content := `plugins:
147+
helm.kubebuilder.io/v1-alpha: {}`
148+
found, err := HasFileContentWith(path, content)
149+
Expect(err).NotTo(HaveOccurred())
150+
Expect(found).To(BeTrue())
151+
})
152+
153+
It("should return false when file does not contain the expected content", func() {
154+
content := "nonExistentContent"
155+
found, err := HasFileContentWith(path, content)
156+
Expect(err).NotTo(HaveOccurred())
157+
Expect(found).To(BeFalse())
158+
})
159+
})
104160
})

test/e2e/helm/e2e_suite_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package helm
15+
16+
import (
17+
"fmt"
18+
"testing"
19+
20+
. "github.com/onsi/ginkgo/v2"
21+
. "github.com/onsi/gomega"
22+
)
23+
24+
// Run e2e tests using the Ginkgo runner.
25+
func TestE2E(t *testing.T) {
26+
RegisterFailHandler(Fail)
27+
_, _ = fmt.Fprintf(GinkgoWriter, "Starting helm plugin kubebuilder suite\n")
28+
RunSpecs(t, "Kubebuilder helm plugin e2e suite")
29+
}

test/e2e/helm/generate_test.go

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package helm
18+
19+
import (
20+
"path/filepath"
21+
22+
pluginutil "sigs.k8s.io/kubebuilder/v4/pkg/plugin/util"
23+
24+
. "github.com/onsi/ginkgo/v2"
25+
26+
. "github.com/onsi/gomega"
27+
28+
"sigs.k8s.io/kubebuilder/v4/test/e2e/utils"
29+
)
30+
31+
var _ = Describe("kubebuilder", func() {
32+
Context("plugin helm/v1-alpha", func() {
33+
var kbc *utils.TestContext
34+
35+
BeforeEach(func() {
36+
var err error
37+
kbc, err = utils.NewTestContext(pluginutil.KubebuilderBinName, "GO111MODULE=on")
38+
Expect(err).NotTo(HaveOccurred())
39+
Expect(kbc.Prepare()).To(Succeed())
40+
})
41+
42+
AfterEach(func() {
43+
kbc.Destroy()
44+
})
45+
46+
It("should extend a runnable project with helm plugin", func() {
47+
initTheProject(kbc)
48+
49+
By("extend the project by adding helm plugin")
50+
err := kbc.Edit(
51+
"--plugins", "helm.kubebuilder.io/v1-alpha",
52+
)
53+
Expect(err).NotTo(HaveOccurred(), "Failed to edit the project")
54+
55+
ensureCommonHelmFilesContent(kbc)
56+
})
57+
58+
// This test is to ensure that the helm plugin can be added to a project
59+
// that has already been initialized with the go/v4 plugin.
60+
// As the project is getting extended with webhooks,
61+
// it is needed to run the `kubebuilder edit --plugins helm.kubebuilder.io/v1-alpha` command
62+
// with ` --force` again to ensure that the webhooks are enabled in the
63+
// values.yaml file.
64+
It("should extend a runnable project with helm plugin and webhooks", func() {
65+
initTheProject(kbc)
66+
67+
By("extend the project by adding helm plugin")
68+
err := kbc.Edit(
69+
"--plugins", "helm.kubebuilder.io/v1-alpha",
70+
)
71+
Expect(err).NotTo(HaveOccurred(), "Failed to edit the project")
72+
73+
ensureCommonHelmFilesContent(kbc)
74+
extendProjectWithWebhooks(kbc)
75+
76+
// after creating webhooks, we want to have the webhooks enabled
77+
// in the values.yaml file, so we need to run `kubebuilder edit`
78+
// with the --force flag for the helm plugin.
79+
By("re-edit the project after creating webhooks")
80+
err = kbc.Edit(
81+
"--plugins", "helm.kubebuilder.io/v1-alpha", "--force",
82+
)
83+
Expect(err).NotTo(HaveOccurred(), "Failed to edit the project")
84+
85+
fileContainsExpr, err := pluginutil.HasFileContentWith(
86+
filepath.Join(kbc.Dir, "dist", "chart", "values.yaml"),
87+
`webhook:
88+
enable: true`)
89+
Expect(err).NotTo(HaveOccurred(), "Failed to read values.yaml file")
90+
Expect(fileContainsExpr).To(BeTrue(), "Failed to get enabled webhook value from values.yaml file")
91+
})
92+
93+
// Without --force, the webhooks should not be enabled in the values.yaml file.
94+
It("should extend a runnable project with helm plugin and webhooks but not running with --force", func() {
95+
initTheProject(kbc)
96+
97+
By("extend the project by adding helm plugin")
98+
err := kbc.Edit(
99+
"--plugins", "helm.kubebuilder.io/v1-alpha",
100+
)
101+
Expect(err).NotTo(HaveOccurred(), "Failed to edit the project")
102+
103+
ensureCommonHelmFilesContent(kbc)
104+
extendProjectWithWebhooks(kbc)
105+
106+
By("re-edit the project after creating webhooks without --force")
107+
err = kbc.Edit(
108+
"--plugins", "helm.kubebuilder.io/v1-alpha",
109+
)
110+
Expect(err).NotTo(HaveOccurred(), "Failed to edit the project")
111+
112+
fileContainsExpr, err := pluginutil.HasFileContentWith(
113+
filepath.Join(kbc.Dir, "dist", "chart", "values.yaml"),
114+
`webhook:
115+
enable: true`)
116+
Expect(err).NotTo(HaveOccurred(), "Failed to read values.yaml file")
117+
Expect(fileContainsExpr).To(BeFalse(), "Failed to get enabled webhook value from values.yaml file")
118+
})
119+
})
120+
})
121+
122+
// ensureCommonHelmFilesContent tests common helm-chart files which got
123+
// generated by the helm/v1(-alpha) plugin
124+
func ensureCommonHelmFilesContent(kbc *utils.TestContext) {
125+
var err error
126+
127+
fileContainsExpr, err := pluginutil.HasFileContentWith(
128+
filepath.Join(kbc.Dir, "PROJECT"),
129+
`helm.kubebuilder.io/v1-alpha: {}`)
130+
Expect(err).NotTo(HaveOccurred(), "Failed to read PROJECT file")
131+
Expect(fileContainsExpr).To(BeTrue(), "Failed to find helm plugin in PROJECT file")
132+
133+
fileContainsExpr, err = pluginutil.HasFileContentWith(
134+
filepath.Join(kbc.Dir, "PROJECT"),
135+
"projectName: e2e-"+kbc.TestSuffix)
136+
Expect(err).NotTo(HaveOccurred(), "Failed to read PROJECT file")
137+
Expect(fileContainsExpr).To(BeTrue(), "Failed to find projectName in PROJECT file")
138+
139+
fileContainsExpr, err = pluginutil.HasFileContentWith(
140+
filepath.Join(kbc.Dir, "dist", "chart", "Chart.yaml"),
141+
"name: e2e-"+kbc.TestSuffix)
142+
Expect(err).NotTo(HaveOccurred(), "Failed to read Chart.yaml file")
143+
Expect(fileContainsExpr).To(BeTrue(), "Failed to find name in Chart.yaml file")
144+
145+
fileContainsExpr, err = pluginutil.HasFileContentWith(
146+
filepath.Join(kbc.Dir, "dist", "chart", "templates", "manager", "manager.yaml"),
147+
`metadata:
148+
name: e2e-`+kbc.TestSuffix)
149+
Expect(err).NotTo(HaveOccurred(), "Failed to read manager.yaml file")
150+
Expect(fileContainsExpr).To(BeTrue(), "Failed to find name in helm template manager.yaml file")
151+
}
152+
153+
// extendProjectWithWebhooks is creating API and scaffolding webhooks in the project
154+
func extendProjectWithWebhooks(kbc *utils.TestContext) {
155+
By("creating API definition")
156+
err := kbc.CreateAPI(
157+
"--group", kbc.Group,
158+
"--version", kbc.Version,
159+
"--kind", kbc.Kind,
160+
"--namespaced",
161+
"--resource",
162+
"--controller",
163+
"--make=false",
164+
)
165+
Expect(err).NotTo(HaveOccurred(), "Failed to create API")
166+
167+
By("scaffolding mutating and validating webhooks")
168+
err = kbc.CreateWebhook(
169+
"--group", kbc.Group,
170+
"--version", kbc.Version,
171+
"--kind", kbc.Kind,
172+
"--defaulting",
173+
"--programmatic-validation",
174+
"--make=false",
175+
)
176+
Expect(err).NotTo(HaveOccurred(), "Failed to scaffolding mutating webhook")
177+
178+
By("run make manifests")
179+
Expect(kbc.Make("manifests")).To(Succeed())
180+
}
181+
182+
// initTheProject initializes a project with the go/v4 plugin and sets the domain.
183+
func initTheProject(kbc *utils.TestContext) {
184+
By("initializing a project")
185+
err := kbc.Init(
186+
"--plugins", "go/v4",
187+
"--project-version", "3",
188+
"--domain", kbc.Domain,
189+
)
190+
Expect(err).NotTo(HaveOccurred(), "Failed to initialize project")
191+
}

test/e2e/setup.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ function test_cluster {
6565
kind load docker-image --name $KIND_CLUSTER busybox:1.36.1
6666

6767
go test $(dirname "$0")/grafana $flags -timeout 30m
68+
go test $(dirname "$0")/helm $flags -timeout 30m
6869
go test $(dirname "$0")/deployimage $flags -timeout 30m
6970
go test $(dirname "$0")/v4 $flags -timeout 30m
7071
go test $(dirname "$0")/alphagenerate $flags -timeout 30m

0 commit comments

Comments
 (0)