Skip to content

Commit 698a24b

Browse files
committed
🌱 Implement a smoke test for clusterctl plugins
1 parent bfb2649 commit 698a24b

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

cmd/clusterctl/cmd/plugin_test.go

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

cmd/clusterctl/cmd/root.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func handlePlugins() {
218218
case "help", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd:
219219
// Don't search for a plugin
220220
default:
221-
if err := handlePluginCommand(pluginHandler, cmdPathPieces, 0); err != nil {
221+
if err = handlePluginCommand(pluginHandler, cmdPathPieces, 0); err != nil {
222222
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
223223
os.Exit(1)
224224
}

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ require (
5454
sigs.k8s.io/yaml v1.4.0
5555
)
5656

57+
require github.com/Masterminds/goutils v1.1.1
58+
5759
require (
5860
cel.dev/expr v0.18.0 // indirect
5961
dario.cat/mergo v1.0.1 // indirect
60-
github.com/Masterminds/goutils v1.1.1 // indirect
6162
github.com/Masterminds/semver/v3 v3.3.0 // indirect
6263
github.com/NYTimes/gziphandler v1.1.1 // indirect
6364
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect

0 commit comments

Comments
 (0)