diff --git a/cmd/edit.go b/cmd/edit.go deleted file mode 100644 index 328fff3cd06..00000000000 --- a/cmd/edit.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "fmt" - "log" - - "github.com/spf13/cobra" - - "sigs.k8s.io/kubebuilder/internal/cmdutil" - "sigs.k8s.io/kubebuilder/internal/config" - "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" - scaffolds "sigs.k8s.io/kubebuilder/pkg/plugin/v2/scaffolds" -) - -type editError struct { - err error -} - -func (e editError) Error() string { - return fmt.Sprintf("failed to edit configuration: %v", e.err) -} - -func newEditCmd() *cobra.Command { - options := &editOptions{} - - cmd := &cobra.Command{ - Use: "edit", - Short: "This command will edit the project configuration", - Long: `This command will edit the project configuration`, - Example: ` # Enable the multigroup layout - kubebuilder edit --multigroup - - # Disable the multigroup layout - kubebuilder edit --multigroup=false`, - Run: func(_ *cobra.Command, _ []string) { - var err error - if options.config, err = config.LoadInitialized(); err != nil { - log.Fatal(err) - } - if err := cmdutil.Run(options); err != nil { - log.Fatal(editError{err}) - } - }, - } - - options.bindFlags(cmd) - - return cmd -} - -var _ cmdutil.RunOptions = &editOptions{} - -type editOptions struct { - config *config.Config - - multigroup bool -} - -func (o *editOptions) bindFlags(cmd *cobra.Command) { - cmd.Flags().BoolVar(&o.multigroup, "multigroup", false, "enable or disable multigroup layout") -} - -func (o *editOptions) Validate() error { - return nil -} - -func (o *editOptions) GetScaffolder() (scaffold.Scaffolder, error) { - return scaffolds.NewEditScaffolder(&o.config.Config, o.multigroup), nil -} - -func (o *editOptions) PostScaffold() error { - return o.config.Save() -} diff --git a/cmd/main.go b/cmd/main.go index 17e327132d8..0839bcd2ba4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -35,7 +35,6 @@ func main() { &pluginv2.Plugin{}, ), cli.WithExtraCommands( - newEditCmd(), newCompletionCmd(), version.NewCmd(), ), diff --git a/pkg/cli/api.go b/pkg/cli/api.go index 8e71ab0438d..aa52ef1d817 100644 --- a/pkg/cli/api.go +++ b/pkg/cli/api.go @@ -54,6 +54,7 @@ func (c cli) newAPIContext() plugin.Context { return ctx } +// nolint:dupl func (c cli) bindCreateAPI(ctx plugin.Context, cmd *cobra.Command) { var getter plugin.CreateAPIPluginGetter for _, p := range c.resolvedPlugins { diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index ad6ffaeb62c..b6a2434e69a 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -356,6 +356,8 @@ func (c cli) buildRootCmd() *cobra.Command { // kubebuilder init rootCmd.AddCommand(c.newInitCmd()) + // kubebuilder edit + rootCmd.AddCommand(c.newEditCmd()) return rootCmd } diff --git a/pkg/cli/edit.go b/pkg/cli/edit.go new file mode 100644 index 00000000000..954cc55e530 --- /dev/null +++ b/pkg/cli/edit.go @@ -0,0 +1,91 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cli // nolint:dupl + +import ( + "fmt" + + "github.com/spf13/cobra" + "sigs.k8s.io/kubebuilder/internal/config" + "sigs.k8s.io/kubebuilder/pkg/plugin" +) + +func (c *cli) newEditCmd() *cobra.Command { + ctx := c.newEditContext() + cmd := &cobra.Command{ + Use: "edit", + Short: "This command will edit the project configuration", + Long: ctx.Description, + Example: ctx.Examples, + RunE: errCmdFunc( + fmt.Errorf("project must be initialized"), + ), + } + + // Lookup the plugin for projectVersion and bind it to the command. + c.bindEdit(ctx, cmd) + return cmd + +} + +func (c *cli) newEditContext() plugin.Context { + ctx := plugin.Context{ + CommandName: c.commandName, + Description: `This command will edit the project configuration. You can have single or multi group project.`, + } + + return ctx +} + +// nolint:dupl +func (c *cli) bindEdit(ctx plugin.Context, cmd *cobra.Command) { + var getter plugin.EditPluginGetter + for _, p := range c.resolvedPlugins { + tmpGetter, isGetter := p.(plugin.EditPluginGetter) + if isGetter { + if getter != nil { + err := fmt.Errorf("duplicate edit project plugins for project version %q (%s, %s), "+ + "use a more specific plugin key", c.projectVersion, plugin.KeyFor(getter), plugin.KeyFor(p)) + cmdErr(cmd, err) + return + } + getter = tmpGetter + } + } + + cfg, err := config.LoadInitialized() + if err != nil { + cmdErr(cmd, err) + return + } + + if getter == nil { + err := fmt.Errorf("layout plugin %q does not support a webhook creation plugin", cfg.Layout) + cmdErr(cmd, err) + return + } + + editProject := getter.GetEditPlugin() + editProject.InjectConfig(&cfg.Config) + editProject.BindFlags(cmd.Flags()) + editProject.UpdateContext(&ctx) + cmd.Long = ctx.Description + cmd.Example = ctx.Examples + cmd.RunE = runECmdFunc(cfg, editProject, + fmt.Sprintf("failed to edit project with version %q", c.projectVersion)) + +} diff --git a/pkg/cli/webhook.go b/pkg/cli/webhook.go index 08d7ecd3334..bd53033bf68 100644 --- a/pkg/cli/webhook.go +++ b/pkg/cli/webhook.go @@ -54,6 +54,7 @@ func (c cli) newWebhookContext() plugin.Context { return ctx } +// nolint:dupl func (c cli) bindCreateWebhook(ctx plugin.Context, cmd *cobra.Command) { var getter plugin.CreateWebhookPluginGetter for _, p := range c.resolvedPlugins { diff --git a/pkg/plugin/interfaces.go b/pkg/plugin/interfaces.go index acfb5780d94..e8508735cec 100644 --- a/pkg/plugin/interfaces.go +++ b/pkg/plugin/interfaces.go @@ -95,3 +95,13 @@ type CreateWebhookPluginGetter interface { type CreateWebhook interface { GenericSubcommand } + +type EditPluginGetter interface { + Base + //GetEditPlugin return the underlying Edit interface. + GetEditPlugin() Edit +} + +type Edit interface { + GenericSubcommand +} diff --git a/pkg/plugin/v2/edit.go b/pkg/plugin/v2/edit.go new file mode 100644 index 00000000000..1671536a20d --- /dev/null +++ b/pkg/plugin/v2/edit.go @@ -0,0 +1,82 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v2 + +import ( + "fmt" + + "github.com/spf13/pflag" + "sigs.k8s.io/kubebuilder/internal/cmdutil" + "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/pkg/plugin/v2/scaffolds" +) + +type editPlugin struct { + config *config.Config + // For help text + commandName string + + multigroup bool +} + +var ( + _ plugin.Edit = &editPlugin{} + _ cmdutil.RunOptions = &editPlugin{} +) + +func (p *editPlugin) UpdateContext(ctx *plugin.Context) { + ctx.Description = `This command will edit the project configuration. You can have single or multi group project.` + + ctx.Examples = fmt.Sprintf(`# Enable the multigroup layout + %s edit --multigroup + + # Disable the multigroup layout + %s edit --multigroup=false + `, ctx.CommandName, ctx.CommandName) + + p.commandName = ctx.CommandName +} + +func (p *editPlugin) BindFlags(fs *pflag.FlagSet) { + fs.BoolVar(&p.multigroup, "multigroup", false, "enable or disable multigroup layout") +} + +func (p *editPlugin) InjectConfig(c *config.Config) { + // v3 project configs get a 'layout' value. + if c.IsV3() { + c.Layout = plugin.KeyFor(Plugin{}) + } + p.config = c +} + +func (p *editPlugin) Run() error { + return cmdutil.Run(p) +} + +func (p *editPlugin) Validate() error { + return nil +} + +func (p *editPlugin) GetScaffolder() (scaffold.Scaffolder, error) { + return scaffolds.NewEditScaffolder(p.config, p.multigroup), nil +} + +func (p *editPlugin) PostScaffold() error { + return nil +} diff --git a/pkg/plugin/v2/plugin.go b/pkg/plugin/v2/plugin.go index 3eb7a3bcace..ef7fc66e269 100644 --- a/pkg/plugin/v2/plugin.go +++ b/pkg/plugin/v2/plugin.go @@ -33,12 +33,14 @@ var ( _ plugin.InitPluginGetter = Plugin{} _ plugin.CreateAPIPluginGetter = Plugin{} _ plugin.CreateWebhookPluginGetter = Plugin{} + _ plugin.EditPluginGetter = Plugin{} ) type Plugin struct { initPlugin createAPIPlugin createWebhookPlugin + editPlugin } func (Plugin) Name() string { return pluginName } @@ -47,3 +49,4 @@ func (Plugin) SupportedProjectVersions() []string { return supported func (p Plugin) GetInitPlugin() plugin.Init { return &p.initPlugin } func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { return &p.createAPIPlugin } func (p Plugin) GetCreateWebhookPlugin() plugin.CreateWebhook { return &p.createWebhookPlugin } +func (p Plugin) GetEditPlugin() plugin.Edit { return &p.editPlugin } diff --git a/pkg/plugin/v3/edit.go b/pkg/plugin/v3/edit.go new file mode 100644 index 00000000000..fe8b8a57746 --- /dev/null +++ b/pkg/plugin/v3/edit.go @@ -0,0 +1,78 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3 + +import ( + "fmt" + + "github.com/spf13/pflag" + "sigs.k8s.io/kubebuilder/internal/cmdutil" + "sigs.k8s.io/kubebuilder/pkg/model/config" + "sigs.k8s.io/kubebuilder/pkg/plugin" + "sigs.k8s.io/kubebuilder/pkg/plugin/scaffold" + "sigs.k8s.io/kubebuilder/pkg/plugin/v3/scaffolds" +) + +type editPlugin struct { + config *config.Config + // For help text + commandName string + + multigroup bool +} + +var ( + _ plugin.Edit = &editPlugin{} + _ cmdutil.RunOptions = &editPlugin{} +) + +func (p *editPlugin) UpdateContext(ctx *plugin.Context) { + ctx.Description = `This command will edit the project configuration. You can have single or multi group project.` + + ctx.Examples = fmt.Sprintf(`# Enable the multigroup layout + %s edit --multigroup + + # Disable the multigroup layout + %s edit --multigroup=false + `, ctx.CommandName, ctx.CommandName) + + p.commandName = ctx.CommandName +} + +func (p *editPlugin) BindFlags(fs *pflag.FlagSet) { + fs.BoolVar(&p.multigroup, "multigroup", false, "enable or disable multigroup layout") +} + +func (p *editPlugin) InjectConfig(c *config.Config) { + p.config = c +} + +func (p *editPlugin) Run() error { + return cmdutil.Run(p) +} + +func (p *editPlugin) Validate() error { + return nil +} + +func (p *editPlugin) GetScaffolder() (scaffold.Scaffolder, error) { + return scaffolds.NewEditScaffolder(p.config, p.multigroup), nil +} + +func (p *editPlugin) PostScaffold() error { + return nil +} diff --git a/pkg/plugin/v3/plugin.go b/pkg/plugin/v3/plugin.go index 64d80991c41..089fd0efeff 100644 --- a/pkg/plugin/v3/plugin.go +++ b/pkg/plugin/v3/plugin.go @@ -33,12 +33,14 @@ var ( _ plugin.InitPluginGetter = Plugin{} _ plugin.CreateAPIPluginGetter = Plugin{} _ plugin.CreateWebhookPluginGetter = Plugin{} + _ plugin.EditPluginGetter = Plugin{} ) type Plugin struct { initPlugin createAPIPlugin createWebhookPlugin + editPlugin } func (Plugin) Name() string { return pluginName } @@ -47,3 +49,4 @@ func (Plugin) SupportedProjectVersions() []string { return supported func (p Plugin) GetInitPlugin() plugin.Init { return &p.initPlugin } func (p Plugin) GetCreateAPIPlugin() plugin.CreateAPI { return &p.createAPIPlugin } func (p Plugin) GetCreateWebhookPlugin() plugin.CreateWebhook { return &p.createWebhookPlugin } +func (p Plugin) GetEditPlugin() plugin.Edit { return &p.editPlugin }