Skip to content

Commit

Permalink
resolve plugins to one before passing to cmd setup function
Browse files Browse the repository at this point in the history
  • Loading branch information
estroz committed May 31, 2020
1 parent d658fa2 commit 669b702
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 246 deletions.
65 changes: 0 additions & 65 deletions internal/config/config_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,74 +21,9 @@ import (

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/spf13/pflag"

internalconfig "sigs.k8s.io/kubebuilder/internal/config"
"sigs.k8s.io/kubebuilder/pkg/model/config"
"sigs.k8s.io/kubebuilder/pkg/plugin"
)

func TestCLI(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Config Suite")
}

// Test plugin types and constructors.
type mockPlugin struct {
name, version string
projectVersions []string
}

func (p mockPlugin) Name() string { return p.name }
func (p mockPlugin) Version() string { return p.version }
func (p mockPlugin) SupportedProjectVersions() []string { return p.projectVersions }

func (mockPlugin) UpdateContext(*plugin.Context) {}
func (mockPlugin) BindFlags(*pflag.FlagSet) {}
func (mockPlugin) InjectConfig(*config.Config) {}
func (mockPlugin) Run() error { return nil }

func makeBasePlugin(name, version string, projVers ...string) plugin.Base {
return mockPlugin{name, version, projVers}
}

func makePluginsForKeys(keys ...string) (plugins []plugin.Base) {
for _, key := range keys {
n, v := plugin.SplitKey(key)
plugins = append(plugins, makeBasePlugin(n, v, internalconfig.DefaultVersion))
}
return
}

func makeKeysForPlugins(plugins ...plugin.Base) (keys []string) {
for _, p := range plugins {
keys = append(keys, plugin.KeyFor(p))
}
return
}

type mockAllPlugin struct {
mockPlugin
mockInitPlugin
mockCreateAPIPlugin
mockCreateWebhookPlugin
}

type mockInitPlugin struct{ mockPlugin }
type mockCreateAPIPlugin struct{ mockPlugin }
type mockCreateWebhookPlugin struct{ mockPlugin }

func (p mockInitPlugin) GetInitPlugin() plugin.Init { return p }
func (p mockCreateAPIPlugin) GetCreateAPIPlugin() plugin.CreateAPI { return p }
func (p mockCreateWebhookPlugin) GetCreateWebhookPlugin() plugin.CreateWebhook { return p }

