Skip to content

Commit 1179cce

Browse files
committed
🌱 Implement a smoke test for clusterctl plugins
1 parent e389055 commit 1179cce

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

cmd/clusterctl/cmd/plugin_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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 cmd
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
"os"
23+
"os/exec"
24+
"path/filepath"
25+
"testing"
26+
27+
. "github.com/onsi/gomega"
28+
)
29+
30+
var baseArgs = []string{"clusterctl", "foo"}
31+
32+
const (
33+
forkEnvVar = "CLUSTERCTL_PLUGIN_TEST_FORK"
34+
pluginCommandEnvVar = "CLUSTERCTL_PLUGIN_COMMAND"
35+
)
36+
37+
func Test_plugin(t *testing.T) {
38+
// If CLUSTERCTL_PLUGIN_TEST_FORK is set then just execute the command.
39+
if os.Getenv(forkEnvVar) != "" {
40+
os.Args = append(baseArgs, os.Getenv(pluginCommandEnvVar))
41+
Execute()
42+
return
43+
}
44+
g := NewWithT(t)
45+
tmpDir := t.TempDir()
46+
47+
// Create a bash based plugin used for the test which gets added to the PATH variable.
48+
pluginPath := filepath.Join(tmpDir, "clusterctl-foo")
49+
pathVar := os.Getenv("PATH")
50+
g.Expect(os.WriteFile(pluginPath, []byte(pluginCode), 0755)).To(Succeed()) //nolint:gosec
51+
52+
tt := []struct {
53+
name string
54+
command string
55+
expected string
56+
}{
57+
{
58+
name: "base plugin command test",
59+
expected: "I am a plugin named clusterctl-foo",
60+
},
61+
{
62+
name: "plugin version command test",
63+
command: "version",
64+
expected: "1.0.0",
65+
},
66+
}
67+
for _, tc := range tt {
68+
t.Run(tc.name, func(t *testing.T) {
69+
g := NewWithT(t)
70+
stdout, _, err := runForkTest(t.Name(), fmt.Sprintf("%s=%s", pluginCommandEnvVar, tc.command), fmt.Sprintf("PATH=%s:%s", tmpDir, pathVar))
71+
g.Expect(err).To(Succeed())
72+
g.Expect(stdout).To(ContainSubstring(tc.expected))
73+
})
74+
}
75+
}
76+
77+
var pluginCode = `#!/bin/bash
78+
79+
# optional argument handling
80+
if [[ "$1" == "version" ]]
81+
then
82+
echo "1.0.0"
83+
exit 0
84+
fi
85+
86+
echo "I am a plugin named clusterctl-foo"
87+
`
88+
89+
func runForkTest(testName string, options ...string) (string, string, error) {
90+
cmd := exec.Command(os.Args[0], "-test.run", testName) //nolint:gosec
91+
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%v", forkEnvVar, true))
92+
cmd.Env = append(cmd.Env, options...)
93+
94+
var stdoutB, stderrB bytes.Buffer
95+
cmd.Stdout = &stdoutB
96+
cmd.Stderr = &stderrB
97+
98+
err := cmd.Run()
99+
100+
return stdoutB.String(), stderrB.String(), err
101+
}

0 commit comments

Comments
 (0)