diff --git a/CHANGELOG.md b/CHANGELOG.md index 48dd38bad6..87ff815eda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Added +- Added [`run`](./doc/cli/operator-sdk_alpha_run.md) and [`cleanup`](./doc/cli/operator-sdk_alpha_cleanup.md) subcommands (under the `alpha` subcommand) to manage deployment/deletion of operators. These commands currently interact with OLM via an in-cluster registry-server created using an operator's on-disk manifests and managed by `operator-sdk`. ([#2402](ttps://github.com/operator-framework/operator-sdk/pull/2402)) + ### Changed ### Deprecated diff --git a/cmd/operator-sdk/alpha/cleanup/cmd.go b/cmd/operator-sdk/alpha/cleanup/cmd.go new file mode 100644 index 0000000000..454be7f8ea --- /dev/null +++ b/cmd/operator-sdk/alpha/cleanup/cmd.go @@ -0,0 +1,50 @@ +// Copyright 2020 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 cleanup + +import ( + olmoperator "github.com/operator-framework/operator-sdk/internal/olm/operator" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +type cleanupArgs struct { + olm bool +} + +func NewCmd() *cobra.Command { + cargs := &cleanupArgs{} + c := &olmoperator.OLMCmd{} + cmd := &cobra.Command{ + Use: "cleanup", + Short: "Delete and clean up after a running Operator", + RunE: func(cmd *cobra.Command, args []string) error { + switch { + case cargs.olm: + if err := c.Cleanup(); err != nil { + log.Fatalf("Failed to clean up operator: %v", err) + } + } + return nil + }, + } + // OLM is the default. + cmd.Flags().BoolVar(&cargs.olm, "olm", true, "The operator to be deleted is managed by OLM in a cluster.") + // TODO(estroz): refactor flag setting when new run mode options are added. + c.AddToFlagSet(cmd.Flags()) + cmd.Flags().BoolVar(&c.ForceRegistry, "force-registry", false, "Force deletion of the in-cluster registry.") + return cmd +} diff --git a/cmd/operator-sdk/alpha/cmd.go b/cmd/operator-sdk/alpha/cmd.go index 9cd977fc81..de359bb4b6 100644 --- a/cmd/operator-sdk/alpha/cmd.go +++ b/cmd/operator-sdk/alpha/cmd.go @@ -15,8 +15,11 @@ package alpha import ( + "github.com/operator-framework/operator-sdk/cmd/operator-sdk/alpha/cleanup" "github.com/operator-framework/operator-sdk/cmd/operator-sdk/alpha/kubebuilder" "github.com/operator-framework/operator-sdk/cmd/operator-sdk/alpha/olm" + run "github.com/operator-framework/operator-sdk/cmd/operator-sdk/alpha/run" + "github.com/spf13/cobra" ) @@ -26,7 +29,11 @@ func NewCmd() *cobra.Command { Short: "Run an alpha subcommand", } - cmd.AddCommand(olm.NewCmd()) - cmd.AddCommand(kubebuilder.NewCmd()) + cmd.AddCommand( + olm.NewCmd(), + kubebuilder.NewCmd(), + run.NewCmd(), + cleanup.NewCmd(), + ) return cmd } diff --git a/cmd/operator-sdk/alpha/run/cmd.go b/cmd/operator-sdk/alpha/run/cmd.go new file mode 100644 index 0000000000..46e2028f8b --- /dev/null +++ b/cmd/operator-sdk/alpha/run/cmd.go @@ -0,0 +1,49 @@ +// Copyright 2020 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 run + +import ( + olmoperator "github.com/operator-framework/operator-sdk/internal/olm/operator" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +type runArgs struct { + olm bool +} + +func NewCmd() *cobra.Command { + cargs := &runArgs{} + c := &olmoperator.OLMCmd{} + cmd := &cobra.Command{ + Use: "run", + Short: "Run an Operator in a variety of environments", + RunE: func(cmd *cobra.Command, args []string) error { + switch { + case cargs.olm: + if err := c.Run(); err != nil { + log.Fatalf("Failed to run operator: %v", err) + } + } + return nil + }, + } + // OLM is the default. + cmd.Flags().BoolVar(&cargs.olm, "olm", true, "The operator to be run will be managed by OLM in a cluster.") + // TODO(estroz): refactor flag setting when new run mode options are added. + c.AddToFlagSet(cmd.Flags()) + return cmd +} diff --git a/doc/cli/operator-sdk_alpha.md b/doc/cli/operator-sdk_alpha.md index cf209d2b32..eccadab732 100644 --- a/doc/cli/operator-sdk_alpha.md +++ b/doc/cli/operator-sdk_alpha.md @@ -15,5 +15,7 @@ Run an alpha subcommand ### SEE ALSO * [operator-sdk](operator-sdk.md) - An SDK for building operators with ease +* [operator-sdk alpha cleanup](operator-sdk_alpha_cleanup.md) - Delete and clean up after a running Operator * [operator-sdk alpha olm](operator-sdk_alpha_olm.md) - Manage the Operator Lifecycle Manager installation in your cluster +* [operator-sdk alpha run](operator-sdk_alpha_run.md) - Run an Operator in a variety of environments diff --git a/doc/cli/operator-sdk_alpha_cleanup.md b/doc/cli/operator-sdk_alpha_cleanup.md new file mode 100644 index 0000000000..d36313b0f7 --- /dev/null +++ b/doc/cli/operator-sdk_alpha_cleanup.md @@ -0,0 +1,31 @@ +## operator-sdk alpha cleanup + +Delete and clean up after a running Operator + +### Synopsis + +Delete and clean up after a running Operator + +``` +operator-sdk alpha cleanup [flags] +``` + +### Options + +``` + --force-registry Force deletion of the in-cluster registry. + -h, --help help for cleanup + --include strings Path to Kubernetes resource manifests, ex. Role, Subscription. These supplement or override defaults generated by run/cleanup + --install-mode string InstallMode to create OperatorGroup with. Format: InstallModeType=[ns1,ns2[, ...]] + --kubeconfig string Path to kubeconfig + --manifests string Directory containing package manifest and operator bundles. + --namespace string Namespace in which to create resources + --olm The operator to be deleted is managed by OLM in a cluster. (default true) + --operator-version string Version of operator to deploy + --timeout duration Time to wait for the command to complete before failing (default 2m0s) +``` + +### SEE ALSO + +* [operator-sdk alpha](operator-sdk_alpha.md) - Run an alpha subcommand + diff --git a/doc/cli/operator-sdk_alpha_run.md b/doc/cli/operator-sdk_alpha_run.md new file mode 100644 index 0000000000..5a0f58ae39 --- /dev/null +++ b/doc/cli/operator-sdk_alpha_run.md @@ -0,0 +1,30 @@ +## operator-sdk alpha run + +Run an Operator in a variety of environments + +### Synopsis + +Run an Operator in a variety of environments + +``` +operator-sdk alpha run [flags] +``` + +### Options + +``` + -h, --help help for run + --include strings Path to Kubernetes resource manifests, ex. Role, Subscription. These supplement or override defaults generated by run/cleanup + --install-mode string InstallMode to create OperatorGroup with. Format: InstallModeType=[ns1,ns2[, ...]] + --kubeconfig string Path to kubeconfig + --manifests string Directory containing package manifest and operator bundles. + --namespace string Namespace in which to create resources + --olm The operator to be run will be managed by OLM in a cluster. (default true) + --operator-version string Version of operator to deploy + --timeout duration Time to wait for the command to complete before failing (default 2m0s) +``` + +### SEE ALSO + +* [operator-sdk alpha](operator-sdk_alpha.md) - Run an alpha subcommand + diff --git a/internal/olm/operator/manager.go b/internal/olm/operator/manager.go index 8374a700da..2f9c4659bd 100644 --- a/internal/olm/operator/manager.go +++ b/internal/olm/operator/manager.go @@ -130,7 +130,7 @@ func (c *OLMCmd) newManager() (*operatorManager, error) { return m, nil } -func (m *operatorManager) up(ctx context.Context) (err error) { +func (m *operatorManager) run(ctx context.Context) (err error) { // Ensure OLM is installed. olmVer, err := m.client.GetInstalledVersion(ctx) if err != nil { @@ -221,7 +221,7 @@ func (m *operatorManager) up(ctx context.Context) (err error) { return nil } -func (m *operatorManager) down(ctx context.Context) (err error) { +func (m *operatorManager) cleanup(ctx context.Context) (err error) { // Ensure OLM is installed. olmVer, err := m.client.GetInstalledVersion(ctx) if err != nil { diff --git a/internal/olm/operator/operator.go b/internal/olm/operator/operator.go index 550f5419a8..664184bb22 100644 --- a/internal/olm/operator/operator.go +++ b/internal/olm/operator/operator.go @@ -36,7 +36,7 @@ const ( type OLMCmd struct { // nolint:golint // ManifestsDir is a directory containing a package manifest and N bundles // of the operator's CSV and CRD's. OperatorVersion can be set to the - // version of the desired operator version's subdir and Up()/Down() will + // version of the desired operator version's subdir and Run()/Cleanup() will // deploy the operator version in that subdir. ManifestsDir string // OperatorVersion is the version of the operator to deploy. It must be @@ -85,13 +85,13 @@ type OLMCmd struct { // nolint:golint var installModeFormat = "InstallModeType=[ns1,ns2[, ...]]" func (c *OLMCmd) AddToFlagSet(fs *pflag.FlagSet) { + fs.StringVar(&c.ManifestsDir, "manifests", "", "Directory containing package manifest and operator bundles.") fs.StringVar(&c.OperatorVersion, "operator-version", "", "Version of operator to deploy") fs.StringVar(&c.InstallMode, "install-mode", "", "InstallMode to create OperatorGroup with. Format: "+installModeFormat) fs.StringVar(&c.KubeconfigPath, "kubeconfig", "", "Path to kubeconfig") fs.StringVar(&c.OperatorNamespace, "namespace", "", "Namespace in which to create resources") - fs.StringSliceVar(&c.IncludePaths, "include", nil, "Path to Kubernetes resource manifests, ex. Role, Subscription. These supplement or override defaults generated by up/down") + fs.StringSliceVar(&c.IncludePaths, "include", nil, "Path to Kubernetes resource manifests, ex. Role, Subscription. These supplement or override defaults generated by run/cleanup") fs.DurationVar(&c.Timeout, "timeout", defaultTimeout, "Time to wait for the command to complete before failing") - fs.BoolVar(&c.ForceRegistry, "force-registry", false, "Force deletion of the in-cluster registry. This option is a no-op on 'up'.") } func (c *OLMCmd) validate() error { @@ -117,7 +117,7 @@ func (c *OLMCmd) initialize() { }) } -func (c *OLMCmd) Up() error { +func (c *OLMCmd) Run() error { c.initialize() if err := c.validate(); err != nil { return fmt.Errorf("validation error: %w", err) @@ -128,10 +128,10 @@ func (c *OLMCmd) Up() error { } ctx, cancel := context.WithTimeout(context.Background(), c.Timeout) defer cancel() - return m.up(ctx) + return m.run(ctx) } -func (c *OLMCmd) Down() (err error) { +func (c *OLMCmd) Cleanup() (err error) { c.initialize() if err := c.validate(); err != nil { return fmt.Errorf("validation error: %w", err) @@ -142,5 +142,5 @@ func (c *OLMCmd) Down() (err error) { } ctx, cancel := context.WithTimeout(context.Background(), c.Timeout) defer cancel() - return m.down(ctx) + return m.cleanup(ctx) } diff --git a/test/integration/operator_olm_test.go b/test/integration/operator_olm_test.go index 5a087ab26f..cc0a81a7c2 100644 --- a/test/integration/operator_olm_test.go +++ b/test/integration/operator_olm_test.go @@ -95,27 +95,27 @@ func SingleOperator(t *testing.T) { // Cleanup. defer func() { opcmd.ForceRegistry = true - if err := opcmd.Down(); err != nil { + if err := opcmd.Cleanup(); err != nil { t.Fatal(err) } }() // "Remove operator before deploy" - assert.NoError(t, opcmd.Down()) + assert.NoError(t, opcmd.Cleanup()) // "Remove operator before deploy (force delete registry)" opcmd.ForceRegistry = true - assert.NoError(t, opcmd.Down()) + assert.NoError(t, opcmd.Cleanup()) // "Deploy operator" - assert.NoError(t, opcmd.Up()) + assert.NoError(t, opcmd.Run()) // "Fail to deploy operator after deploy" - assert.Error(t, opcmd.Up()) + assert.Error(t, opcmd.Run()) // "Remove operator after deploy" - assert.NoError(t, opcmd.Down()) + assert.NoError(t, opcmd.Cleanup()) // "Remove operator after removal" - assert.NoError(t, opcmd.Down()) + assert.NoError(t, opcmd.Cleanup()) // "Remove operator after removal (force delete registry)" opcmd.ForceRegistry = true - assert.NoError(t, opcmd.Down()) + assert.NoError(t, opcmd.Cleanup()) }