func makeAllPlugin(name, version string, projectVersions ...string) plugin.Base {
p := makeBasePlugin(name, version, projectVersions...).(mockPlugin)
return mockAllPlugin{
p,
mockInitPlugin{p},
mockCreateAPIPlugin{p},
mockCreateWebhookPlugin{p},
}
}
13 changes: 9 additions & 4 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func WithPlugins(plugins ...plugin.Base) Option {
func WithDefaultPlugins(plugins ...plugin.Base) Option {
return func(c *cli) error {
for _, p := range plugins {
// NB(estroz): consider only allowing one default plugin per project version.
for _, version := range p.SupportedProjectVersions() {
c.defaultPluginsFromOptions[version] = append(c.defaultPluginsFromOptions[version], p)
}
Expand Down Expand Up @@ -212,6 +213,10 @@ func (c *cli) initialize() error {
// layout and --plugins values can be short (ex. "go/v2.0.0") or unversioned
// (ex. "go.kubebuilder.io") keys or both, their values may need to be
// resolved to known plugins by key.
//
// NB(estroz): running "init --plugins go" when default plugins contain
// exactly one name match for "go" should result in the matching default
// being selected.
plugins := c.pluginsFromOptions[c.projectVersion]
switch {
case c.cliPluginKey != "":
Expand Down Expand Up @@ -339,11 +344,11 @@ func validatePlugins(plugins ...plugin.Base) error {
}
}
// Check for duplicate plugin keys.
key := plugin.KeyFor(p)
if _, hasKey := pluginKeySet[key]; hasKey {
return fmt.Errorf("two plugins have the same key: %q", key)
pluginKey := plugin.KeyFor(p)
if _, seen := pluginKeySet[pluginKey]; seen {
return fmt.Errorf("two plugins have the same key: %q", pluginKey)
}
pluginKeySet[key] = struct{}{}
pluginKeySet[pluginKey] = struct{}{}
}
return nil
}
Expand Down
17 changes: 10 additions & 7 deletions pkg/cli/cli_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,6 @@ func makePluginsForKeys(keys ...string) (plugins []plugin.Base) {
return
}

func makeKeysForPlugins(plugins ...plugin.Base) (keys []string) {
for _, p := range plugins {
keys = append(keys, plugin.KeyFor(p))
}
return
}

type mockAllPlugin struct {
mockPlugin
mockInitPlugin
Expand All @@ -92,3 +85,13 @@ func makeAllPlugin(name, version string, projectVersions ...string) plugin.Base
mockCreateWebhookPlugin{p},
}
}

func makeSetByProjVer(ps ...plugin.Base) map[string][]plugin.Base {
set := make(map[string][]plugin.Base)
for _, p := range ps {
for _, version := range p.SupportedProjectVersions() {
set[version] = append(set[version], p)
}
}
return set
}
39 changes: 17 additions & 22 deletions pkg/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,18 @@ var _ = Describe("CLI", func() {
})

It("should return a valid CLI", func() {
By(`setting cliPluginKey to "go"`)
setPluginsFlag("go")
c, err = New(WithDefaultPlugins(pluginAV1), WithPlugins(pluginAV1, pluginBV2))
Expect(err).NotTo(HaveOccurred())
Expect(c).NotTo(BeNil())
Expect(c.(*cli).pluginsFromOptions).To(Equal(makeSetByProjVer(pluginAV1, pluginBV2)))
Expect(c.(*cli).resolvedPlugins).To(Equal([]plugin.Base{pluginAV1, pluginBV2}))
// TODO(estroz): this case currently fails because "go" is ambiguous.
// However, running "init --plugins go" when default plugins contain
// exactly one name match for "go" should result in the matching default
// being selected. Once that is implemented, uncomment this case.
//
// By(`setting cliPluginKey to "go"`)
// setPluginsFlag("go")
// c, err = New(WithDefaultPlugins(pluginAV1), WithPlugins(pluginAV1, pluginAV2))
// Expect(err).NotTo(HaveOccurred())
// Expect(c).NotTo(BeNil())
// Expect(c.(*cli).pluginsFromOptions).To(Equal(makeSetByProjVer(pluginAV1, pluginAV2)))
// Expect(c.(*cli).resolvedPlugins).To(Equal([]plugin.Base{pluginAV2}))

By(`setting cliPluginKey to "go/v1"`)
setPluginsFlag("go/v1")
Expand Down Expand Up @@ -145,32 +150,22 @@ var _ = Describe("CLI", func() {
By(`setting cliPluginKey to an non-existent key "foo"`)
setPluginsFlag("foo")
_, err = New(WithDefaultPlugins(pluginAV1), WithPlugins(pluginAV1, pluginAV2))
Expect(err).To(MatchError(`ambiguous plugin name "foo": no names match`))
Expect(err).To(MatchError(errAmbiguousPlugin{"foo", "no names match"}))

By(`setting cliPluginKey to an ambiguous key "go"`)
setPluginsFlag("go")
c, err = New(WithDefaultPlugins(pluginAV1), WithPlugins(allPlugins...))
Expect(err).NotTo(HaveOccurred())
Expect(c.(*cli).resolvedPlugins).To(Equal(allPlugins))
Expect(c.Run()).To(MatchError(`duplicate initialization plugins for project version "3-alpha": ` +
"go.example.com/v1.0, go.example.com/v2.0"))
Expect(err).To(MatchError(errAmbiguousPlugin{
key: "go",
msg: `possible keys: ["go.example.com/v1.0" "go.example.com/v2.0" "go.test.com/v1.0" "go.test.com/v2.0"]`,
}))
})
})

})

})

func makeSetByProjVer(ps ...plugin.Base) map[string][]plugin.Base {
set := make(map[string][]plugin.Base)
for _, p := range ps {
for _, version := range p.SupportedProjectVersions() {
set[version] = append(set[version], p)
}
}
return set
}

func setPluginsFlag(key string) {
os.Args = append(os.Args, "init", "--"+pluginsFlag, key)
}
Loading

0 comments on commit 669b702

Please sign in to comment.