diff --git a/internal/plugins/ansible/v1/init.go b/internal/plugins/ansible/v1/init.go index 428fb69bc14..747e4cc0f0e 100644 --- a/internal/plugins/ansible/v1/init.go +++ b/internal/plugins/ansible/v1/init.go @@ -102,6 +102,8 @@ func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { fs.StringVar(&p.domain, "domain", "my.domain", "domain for groups") fs.StringVar(&p.projectName, "project-name", "", "name of this project, the default being directory name") + // Bind GVK flags here so they can be passed to `create api`, + // for which GVK flags are auto-bound by the CLI. fs.StringVar(&p.group, "group", "", "resource Group") fs.StringVar(&p.version, "version", "", "resource Version") fs.StringVar(&p.kind, "kind", "", "resource Kind") diff --git a/internal/plugins/envtest/v1/init.go b/internal/plugins/envtest/v1/init.go index e9d5d13b194..e4638ed444d 100644 --- a/internal/plugins/envtest/v1/init.go +++ b/internal/plugins/envtest/v1/init.go @@ -15,7 +15,6 @@ package v1 import ( - "errors" "fmt" "io/ioutil" "os" @@ -62,10 +61,6 @@ func (s *initSubcommand) Scaffold(fs machinery.Filesystem) error { return fmt.Errorf("error updating Makefile: %w", err) } - if err := s.config.EncodePluginConfig(pluginKey, Config{}); err != nil && !errors.As(err, &config.UnsupportedFieldError{}) { - return err - } - return nil } diff --git a/internal/plugins/envtest/v1/plugin.go b/internal/plugins/envtest/v1/plugin.go index 42e6d4d411a..5ddf8b58602 100644 --- a/internal/plugins/envtest/v1/plugin.go +++ b/internal/plugins/envtest/v1/plugin.go @@ -30,7 +30,6 @@ const pluginName = "envtest" + plugins.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 1} supportedProjectVersions = []config.Version{cfgv2.Version, cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) var ( diff --git a/internal/plugins/helm/v1/api.go b/internal/plugins/helm/v1/api.go index 0e24f054f0b..1403be1ba00 100644 --- a/internal/plugins/helm/v1/api.go +++ b/internal/plugins/helm/v1/api.go @@ -38,10 +38,7 @@ const ( helmChartRepoFlag = "helm-chart-repo" helmChartVersionFlag = "helm-chart-version" - defaultCrdVersion = "v1" - defaultHelmChart = "" - defaultHelmChartRepo = "" - defaultHelmChartVersion = "" + defaultCrdVersion = "v1" // defaultGroup is the Kubernetes CRD API Group used for fetched charts when the --group flag is not specified defaultGroup = "charts" @@ -117,9 +114,9 @@ func (p *createAPISubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdM func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) { fs.SortFlags = false - fs.StringVar(&p.options.chartOptions.Chart, helmChartFlag, defaultHelmChart, "helm chart") - fs.StringVar(&p.options.chartOptions.Repo, helmChartRepoFlag, defaultHelmChartRepo, "helm chart repository") - fs.StringVar(&p.options.chartOptions.Version, helmChartVersionFlag, defaultHelmChartVersion, "helm chart version (default: latest)") + fs.StringVar(&p.options.chartOptions.Chart, helmChartFlag, "", "helm chart") + fs.StringVar(&p.options.chartOptions.Repo, helmChartRepoFlag, "", "helm chart repository") + fs.StringVar(&p.options.chartOptions.Version, helmChartVersionFlag, "", "helm chart version (default: latest)") fs.StringVar(&p.options.CRDVersion, crdVersionFlag, defaultCrdVersion, "crd version to generate") } diff --git a/internal/plugins/helm/v1/init.go b/internal/plugins/helm/v1/init.go index 21fb15d2548..f15a475b081 100644 --- a/internal/plugins/helm/v1/init.go +++ b/internal/plugins/helm/v1/init.go @@ -124,6 +124,8 @@ func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) { fs.StringVar(&p.domain, "domain", "my.domain", "domain for groups") fs.StringVar(&p.projectName, "project-name", "", "name of this project, the default being directory name") + // Bind GVK flags here so they can be passed to `create api`, + // for which GVK flags are auto-bound by the CLI. fs.StringVar(&p.group, groupFlag, "", "resource Group") fs.StringVar(&p.version, versionFlag, "", "resource Version") fs.StringVar(&p.kind, kindFlag, "", "resource Kind") @@ -164,7 +166,7 @@ func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error { // PostScaffold will run the required actions after the default plugin scaffold func (p *initSubcommand) PostScaffold() error { - doAPI := p.group != "" || p.version != "" || p.kind != "" || p.apiSubcommand.options.chartOptions.Chart != defaultHelmChart + doAPI := p.group != "" || p.version != "" || p.kind != "" || p.apiSubcommand.options.chartOptions.Chart != "" if !doAPI { fmt.Printf("Next: define a resource with:\n$ %s create api\n", p.commandName) } else { @@ -182,13 +184,13 @@ func (p *initSubcommand) PostScaffold() error { if p.apiSubcommand.options.CRDVersion != defaultCrdVersion { args = append(args, fmt.Sprintf("--%s", crdVersionFlag), p.apiSubcommand.options.CRDVersion) } - if p.apiSubcommand.options.chartOptions.Chart != defaultHelmChart { + if p.apiSubcommand.options.chartOptions.Chart != "" { args = append(args, fmt.Sprintf("--%s", helmChartFlag), p.apiSubcommand.options.chartOptions.Chart) } - if p.apiSubcommand.options.chartOptions.Repo != defaultHelmChartRepo { + if p.apiSubcommand.options.chartOptions.Repo != "" { args = append(args, fmt.Sprintf("--%s", helmChartRepoFlag), p.apiSubcommand.options.chartOptions.Repo) } - if p.apiSubcommand.options.chartOptions.Version != defaultHelmChartVersion { + if p.apiSubcommand.options.chartOptions.Version != "" { args = append(args, fmt.Sprintf("--%s", helmChartVersionFlag), p.apiSubcommand.options.chartOptions.Version) } if err := util.RunCmd("Creating the API", os.Args[0], args...); err != nil { diff --git a/internal/plugins/manifests/v2/api.go b/internal/plugins/manifests/v2/api.go index d4929d3c84a..84a187b7f9c 100644 --- a/internal/plugins/manifests/v2/api.go +++ b/internal/plugins/manifests/v2/api.go @@ -24,6 +24,7 @@ import ( "sigs.k8s.io/kubebuilder/v3/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2/templates/config/samples" + "github.com/operator-framework/operator-sdk/internal/plugins/util" ) var _ plugin.CreateAPISubcommand = &createAPISubcommand{} @@ -38,6 +39,9 @@ func (s *createAPISubcommand) InjectConfig(c config.Config) error { // Try to retrieve the plugin config if err := s.config.DecodePluginConfig(pluginKey, &Config{}); errors.As(err, &config.PluginKeyNotFoundError{}) { + if util.UpdateIfLegacyKey(s.config) { + return nil + } // If we couldn't find it, it means we are not using this plugin, so we skip remaining hooks // This scenario could happen if the project was initialized with kubebuilder which doesn't have this plugin return plugin.ExitError{ diff --git a/internal/plugins/manifests/v2/plugin.go b/internal/plugins/manifests/v2/plugin.go index 1a4aecde05b..e7ac8d51960 100644 --- a/internal/plugins/manifests/v2/plugin.go +++ b/internal/plugins/manifests/v2/plugin.go @@ -18,7 +18,6 @@ import ( "sigs.k8s.io/kubebuilder/v3/pkg/config" cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2" cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3" - "sigs.k8s.io/kubebuilder/v3/pkg/model/resource" "sigs.k8s.io/kubebuilder/v3/pkg/plugin" "github.com/operator-framework/operator-sdk/internal/plugins" @@ -49,6 +48,4 @@ func (Plugin) SupportedProjectVersions() []config.Version { return sup func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand } func (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { return &p.createAPISubcommand } -type Config struct { - Resources []resource.GVK `json:"resources,omitempty"` -} +type Config struct{} diff --git a/internal/plugins/util/legacy_keys.go b/internal/plugins/util/legacy_keys.go new file mode 100644 index 00000000000..89a5fb70d29 --- /dev/null +++ b/internal/plugins/util/legacy_keys.go @@ -0,0 +1,77 @@ +// Copyright 2021 The Operator-SDK 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 util + +import ( + "errors" + + log "github.com/sirupsen/logrus" + gofunk "github.com/thoas/go-funk" + "sigs.k8s.io/kubebuilder/v3/pkg/config" + cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3" +) + +const ( + // The catch-all plugin key for the go/v2+manifests+scorecard plugins. + // Should still be accepted for backwards-compat. + legacyGoPluginKey = "go.sdk.operatorframework.io/v2-alpha" + + // Hard-code the latest manifests and scorecard keys here to avoid a circular import. + manifestsKey = "manifests.sdk.operatorframework.io/v2" + scorecardKey = "scorecard.sdk.operatorframework.io/v2" +) + +// Plugin keys that existed when manifests/scorecard keys did not. +var acceptedLayoutKeys = []string{ + "ansible.sdk.operatorframework.io/v1", + "helm.sdk.operatorframework.io/v1", +} + +// UpdateIfLegacyKey returns true if c's "plugins" map or "layout" value contains +// a legacy key that may require this plugin be executed, even if the "manifests" key +// isn't in "plugins". +func UpdateIfLegacyKey(c config.Config) bool { + if c.GetVersion().Compare(cfgv3.Version) < 0 { + return false + } + + err := c.DecodePluginConfig(legacyGoPluginKey, struct{}{}) + if err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) { + // There is no way to remove keys from "plugins", so print a warning. + log.Warnf("Plugin key %q is deprecated. Replace this key with %q and %q on separate lines.", + legacyGoPluginKey, manifestsKey, scorecardKey) + return true + } + + chain := c.GetPluginChain() + for _, key := range acceptedLayoutKeys { + if gofunk.ContainsString(chain, key) { + // Encode missing plugin keys. + if !gofunk.ContainsString(chain, manifestsKey) { + if err := c.EncodePluginConfig(manifestsKey, struct{}{}); err != nil { + log.Error(err) + } + } + if !gofunk.ContainsString(chain, scorecardKey) { + if err := c.EncodePluginConfig(scorecardKey, struct{}{}); err != nil { + log.Error(err) + } + } + return true + } + } + + return false +} diff --git a/testdata/go/v2/memcached-operator/PROJECT b/testdata/go/v2/memcached-operator/PROJECT index 31c7f21fdd2..0ab78ad7e64 100644 --- a/testdata/go/v2/memcached-operator/PROJECT +++ b/testdata/go/v2/memcached-operator/PROJECT @@ -2,7 +2,6 @@ domain: example.com layout: - go.kubebuilder.io/v2 plugins: - envtest.sdk.operatorframework.io/v1: {} manifests.sdk.operatorframework.io/v2: {} scorecard.sdk.operatorframework.io/v2: {} projectName: memcached-operator