From 68d194f41bfa5f69550a2ffba9ab6b7d95246e3d Mon Sep 17 00:00:00 2001 From: Eric Stroczynski Date: Wed, 17 Jun 2020 13:47:40 -0700 Subject: [PATCH] `run packagemanifests` is now available for new operator project layouts. This command must be used on operator projects with a package manifests format available. test/e2e-new: test `run packagemanifests` test/utils: add utils to install/uninstall OLM --- cmd/operator-sdk/cli/cli.go | 4 +- cmd/operator-sdk/cli/legacy.go | 2 +- cmd/operator-sdk/run/cmd.go | 19 ++++++- .../run/packagemanifests/packagemanifests.go | 14 ++++- internal/olm/operator/packagemanifests.go | 10 ++++ test/e2e-new/e2e_suite.go | 45 +++++++++++---- test/internal/utils.go | 55 +++++++++++++++++++ .../content/en/docs/cli/operator-sdk_run.md | 2 +- .../cli/operator-sdk_run_packagemanifests.md | 5 +- .../content/en/docs/new-cli/operator-sdk.md | 1 + .../en/docs/new-cli/operator-sdk_run.md | 31 +++++++++++ .../operator-sdk_run_packagemanifests.md | 39 +++++++++++++ 12 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 test/internal/utils.go create mode 100644 website/content/en/docs/new-cli/operator-sdk_run.md create mode 100644 website/content/en/docs/new-cli/operator-sdk_run_packagemanifests.md diff --git a/cmd/operator-sdk/cli/cli.go b/cmd/operator-sdk/cli/cli.go index 03446002be..61d8ec5d48 100644 --- a/cmd/operator-sdk/cli/cli.go +++ b/cmd/operator-sdk/cli/cli.go @@ -22,6 +22,7 @@ import ( "github.com/operator-framework/operator-sdk/cmd/operator-sdk/generate" "github.com/operator-framework/operator-sdk/cmd/operator-sdk/new" "github.com/operator-framework/operator-sdk/cmd/operator-sdk/olm" + "github.com/operator-framework/operator-sdk/cmd/operator-sdk/run" "github.com/operator-framework/operator-sdk/cmd/operator-sdk/version" "github.com/operator-framework/operator-sdk/internal/flags" golangv2 "github.com/operator-framework/operator-sdk/internal/plugins/golang/v2" @@ -46,8 +47,7 @@ var commands = []*cobra.Command{ completion.NewCmd(), generate.NewCmd(), olm.NewCmd(), - // Add back when implemented for new project layouts. - // run.NewCmd(), + run.NewCmd(), version.NewCmd(), } diff --git a/cmd/operator-sdk/cli/legacy.go b/cmd/operator-sdk/cli/legacy.go index 14f2b13eb0..0ec41b8bc4 100644 --- a/cmd/operator-sdk/cli/legacy.go +++ b/cmd/operator-sdk/cli/legacy.go @@ -82,7 +82,7 @@ func GetCLIRoot() *cobra.Command { new.NewCmd(), olm.NewCmd(), printdeps.NewCmd(), - run.NewCmd(), + run.NewCmdLegacy(), scorecard.NewCmd(), test.NewCmd(), version.NewCmd(), diff --git a/cmd/operator-sdk/run/cmd.go b/cmd/operator-sdk/run/cmd.go index 3b4fb8a64f..437338cec2 100644 --- a/cmd/operator-sdk/run/cmd.go +++ b/cmd/operator-sdk/run/cmd.go @@ -34,6 +34,23 @@ import ( hoflags "github.com/operator-framework/operator-sdk/pkg/helm/flags" ) +func NewCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "run", + Short: "Run an Operator in a variety of environments", + Long: `This command has subcommands that will deploy your Operator with OLM. +Currently only the package manifests format is supported via the 'packagemanifests' subcommand. +Run 'operator-sdk run --help' for more information. +`, + } + + cmd.AddCommand( + packagemanifests.NewCmd(), + ) + + return cmd +} + type runCmd struct { // Common options. kubeconfig string @@ -57,7 +74,7 @@ func (c *runCmd) checkRunType() error { return nil } -func NewCmd() *cobra.Command { +func NewCmdLegacy() *cobra.Command { c := &runCmd{} cmd := &cobra.Command{ Use: "run", diff --git a/cmd/operator-sdk/run/packagemanifests/packagemanifests.go b/cmd/operator-sdk/run/packagemanifests/packagemanifests.go index 6b2104e573..184fb44e9a 100644 --- a/cmd/operator-sdk/run/packagemanifests/packagemanifests.go +++ b/cmd/operator-sdk/run/packagemanifests/packagemanifests.go @@ -23,6 +23,7 @@ import ( olmcatalog "github.com/operator-framework/operator-sdk/internal/generate/olm-catalog" olmoperator "github.com/operator-framework/operator-sdk/internal/olm/operator" + kbutil "github.com/operator-framework/operator-sdk/internal/util/kubebuilder" "github.com/operator-framework/operator-sdk/internal/util/projutil" ) @@ -35,7 +36,9 @@ func NewCmd() *cobra.Command { cmd := &cobra.Command{ Use: "packagemanifests", - Short: "Run an Operator organized in the package manifests format with OLM", + Short: "Deploy an Operator in the package manifests format with OLM", + Long: `'run packagemanifests' deploys an Operator's package manifests with OLM. The command's argument +must be set to a valid package manifests root directory, ex. '/packagemanifests'.`, RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { if len(args) > 1 { @@ -43,8 +46,13 @@ func NewCmd() *cobra.Command { } c.ManifestsDir = args[0] } else { - operatorName := filepath.Base(projutil.MustGetwd()) - c.ManifestsDir = filepath.Join(olmcatalog.OLMCatalogDir, operatorName) + // Choose the default path depending on project configuration. + if kbutil.HasProjectFile() { + c.ManifestsDir = "packagemanifests" + } else { + operatorName := filepath.Base(projutil.MustGetwd()) + c.ManifestsDir = filepath.Join(olmcatalog.OLMCatalogDir, operatorName) + } } log.Infof("Running operator from directory %s", c.ManifestsDir) diff --git a/internal/olm/operator/packagemanifests.go b/internal/olm/operator/packagemanifests.go index 8cb0e008b1..85fd256e7e 100644 --- a/internal/olm/operator/packagemanifests.go +++ b/internal/olm/operator/packagemanifests.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "os" "github.com/spf13/pflag" ) @@ -61,9 +62,18 @@ func (c *PackageManifestsCmd) validate() error { if c.ManifestsDir == "" { return errors.New("manifests dir must be set") } + manDirInfo, err := os.Stat(c.ManifestsDir) + if err != nil { + return err + } + if !manDirInfo.IsDir() { + return fmt.Errorf("%s must be a directory", c.ManifestsDir) + } + if c.OperatorVersion == "" { return errors.New("operator version must be set") } + return c.OperatorCmd.validate() } diff --git a/test/e2e-new/e2e_suite.go b/test/e2e-new/e2e_suite.go index 8a63e8beac..a5ad06ab19 100644 --- a/test/e2e-new/e2e_suite.go +++ b/test/e2e-new/e2e_suite.go @@ -29,26 +29,29 @@ import ( . "github.com/onsi/ginkgo" //nolint:golint . "github.com/onsi/gomega" //nolint:golint + kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" - "sigs.k8s.io/kubebuilder/test/e2e/utils" + testutils "github.com/operator-framework/operator-sdk/test/internal" ) var _ = Describe("operator-sdk", func() { Context("with the new project layout", func() { var ( - tc *utils.TestContext - projectName string + tc testutils.TestContext + projectName string + operatorVersion = "0.0.1" ) BeforeEach(func() { - By("creating a new test context") var err error - tc, err = utils.NewTestContext("operator-sdk", "GO111MODULE=on") + tc, err = testutils.NewTestContext("GO111MODULE=on") Expect(err).NotTo(HaveOccurred()) Expect(tc.Prepare()).To(Succeed()) - projectName = filepath.Base(tc.Dir) + + By("installing OLM") + Expect(tc.InstallOLM()).To(Succeed()) }) AfterEach(func() { @@ -57,6 +60,9 @@ var _ = Describe("operator-sdk", func() { By("removing container image and work dir") tc.Destroy() + + By("uninstalling OLM") + tc.UninstallOLM() }) It("should generate a runnable project", func() { @@ -81,7 +87,7 @@ var _ = Describe("operator-sdk", func() { Expect(err).Should(Succeed()) By("implementing the API") - Expect(utils.InsertCode( + Expect(kbtestutils.InsertCode( filepath.Join(tc.Dir, "api", tc.Version, fmt.Sprintf("%s_types.go", strings.ToLower(tc.Kind))), fmt.Sprintf(`type %sSpec struct { `, tc.Kind), @@ -110,7 +116,7 @@ var _ = Describe("operator-sdk", func() { "-o", "go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}"+ "{{ \"\\n\" }}{{ end }}{{ end }}") Expect(err).NotTo(HaveOccurred()) - podNames := utils.GetNonEmptyLines(podOutput) + podNames := kbtestutils.GetNonEmptyLines(podOutput) if len(podNames) != 1 { return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames)) } @@ -147,6 +153,12 @@ var _ = Describe("operator-sdk", func() { } Eventually(managerContainerLogs, time.Minute, time.Second).Should(ContainSubstring("Successfully Reconciled")) + By("cleaning up the operator and resources") + defaultOutput, err := tc.KustomizeBuild(filepath.Join("config", "default")) + Expect(err).NotTo(HaveOccurred()) + _, err = tc.Kubectl.WithInput(string(defaultOutput)).Command("delete", "-f", "-") + Expect(err).NotTo(HaveOccurred()) + By("generating the operator bundle") // Turn off interactive prompts for all generation tasks. replace := "operator-sdk generate kustomize manifests" @@ -169,12 +181,25 @@ var _ = Describe("operator-sdk", func() { genKustomizeCmd := exec.Command(tc.BinaryName, "generate", "kustomize", "manifests") _, err = tc.Run(genKustomizeCmd) Expect(err).NotTo(HaveOccurred()) - kustomizeOutput, err := tc.Run(exec.Command("kustomize", "build", filepath.Join("config", "manifests"))) + manifestsOutput, err := tc.KustomizeBuild(filepath.Join("config", "manifests")) Expect(err).NotTo(HaveOccurred()) genPkgManCmd := exec.Command(tc.BinaryName, "generate", "packagemanifests", "--version", "0.0.1") - tc.Stdin = bytes.NewBuffer(kustomizeOutput) + tc.Stdin = bytes.NewBuffer(manifestsOutput) _, err = tc.Run(genPkgManCmd) Expect(err).NotTo(HaveOccurred()) + + By("running the package manifests-formatted operator") + _, err = tc.Kubectl.Command("create", "namespace", tc.Kubectl.Namespace) + Expect(err).NotTo(HaveOccurred()) + runPkgManCmd := exec.Command(tc.BinaryName, "run", "packagemanifests", + "--install-mode", "AllNamespaces", + "--operator-namespace", tc.Kubectl.Namespace, + "--operator-version", operatorVersion, + "--timeout", "4m") + _, err = tc.Run(runPkgManCmd) + Expect(err).NotTo(HaveOccurred()) + + // TODO: run 'cleanup packagemanifests' when added to the new CLI. }) }) }) diff --git a/test/internal/utils.go b/test/internal/utils.go new file mode 100644 index 0000000000..b63c544e3e --- /dev/null +++ b/test/internal/utils.go @@ -0,0 +1,55 @@ +// 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 internal + +import ( + "fmt" + "os/exec" + + . "github.com/onsi/ginkgo" //nolint:golint + + kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils" +) + +// TestContext wraps kubebuilder's e2e TestContext. +type TestContext struct { + *kbtestutils.TestContext +} + +// NewTestContext returns a TestContext containing a new kubebuilder TestContext. +func NewTestContext(env ...string) (tc TestContext, err error) { + tc.TestContext, err = kbtestutils.NewTestContext("operator-sdk", env...) + return tc, err +} + +// InstallOLM runs 'operator-sdk olm install' and returns any errors emitted by that command. +func (tc TestContext) InstallOLM() error { + cmd := exec.Command(tc.BinaryName, "olm", "install", "--timeout", "4m") + _, err := tc.Run(cmd) + return err +} + +// InstallOLM runs 'operator-sdk olm uninstall' and logs any errors emitted by that command. +func (tc TestContext) UninstallOLM() { + cmd := exec.Command(tc.BinaryName, "olm", "uninstall") + if _, err := tc.Run(cmd); err != nil { + fmt.Fprintln(GinkgoWriter, "warning: error when uninstalling OLM:", err) + } +} + +// KustomizeBuild runs 'kustomize build ' and returns its output and an error if any. +func (tc TestContext) KustomizeBuild(dir string) ([]byte, error) { + return tc.Run(exec.Command("kustomize", "build", dir)) +} diff --git a/website/content/en/docs/cli/operator-sdk_run.md b/website/content/en/docs/cli/operator-sdk_run.md index 94f3800256..3901d5fafe 100644 --- a/website/content/en/docs/cli/operator-sdk_run.md +++ b/website/content/en/docs/cli/operator-sdk_run.md @@ -27,5 +27,5 @@ operator-sdk run [flags] * [operator-sdk](../operator-sdk) - An SDK for building operators with ease * [operator-sdk run local](../operator-sdk_run_local) - Run an Operator locally -* [operator-sdk run packagemanifests](../operator-sdk_run_packagemanifests) - Run an Operator organized in the package manifests format with OLM +* [operator-sdk run packagemanifests](../operator-sdk_run_packagemanifests) - Deploy an Operator in the package manifests format with OLM diff --git a/website/content/en/docs/cli/operator-sdk_run_packagemanifests.md b/website/content/en/docs/cli/operator-sdk_run_packagemanifests.md index be19968d58..3302f484c7 100644 --- a/website/content/en/docs/cli/operator-sdk_run_packagemanifests.md +++ b/website/content/en/docs/cli/operator-sdk_run_packagemanifests.md @@ -3,11 +3,12 @@ title: "operator-sdk run packagemanifests" --- ## operator-sdk run packagemanifests -Run an Operator organized in the package manifests format with OLM +Deploy an Operator in the package manifests format with OLM ### Synopsis -Run an Operator organized in the package manifests format with OLM +'run packagemanifests' deploys an Operator's package manifests with OLM. The command's argument +must be set to a valid package manifests root directory, ex. '/packagemanifests'. ``` operator-sdk run packagemanifests [flags] diff --git a/website/content/en/docs/new-cli/operator-sdk.md b/website/content/en/docs/new-cli/operator-sdk.md index b5f2aaeba8..0403617dce 100644 --- a/website/content/en/docs/new-cli/operator-sdk.md +++ b/website/content/en/docs/new-cli/operator-sdk.md @@ -75,5 +75,6 @@ operator-sdk [flags] * [operator-sdk init](../operator-sdk_init) - Initialize a new project * [operator-sdk new](../operator-sdk_new) - Creates a new operator application * [operator-sdk olm](../operator-sdk_olm) - Manage the Operator Lifecycle Manager installation in your cluster +* [operator-sdk run](../operator-sdk_run) - Run an Operator in a variety of environments * [operator-sdk version](../operator-sdk_version) - Prints the version of operator-sdk diff --git a/website/content/en/docs/new-cli/operator-sdk_run.md b/website/content/en/docs/new-cli/operator-sdk_run.md new file mode 100644 index 0000000000..3c50cfec00 --- /dev/null +++ b/website/content/en/docs/new-cli/operator-sdk_run.md @@ -0,0 +1,31 @@ +--- +title: "operator-sdk run" +--- +## operator-sdk run + +Run an Operator in a variety of environments + +### Synopsis + +This command has subcommands that will deploy your Operator with OLM. +Currently only the package manifests format is supported via the 'packagemanifests' subcommand. +Run 'operator-sdk run --help' for more information. + + +### Options + +``` + -h, --help help for run +``` + +### Options inherited from parent commands + +``` + --verbose Enable verbose logging +``` + +### SEE ALSO + +* [operator-sdk](../operator-sdk) - Development kit for building Kubernetes extensions and tools. +* [operator-sdk run packagemanifests](../operator-sdk_run_packagemanifests) - Deploy an Operator in the package manifests format with OLM + diff --git a/website/content/en/docs/new-cli/operator-sdk_run_packagemanifests.md b/website/content/en/docs/new-cli/operator-sdk_run_packagemanifests.md new file mode 100644 index 0000000000..e6746217e9 --- /dev/null +++ b/website/content/en/docs/new-cli/operator-sdk_run_packagemanifests.md @@ -0,0 +1,39 @@ +--- +title: "operator-sdk run packagemanifests" +--- +## operator-sdk run packagemanifests + +Deploy an Operator in the package manifests format with OLM + +### Synopsis + +'run packagemanifests' deploys an Operator's package manifests with OLM. The command's argument +must be set to a valid package manifests root directory, ex. '/packagemanifests'. + +``` +operator-sdk run packagemanifests [flags] +``` + +### Options + +``` + -h, --help help for packagemanifests + --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 The file path to kubernetes configuration file. Defaults to location specified by $KUBECONFIG, or to default file rules if not set + --olm-namespace string The namespace where OLM is installed (default "olm") + --operator-namespace string The namespace where operator resources are created. It must already exist in the cluster or be defined in a manifest passed to --include + --operator-version string Version of operator to deploy + --timeout duration Time to wait for the command to complete before failing (default 2m0s) +``` + +### Options inherited from parent commands + +``` + --verbose Enable verbose logging +``` + +### SEE ALSO + +* [operator-sdk run](../operator-sdk_run) - Run an Operator in a variety of environments +