Skip to content

Commit 88726be

Browse files
author
Mengqi Yu
committed
add e2e test for v1 kubebuilder
1 parent 6bb9d63 commit 88726be

File tree

6 files changed

+314
-39
lines changed

6 files changed

+314
-39
lines changed

common.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ function setup_envs {
142142
header_text "setting up env vars"
143143

144144
# Setup env vars
145-
export PATH=/tmp/kubebuilder/bin/:$PATH
145+
export PATH=/tmp/kubebuilder/bin:$PATH
146146
export TEST_ASSET_KUBECTL=/tmp/kubebuilder/bin/kubectl
147147
export TEST_ASSET_KUBE_APISERVER=/tmp/kubebuilder/bin/kube-apiserver
148148
export TEST_ASSET_ETCD=/tmp/kubebuilder/bin/etcd

test/e2e/common.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright 2018 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 e2e
18+
19+
import (
20+
"log"
21+
"os"
22+
"path/filepath"
23+
24+
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework"
25+
e2einternal "github.com/kubernetes-sigs/kubebuilder/test/internal/e2e"
26+
. "github.com/onsi/ginkgo"
27+
. "github.com/onsi/gomega"
28+
)
29+
30+
func prepare(workDir string) {
31+
By("create a path under given project dir, as the test work dir")
32+
err := os.MkdirAll(workDir, 0755)
33+
Expect(err).NotTo(HaveOccurred())
34+
}
35+
36+
func cleanupv0(builderTest *e2einternal.KubebuilderTest, workDir string, imageName string) {
37+
By("clean up created API objects during test process")
38+
inputFile := filepath.Join(workDir, "hack", "install.yaml")
39+
deleteOptions := []string{"delete", "-f", inputFile}
40+
builderTest.RunKubectlCommand(framework.GetKubectlArgs(deleteOptions))
41+
42+
By("remove container image created during test")
43+
builderTest.CleanupImage([]string{imageName})
44+
45+
By("remove test work dir")
46+
os.RemoveAll(workDir)
47+
}
48+
49+
func cleanupv1(builderTest *e2einternal.KubebuilderTest, workDir string, imageName string) {
50+
By("clean up created API objects during test process")
51+
52+
kustomizeOptions := []string{"build", filepath.Join("config", "default")}
53+
resources, err := builderTest.RunKustomizeCommand(kustomizeOptions)
54+
if err != nil {
55+
log.Printf("error when runing kustomize build during cleaning up: %v", err)
56+
}
57+
58+
deleteOptions := []string{"delete", "--recursive", "-f", "-"}
59+
_, err = builderTest.RunKubectlCommandWithInput(framework.GetKubectlArgs(deleteOptions), resources)
60+
if err != nil {
61+
log.Printf("error when runing kubectl delete during cleaning up: %v", err)
62+
}
63+
64+
deleteOptions = []string{"delete", "--recursive", "-f", filepath.Join("config", "crds")}
65+
_, err = builderTest.RunKubectlCommand(framework.GetKubectlArgs(deleteOptions))
66+
67+
By("remove container image created during test")
68+
builderTest.CleanupImage([]string{imageName})
69+
70+
By("remove test work dir")
71+
os.RemoveAll(workDir)
72+
}

test/e2e/e2e_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ limitations under the License.
1717
package e2e
1818

1919
import (
20+
"log"
21+
"os"
22+
"os/exec"
23+
"path"
24+
"strings"
2025
"testing"
2126

27+
"github.com/golang/glog"
2228
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework"
29+
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework/ginkgowrapper"
30+
. "github.com/onsi/ginkgo"
31+
. "github.com/onsi/gomega"
2332
"github.com/spf13/pflag"
2433
)
2534

@@ -28,6 +37,51 @@ func init() {
2837
pflag.Parse()
2938
}
3039

40+
var kubebuilderBinDir string
41+
42+
/*
43+
2 steps to do before running the e2e test suite
44+
1) go build a new kubebuilder binary
45+
2) install all required binaries, such as etcd and kube-apiserver
46+
If you have run testv0.sh or testv1.sh before running this e2e suite,
47+
it will build the new kubebuilder.
48+
*/
49+
// TODO: ensure the required binaries are installed when integrate with Prow.
50+
var _ = BeforeSuite(func(done Done) {
51+
// Uncomment the following line to set the image name before runing the e2e test
52+
//os.Setenv("IMG", "gcr.io/<my-project-name>/<iamge-name:tag>")
53+
// If you want to run the test against a GKE cluster, run the following command first
54+
// $ kubectl create clusterrolebinding myname-cluster-admin-binding --clusterrole=cluster-admin [email protected]
55+
framework.TestContext.BinariesDir = "/tmp/kubebuilder/bin/"
56+
// build a kubebuilder
57+
targets := []string{"kubebuilder", "kubebuilder-gen"}
58+
for _, target := range targets {
59+
buildOptions := []string{
60+
"build", "-o", path.Join(framework.TestContext.BinariesDir, target), path.Join("github.com/kubernetes-sigs/kubebuilder/cmd", target)}
61+
cmd := exec.Command("go", buildOptions...)
62+
cmd.Env = os.Environ()
63+
command := strings.Join(cmd.Args, " ")
64+
log.Printf("running %v", command)
65+
output, err := cmd.CombinedOutput()
66+
log.Printf("output when running:\n%s", output)
67+
Expect(err).NotTo(HaveOccurred())
68+
}
69+
70+
close(done)
71+
}, 60)
72+
73+
var _ = AfterSuite(func() {
74+
os.RemoveAll(kubebuilderBinDir)
75+
})
76+
77+
// RunE2ETests checks configuration parameters (specified through flags) and then runs
78+
// E2E tests using the Ginkgo runner.
79+
func RunE2ETests(t *testing.T) {
80+
RegisterFailHandler(ginkgowrapper.Fail)
81+
glog.Infof("Starting kubebuilder suite")
82+
RunSpecs(t, "Kubebuilder e2e suite")
83+
}
84+
3185
func TestE2E(t *testing.T) {
3286
RunE2ETests(t)
3387
}

test/e2e/e2e.go renamed to test/e2e/e2e_v0.go

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
66
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
1010
Unless required by applicable law or agreed to in writing, software
1111
distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,42 +18,30 @@ package e2e
1818

1919
import (
2020
"fmt"
21-
"os"
2221
"path/filepath"
2322
"strings"
24-
"testing"
2523
"time"
2624

27-
"github.com/golang/glog"
2825
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
2926
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework"
30-
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework/ginkgowrapper"
3127
e2einternal "github.com/kubernetes-sigs/kubebuilder/test/internal/e2e"
3228
. "github.com/onsi/ginkgo"
3329
. "github.com/onsi/gomega"
3430
)
3531

36-
// RunE2ETests checks configuration parameters (specified through flags) and then runs
37-
// E2E tests using the Ginkgo runner.
38-
func RunE2ETests(t *testing.T) {
39-
RegisterFailHandler(ginkgowrapper.Fail)
40-
glog.Infof("Starting kubebuilder suite")
41-
RunSpecs(t, "Kubebuilder e2e suite")
42-
}
43-
44-
var _ = Describe("main workflow", func() {
32+
var _ = Describe("v0 main workflow", func() {
4533
It("should perform main kubebuilder workflow successfully", func() {
4634
testSuffix := framework.RandomSuffix()
4735
c := initConfig(testSuffix)
4836
kubebuilderTest := e2einternal.NewKubebuilderTest(c.workDir, framework.TestContext.BinariesDir)
4937

5038
prepare(c.workDir)
51-
defer cleanup(kubebuilderTest, c.workDir, c.controllerImageName)
39+
defer cleanupv0(kubebuilderTest, c.workDir, c.controllerImageName)
5240

5341
var controllerPodName string
5442

5543
By("init project")
56-
initOptions := []string{"--domain", c.domain}
44+
initOptions := []string{"--domain", c.domain, "--project-version", "v0"}
5745
err := kubebuilderTest.Init(initOptions)
5846
Expect(err).NotTo(HaveOccurred())
5947

@@ -86,7 +74,7 @@ var _ = Describe("main workflow", func() {
8674
Expect(err).NotTo(HaveOccurred())
8775

8876
By("installing controller-manager in cluster")
89-
inputFile := filepath.Join(kubebuilderTest.Dir, "hack", "install.yaml")
77+
inputFile := filepath.Join("hack", "install.yaml")
9078
installOptions := []string{"apply", "-f", inputFile}
9179
_, err = kubebuilderTest.RunKubectlCommand(framework.GetKubectlArgs(installOptions))
9280
Expect(err).NotTo(HaveOccurred())
@@ -104,7 +92,7 @@ var _ = Describe("main workflow", func() {
10492
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
10593
}
10694
controllerPodName = podNames[0]
107-
Expect(controllerPodName).Should(HavePrefix(c.installName+"-controller-manager"))
95+
Expect(controllerPodName).Should(HavePrefix(c.installName + "-controller-manager"))
10896

10997
// Validate pod status
11098
getOptions = []string{"get", "pods", controllerPodName, "-n", c.namespace, "-o", "jsonpath={.status.phase}"}
@@ -150,22 +138,3 @@ var _ = Describe("main workflow", func() {
150138
Eventually(controllerContainerLogs, 1*time.Minute, 500*time.Millisecond).Should(ContainSubstring("to reconcile deployment-example"))
151139
})
152140
})
153-
154-
func prepare(workDir string) {
155-
By("create a path under given project dir, as the test work dir")
156-
err := os.MkdirAll(workDir, 0755)
157-
Expect(err).NotTo(HaveOccurred())
158-
}
159-
160-
func cleanup(builderTest *e2einternal.KubebuilderTest, workDir string, imageName string) {
161-
By("clean up created API objects during test process")
162-
inputFile := filepath.Join(workDir, "hack", "install.yaml")
163-
createOptions := []string{"delete", "-f", inputFile}
164-
builderTest.RunKubectlCommand(framework.GetKubectlArgs(createOptions))
165-
166-
By("remove container image created during test")
167-
builderTest.CleanupImage([]string{imageName})
168-
169-
By("remove test work dir")
170-
os.RemoveAll(workDir)
171-
}

test/e2e/e2e_v1.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
Copyright 2018 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 e2e
18+
19+
import (
20+
"fmt"
21+
"os/exec"
22+
"path/filepath"
23+
"strings"
24+
"time"
25+
26+
"github.com/kubernetes-sigs/kubebuilder/test/e2e/framework"
27+
e2einternal "github.com/kubernetes-sigs/kubebuilder/test/internal/e2e"
28+
. "github.com/onsi/ginkgo"
29+
. "github.com/onsi/gomega"
30+
)
31+
32+
var _ = Describe("v1 main workflow", func() {
33+
It("should perform main kubebuilder workflow successfully", func() {
34+
testSuffix := framework.RandomSuffix()
35+
c := initConfig(testSuffix)
36+
kubebuilderTest := e2einternal.NewKubebuilderTest(c.workDir, framework.TestContext.BinariesDir)
37+
38+
prepare(c.workDir)
39+
defer cleanupv1(kubebuilderTest, c.workDir, c.controllerImageName)
40+
41+
var controllerPodName string
42+
43+
output, errrr := exec.Command("which", "kubebuilder").Output()
44+
fmt.Printf("output of which: %s", output)
45+
Expect(errrr).NotTo(HaveOccurred())
46+
47+
By("init v1 project")
48+
initOptions := []string{
49+
"--project-version", "v1",
50+
"--domain", c.domain,
51+
"--dep", "true",
52+
}
53+
err := kubebuilderTest.Init(initOptions)
54+
Expect(err).NotTo(HaveOccurred())
55+
56+
By("creating api definition")
57+
crdOptions := []string{
58+
"--group", c.group,
59+
"--version", c.version,
60+
"--kind", c.kind,
61+
"--namespaced", "false",
62+
"--resource", "true",
63+
"--controller", "true",
64+
}
65+
err = kubebuilderTest.CreateAPI(crdOptions)
66+
Expect(err).NotTo(HaveOccurred())
67+
68+
// TODO: enable this test after we support gen rbac for core type controller
69+
By("creating core-type resource controller")
70+
coreControllerOptions := []string{
71+
"--group", "apps",
72+
"--version", "v1",
73+
"--kind", "Deployment",
74+
"--namespaced", "true",
75+
"--resource", "false",
76+
"--controller", "true",
77+
}
78+
err = kubebuilderTest.CreateAPI(coreControllerOptions)
79+
Expect(err).NotTo(HaveOccurred())
80+
81+
By("building image")
82+
makeDockerBuildOptions := []string{"docker-build"}
83+
err = kubebuilderTest.Make(makeDockerBuildOptions)
84+
Expect(err).NotTo(HaveOccurred())
85+
86+
By("pushing image")
87+
makeDockerPushOptions := []string{"docker-push"}
88+
err = kubebuilderTest.Make(makeDockerPushOptions)
89+
Expect(err).NotTo(HaveOccurred())
90+
91+
// NOTE: If you want to run the test against a GKE cluster, you will need to grant yourself permission.
92+
// Otherwise, you may see "... is forbidden: attempt to grant extra privileges"
93+
// $ kubectl create clusterrolebinding myname-cluster-admin-binding --clusterrole=cluster-admin [email protected]
94+
// https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control
95+
By("deploying controller manager")
96+
makeDeployOptions := []string{"deploy"}
97+
err = kubebuilderTest.Make(makeDeployOptions)
98+
99+
By("validate the controller-manager pod running as expected")
100+
verifyContollerUp := func() error {
101+
// Get pod name
102+
getOptions := []string{"get", "pods", "-l", "control-plane=controller-manager", "-n", fmt.Sprintf("e2e-%s-system", testSuffix), "-o", "go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}{{ \"\\n\" }}{{ end }}{{ end }}"}
103+
podOutput, err := kubebuilderTest.RunKubectlCommand(framework.GetKubectlArgs(getOptions))
104+
Expect(err).NotTo(HaveOccurred())
105+
podNames := framework.ParseCmdOutput(podOutput)
106+
if len(podNames) != 1 {
107+
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
108+
}
109+
controllerPodName = podNames[0]
110+
Expect(controllerPodName).Should(ContainSubstring("controller-manager"))
111+
112+
// Validate pod status
113+
getOptions = []string{"get", "pods", controllerPodName, "-o", "jsonpath={.status.phase}", "-n", fmt.Sprintf("e2e-%s-system", testSuffix)}
114+
status, err := kubebuilderTest.RunKubectlCommand(framework.GetKubectlArgs(getOptions))
115+
Expect(err).NotTo(HaveOccurred())
116+
if status != "Running" {
117+
return fmt.Errorf("controller pod in %s status", status)
118+
}
119+
120+
return nil
121+
}
122+
Eventually(verifyContollerUp, 5*time.Minute, time.Second).Should(BeNil())
123+
124+
By("creating an instance of CR")
125+
inputFile := filepath.Join("config", "samples", fmt.Sprintf("%s_%s_%s.yaml", c.group, c.version, strings.ToLower(c.kind)))
126+
createOptions := []string{"apply", "-f", inputFile}
127+
_, err = kubebuilderTest.RunKubectlCommand(framework.GetKubectlArgs(createOptions))
128+
Expect(err).NotTo(HaveOccurred())
129+
130+
By("validate the created resource object gets reconciled in controller")
131+
controllerContainerLogs := func() string {
132+
// Check container log to validate that the created resource object gets reconciled in controller
133+
logOptions := []string{"logs", controllerPodName, "-n", fmt.Sprintf("e2e-%s-system", testSuffix)}
134+
logOutput, err := kubebuilderTest.RunKubectlCommand(framework.GetKubectlArgs(logOptions))
135+
Expect(err).NotTo(HaveOccurred())
136+
137+
return logOutput
138+
}
139+
Eventually(controllerContainerLogs, 3*time.Minute, time.Second).Should(ContainSubstring("Updating"))
140+
Eventually(controllerContainerLogs, 3*time.Minute, time.Second).Should(ContainSubstring("Updating"))
141+
})
142+
})

0 commit comments

Comments
 (0)