Skip to content

Commit

Permalink
Merge pull request #2089 from Adirio/extra-alpha-commands
Browse files Browse the repository at this point in the history
✨ Provide third-party devs the option to provide their own alpha subcommands
  • Loading branch information
k8s-ci-robot committed Mar 15, 2021
2 parents e9caa6e + bca394b commit fdb87df
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
33 changes: 31 additions & 2 deletions pkg/cli/alpha.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,24 @@ limitations under the License.
package cli

import (
"fmt"
"strings"

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

const (
alphaCommand = "alpha"
)

var alphaCommands = []*cobra.Command{
configgen.NewCommand(),
}

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

func (c *CLI) addAlphaCmd() {
if len(alphaCommands) > 0 {
if (len(alphaCommands) + len(c.extraAlphaCommands)) > 0 {
c.cmd.AddCommand(c.newAlphaCmd())
}
}

func (c *CLI) addExtraAlphaCommands() error {
// Search for the alpha subcommand
var alpha *cobra.Command
for _, subCmd := range c.cmd.Commands() {
if subCmd.Name() == alphaCommand {
alpha = subCmd
break
}
}
if alpha == nil {
return fmt.Errorf("no %q command found", alphaCommand)
}

for _, cmd := range c.extraAlphaCommands {
for _, subCmd := range alpha.Commands() {
if cmd.Name() == subCmd.Name() {
return fmt.Errorf("command %q already exists", fmt.Sprintf("%s %s", alphaCommand, cmd.Name()))
}
}
c.cmd.AddCommand(cmd)
}
return nil
}
7 changes: 7 additions & 0 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type CLI struct { //nolint:maligned
plugins map[string]plugin.Plugin
// Commands injected by options.
extraCommands []*cobra.Command
// Alpha commands injected by options.
extraAlphaCommands []*cobra.Command
// Whether to add a completion command to the CLI.
completionCommand bool

Expand Down Expand Up @@ -122,6 +124,11 @@ func New(options ...Option) (*CLI, error) {
return nil, err
}

// Add extra alpha commands injected by options.
if err := c.addExtraAlphaCommands(); err != nil {
return nil, err
}

// Write deprecation notices after all commands have been constructed.
c.printDeprecationWarnings()

Expand Down
12 changes: 12 additions & 0 deletions pkg/cli/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ func WithExtraCommands(cmds ...*cobra.Command) Option {
}
}

// WithExtraAlphaCommands is an Option that adds extra alpha subcommands to the CLI.
//
// Adding extra alpha commands that duplicate existing commands results in an error.
func WithExtraAlphaCommands(cmds ...*cobra.Command) Option {
return func(c *CLI) error {
// We don't know the commands defined by the CLI yet so we are not checking if the extra alpha commands
// conflict with a pre-existing one yet. We do this after creating the base commands.
c.extraAlphaCommands = append(c.extraAlphaCommands, cmds...)
return nil
}
}

// WithCompletion is an Option that adds the completion subcommand.
func WithCompletion() Option {
return func(c *CLI) error {
Expand Down
15 changes: 15 additions & 0 deletions pkg/cli/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,21 @@ var _ = Describe("CLI options", func() {
})
})

Context("WithExtraAlphaCommands", func() {
It("should return a valid CLI with extra alpha commands", func() {
commandTest := &cobra.Command{
Use: "example",
}
c, err = newCLI(WithExtraAlphaCommands(commandTest))
Expect(err).NotTo(HaveOccurred())
Expect(c).NotTo(BeNil())
Expect(c.extraAlphaCommands).NotTo(BeNil())
Expect(len(c.extraAlphaCommands)).To(Equal(1))
Expect(c.extraAlphaCommands[0]).NotTo(BeNil())
Expect(c.extraAlphaCommands[0].Use).To(Equal(commandTest.Use))
})
})

Context("WithCompletion", func() {
It("should not add the completion command by default", func() {
c, err = newCLI()
Expand Down

0 comments on commit fdb87df

Please sign in to comment.