Skip to content

Commit bca394b

Browse files
committed
Provide third-party devs the option to provide their own alpha subcommands
Signed-off-by: Adrian Orive <[email protected]>
1 parent 73cda2b commit bca394b

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

pkg/cli/alpha.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,24 @@ limitations under the License.
1717
package cli
1818

1919
import (
20+
"fmt"
2021
"strings"
2122

2223
"github.com/spf13/cobra"
2324
configgen "sigs.k8s.io/kubebuilder/v3/pkg/cli/alpha/config-gen"
2425
)
2526

27+
const (
28+
alphaCommand = "alpha"
29+
)
30+
2631
var alphaCommands = []*cobra.Command{
2732
configgen.NewCommand(),
2833
}
2934

3035
func (c *CLI) newAlphaCmd() *cobra.Command {
3136
alpha := &cobra.Command{
32-
Use: "alpha",
37+
Use: alphaCommand,
3338
SuggestFor: []string{"experimental"},
3439
Short: "Alpha kubebuilder subcommands",
3540
Long: strings.TrimSpace(`
@@ -46,7 +51,31 @@ Alpha kubebuilder commands are for unstable features.
4651
}
4752

4853
func (c *CLI) addAlphaCmd() {
49-
if len(alphaCommands) > 0 {
54+
if (len(alphaCommands) + len(c.extraAlphaCommands)) > 0 {
5055
c.cmd.AddCommand(c.newAlphaCmd())
5156
}
5257
}
58+
59+
func (c *CLI) addExtraAlphaCommands() error {
60+
// Search for the alpha subcommand
61+
var alpha *cobra.Command
62+
for _, subCmd := range c.cmd.Commands() {
63+
if subCmd.Name() == alphaCommand {
64+
alpha = subCmd
65+
break
66+
}
67+
}
68+
if alpha == nil {
69+
return fmt.Errorf("no %q command found", alphaCommand)
70+
}
71+
72+
for _, cmd := range c.extraAlphaCommands {
73+
for _, subCmd := range alpha.Commands() {
74+
if cmd.Name() == subCmd.Name() {
75+
return fmt.Errorf("command %q already exists", fmt.Sprintf("%s %s", alphaCommand, cmd.Name()))
76+
}
77+
}
78+
c.cmd.AddCommand(cmd)
79+
}
80+
return nil
81+
}

pkg/cli/cli.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ type CLI struct { //nolint:maligned
7575
plugins map[string]plugin.Plugin
7676
// Commands injected by options.
7777
extraCommands []*cobra.Command
78+
// Alpha commands injected by options.
79+
extraAlphaCommands []*cobra.Command
7880
// Whether to add a completion command to the CLI.
7981
completionCommand bool
8082

@@ -121,6 +123,11 @@ func New(options ...Option) (*CLI, error) {
121123
return nil, err
122124
}
123125

126+
// Add extra alpha commands injected by options.
127+
if err := c.addExtraAlphaCommands(); err != nil {
128+
return nil, err
129+
}
130+
124131
// Write deprecation notices after all commands have been constructed.
125132
c.printDeprecationWarnings()
126133

pkg/cli/options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,18 @@ func WithExtraCommands(cmds ...*cobra.Command) Option {
112112
}
113113
}
114114

115+
// WithExtraAlphaCommands is an Option that adds extra alpha subcommands to the CLI.
116+
//
117+
// Adding extra alpha commands that duplicate existing commands results in an error.
118+
func WithExtraAlphaCommands(cmds ...*cobra.Command) Option {
119+
return func(c *CLI) error {
120+
// We don't know the commands defined by the CLI yet so we are not checking if the extra alpha commands
121+
// conflict with a pre-existing one yet. We do this after creating the base commands.
122+
c.extraAlphaCommands = append(c.extraAlphaCommands, cmds...)
123+
return nil
124+
}
125+
}
126+
115127
// WithCompletion is an Option that adds the completion subcommand.
116128
func WithCompletion() Option {
117129
return func(c *CLI) error {

pkg/cli/options_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,21 @@ var _ = Describe("CLI options", func() {
221221
})
222222
})
223223

224+
Context("WithExtraAlphaCommands", func() {
225+
It("should return a valid CLI with extra alpha commands", func() {
226+
commandTest := &cobra.Command{
227+
Use: "example",
228+
}
229+
c, err = newCLI(WithExtraAlphaCommands(commandTest))
230+
Expect(err).NotTo(HaveOccurred())
231+
Expect(c).NotTo(BeNil())
232+
Expect(c.extraAlphaCommands).NotTo(BeNil())
233+
Expect(len(c.extraAlphaCommands)).To(Equal(1))
234+
Expect(c.extraAlphaCommands[0]).NotTo(BeNil())
235+
Expect(c.extraAlphaCommands[0].Use).To(Equal(commandTest.Use))
236+
})
237+
})
238+
224239
Context("WithCompletion", func() {
225240
It("should not add the completion command by default", func() {
226241
c, err = newCLI()

0 commit comments

Comments
 (0)