Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ require (
rsc.io/letsencrypt v0.0.3 // indirect
sigs.k8s.io/controller-runtime v0.6.1
sigs.k8s.io/controller-tools v0.3.0
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e
sigs.k8s.io/yaml v1.2.0
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1078,8 +1078,8 @@ sigs.k8s.io/controller-runtime v0.6.1-0.20200724132623-e50c7b819263 h1:NXplhERc8
sigs.k8s.io/controller-runtime v0.6.1-0.20200724132623-e50c7b819263/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4=
sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b h1:FhUDioJh37CVomwCLftxP4AbW+gy/lw0QObz8QYe2VY=
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b/go.mod h1:lkExAOdnNf9BGrvi4lWHCMo1fa6xtENt/QVwDhWpK+c=
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e h1:S2x0oyND+3EZbO3u9Iqw0qZt1ijPInWXGxkQqfm/zgI=
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e/go.mod h1:lkExAOdnNf9BGrvi4lWHCMo1fa6xtENt/QVwDhWpK+c=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
Expand Down
9 changes: 7 additions & 2 deletions internal/cmd/operator-sdk/generate/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,20 @@ https://github.com/operator-framework/operator-registry/#manifest-format
const defaultRootDir = "bundle"

// setDefaults sets defaults useful to all modes of this subcommand.
func (c *bundleCmd) setDefaults(cfg *config.Config) {
func (c *bundleCmd) setDefaults(cfg *config.Config) error {
if c.operatorName == "" {
c.operatorName = filepath.Base(cfg.Repo)
projectName, err := genutil.GetOperatorName(cfg)
if err != nil {
return err
}
c.operatorName = projectName
}
// A default channel can be inferred if there is only one channel. Don't infer
// default otherwise; the user must set this value.
if c.defaultChannel == "" && strings.Count(c.channels, ",") == 0 {
c.defaultChannel = c.channels
}
return nil
}

// validateManifests validates c for bundle manifests generation.
Expand Down
5 changes: 4 additions & 1 deletion internal/cmd/operator-sdk/generate/bundle/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ func NewCmd() *cobra.Command {
if err != nil {
return fmt.Errorf("error reading configuration: %v", err)
}
c.setDefaults(cfg)

if err := c.setDefaults(cfg); err != nil {
return err
}

// Validate command args before running so a preceding mode doesn't run
// before a following validation fails.
Expand Down
25 changes: 25 additions & 0 deletions internal/cmd/operator-sdk/generate/internal/genutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ import (
"io"
"os"
"path/filepath"
"strings"

"k8s.io/apimachinery/pkg/util/validation"

"github.com/blang/semver"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"sigs.k8s.io/kubebuilder/pkg/model/config"
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -173,3 +177,24 @@ func IsNotExist(path string) bool {
_, err := os.Stat(path)
return err != nil && errors.Is(err, os.ErrNotExist)
}

// GetOperatorName returns the name of the operator which is by default the projectName attribute of the PROJECT file
// However, the Go projects built with the plugin version v2 has not this attribute and then, for this case
// the operatorName will be the current directory.
func GetOperatorName(cfg *config.Config) (string, error) {
if cfg.ProjectName != "" {
return cfg.ProjectName, nil
}
if cfg.IsV3() {
return "", errors.New("project config file must contain 'projectName'")
}
dir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("error getting current directory: %v", err)
}
projectName := strings.ToLower(filepath.Base(dir))
if err := validation.IsDNS1123Label(projectName); err != nil {
return "", fmt.Errorf("project name (%s) is invalid: %v", projectName, err)
}
return projectName, nil
}
15 changes: 12 additions & 3 deletions internal/cmd/operator-sdk/generate/kustomize/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/spf13/pflag"
"sigs.k8s.io/kubebuilder/pkg/model/config"

genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal"
gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion"
"github.com/operator-framework/operator-sdk/internal/plugins/util/kustomize"
"github.com/operator-framework/operator-sdk/internal/util/projutil"
Expand Down Expand Up @@ -97,7 +98,10 @@ func newManifestsCmd() *cobra.Command {
if err != nil {
return fmt.Errorf("error reading configuration: %v", err)
}
c.setDefaults(cfg)

if err := c.setDefaults(cfg); err != nil {
return err
}

// Run command logic.
if err = c.run(cfg); err != nil {
Expand Down Expand Up @@ -127,9 +131,13 @@ func (c *manifestsCmd) addFlagsTo(fs *pflag.FlagSet) {
var defaultDir = filepath.Join("config", "manifests")

// setDefaults sets command defaults.
func (c *manifestsCmd) setDefaults(cfg *config.Config) {
func (c *manifestsCmd) setDefaults(cfg *config.Config) error {
if c.operatorName == "" {
c.operatorName = filepath.Base(cfg.Repo)
projectName, err := genutil.GetOperatorName(cfg)
if err != nil {
return err
}
c.operatorName = projectName
}

if c.inputDir == "" {
Expand All @@ -145,6 +153,7 @@ func (c *manifestsCmd) setDefaults(cfg *config.Config) {
c.apisDir = "api"
}
}
return nil
}

// kustomization.yaml file contents for manifests. this should always be written to
Expand Down
4 changes: 3 additions & 1 deletion internal/cmd/operator-sdk/generate/packagemanifests/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func NewCmd() *cobra.Command {
if err != nil {
log.Fatal(fmt.Errorf("error reading configuration: %v", err))
}
c.setDefaults(cfg)
if err := c.setDefaults(cfg); err != nil {
return err
}

if err = c.validate(); err != nil {
return fmt.Errorf("invalid command options: %v", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ https://github.com/operator-framework/operator-registry/#manifest-format
const defaultRootDir = "packagemanifests"

// setDefaults sets command defaults.
func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) {
func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) error {
if c.operatorName == "" {
c.operatorName = filepath.Base(cfg.Repo)
projectName, err := genutil.GetOperatorName(cfg)
if err != nil {
return err
}
c.operatorName = projectName
}

if c.inputDir == "" {
Expand All @@ -92,6 +96,7 @@ func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) {
c.outputDir = defaultRootDir
}
}
return nil
}

// validate validates c for package manifests generation.
Expand Down
69 changes: 66 additions & 3 deletions test/e2e-helm/e2e_helm_olm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,88 @@
package e2e_helm_test

import (
"fmt"
"os/exec"
"path"
"path/filepath"
"strings"

. "github.com/onsi/ginkgo" //nolint:golint
. "github.com/onsi/gomega" //nolint:golint

testutils "github.com/operator-framework/operator-sdk/test/internal"
)

var _ = PDescribe("Integrating Helm Projects with OLM", func() {
var _ = Describe("Integrating Helm Projects with OLM", func() {
Context("with operator-sdk", func() {
const operatorVersion = "0.0.1"

BeforeEach(func() {
By("Turning off interactive prompts for all generation tasks.")
By("turning off interactive prompts for all generation tasks.")
replace := "operator-sdk generate kustomize manifests"
testutils.ReplaceInFile(filepath.Join(tc.Dir, "Makefile"), replace, replace+" --interactive=false")
})

AfterEach(func() {
By("destroying the deployed package manifests-formatted operator")
cleanupPkgManCmd := exec.Command(tc.BinaryName, "cleanup", "packagemanifests",
"--operator-version", operatorVersion,
"--timeout", "4m")
_, _ = tc.Run(cleanupPkgManCmd)

By("uninstalling CRD's")
_ = tc.Make("uninstall")
})

It("Should allow generate the OLM bundle and run it", func() {
It("should generate and run a valid OLM bundle and packagemanifests", func() {
By("building the bundle")
err := tc.Make("bundle")
Expect(err).NotTo(HaveOccurred())

By("validating the bundle")
bundleValidateCmd := exec.Command(tc.BinaryName, "bundle", "validate", "bundle")
_, err = tc.Run(bundleValidateCmd)
Expect(err).NotTo(HaveOccurred())

By("building the operator bundle image")
// Use the existing image tag but with a "-bundle" suffix.
imageSplit := strings.SplitN(tc.ImageName, ":", 2)
bundleImage := path.Join("quay.io", imageSplit[0]+"-bundle")
if len(imageSplit) == 2 {
bundleImage += ":" + imageSplit[1]
}
err = tc.Make("bundle-build", "BUNDLE_IMG="+bundleImage)
Expect(err).NotTo(HaveOccurred())

By("loading the project image into Kind cluster")
err = tc.LoadImageToKindClusterWithName(bundleImage)
Expect(err).Should(Succeed())

By("adding the 'packagemanifests' rule to the Makefile")
err = tc.AddPackagemanifestsTarget()
Expect(err).Should(Succeed())

By("generating the operator package manifests")
err = tc.Make("packagemanifests")
Expect(err).NotTo(HaveOccurred())

By("updating clusterserviceversion with the manager image")
testutils.ReplaceInFile(
filepath.Join(tc.Dir, "packagemanifests", operatorVersion,
fmt.Sprintf("e2e-%s.clusterserviceversion.yaml", tc.TestSuffix)),
"controller:latest", tc.ImageName)

By("installing crds to run packagemanifests")
err = tc.Make("install")
Expect(err).NotTo(HaveOccurred())

By("running the package")
runPkgManCmd := exec.Command(tc.BinaryName, "run", "packagemanifests",
"--install-mode", "AllNamespaces",
"--operator-version", operatorVersion,
"--timeout", "4m")
_, err = tc.Run(runPkgManCmd)
Expect(err).NotTo(HaveOccurred())
Comment on lines +75 to +99
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we separate the generate/run bundle tests from the generate/run packagemanifests tests?

Can be done in a follow-up

})
})
})
43 changes: 43 additions & 0 deletions test/internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"

. "github.com/onsi/ginkgo" //nolint:golint
Expand All @@ -27,6 +28,23 @@ import (
kbtestutils "sigs.k8s.io/kubebuilder/test/e2e/utils"
)

// Makefile fragments to add to the base Makefile just to ensure the packagemanifests feature
const makefilePackagemanifests = `
# Options for "packagemanifests".
ifneq ($(origin CHANNEL), undefined)
PKG_CHANNELS := --channel=$(CHANNEL)
endif
ifeq ($(IS_CHANNEL_DEFAULT), 1)
PKG_IS_DEFAULT_CHANNEL := --default-channel
endif
PKG_MAN_OPTS ?= $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)

# Generate package manifests.
packagemanifests: kustomize
operator-sdk generate kustomize manifests -q --interactive=false
$(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)
`

// TestContext wraps kubebuilder's e2e TestContext.
type TestContext struct {
*kbtestutils.TestContext
Expand Down Expand Up @@ -58,6 +76,23 @@ func (tc TestContext) KustomizeBuild(dir string) ([]byte, error) {
return tc.Run(exec.Command("kustomize", "build", dir))
}

// AddPackagemanifestsTarget will append the packagemanifests target to the makefile
// in order to test the steps described in the docs.
// More info: https://master.sdk.operatorframework.io/docs/olm-integration/generation/#package-manifests-formats
func (tc TestContext) AddPackagemanifestsTarget() error {
makefileBytes, err := ioutil.ReadFile(filepath.Join(tc.Dir, "Makefile"))
if err != nil {
return err
}

makefileBytes = append([]byte(makefilePackagemanifests), makefileBytes...)
err = ioutil.WriteFile(filepath.Join(tc.Dir, "Makefile"), makefileBytes, 0644)
if err != nil {
return err
}
return nil
}

// ReplaceInFile replaces all instances of old with new in the file at path.
func ReplaceInFile(path, old, new string) {
info, err := os.Stat(path)
Expand All @@ -68,3 +103,11 @@ func ReplaceInFile(path, old, new string) {
err = ioutil.WriteFile(path, []byte(s), info.Mode())
ExpectWithOffset(1, err).NotTo(HaveOccurred())
}

// LoadImageToKindCluster loads a local docker image with the name informed to the kind cluster
func (tc TestContext) LoadImageToKindClusterWithName(image string) error {
kindOptions := []string{"load", "docker-image", image}
cmd := exec.Command("kind", kindOptions...)
_, err := tc.Run(cmd)
return err
}
1 change: 1 addition & 0 deletions website/content/en/docs/cli/operator-sdk_init.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ operator-sdk init [flags]
--license string license to use to boilerplate, may be one of 'apache2', 'none' (default "apache2")
--owner string owner to add to the copyright
--plugins strings Name and optionally version of the plugin to initialize the project with. Available plugins: ("ansible.sdk.operatorframework.io/v1", "go.kubebuilder.io/v2", "helm.sdk.operatorframework.io/v1")
--project-name string name of this project
--project-version string project version, possible values: ("2", "3-alpha") (default "3-alpha")
--repo string name to use for go module (e.g., github.com/user/repo), defaults to the go package of the current working directory.
--skip-go-version-check if specified, skip checking the Go version
Expand Down
27 changes: 25 additions & 2 deletions website/content/en/docs/olm-integration/generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,29 @@ package manifest YAML file containing channel-to-version mappings, much like a b
If your Operator is already formatted as a package manifests and you do not wish to migrate to the bundle format yet,
you should add the following to your `Makefile` to make development easier:

**For Go-based Operator projects**

```make
# Options for "packagemanifests".
ifneq ($(origin FROM_VERSION), undefined)
PKG_FROM_VERSION := --from-version=$(FROM_VERSION)
endif
ifneq ($(origin CHANNEL), undefined)
PKG_CHANNELS := --channel=$(CHANNEL)
endif
ifeq ($(IS_CHANNEL_DEFAULT), 1)
PKG_IS_DEFAULT_CHANNEL := --default-channel
endif
PKG_MAN_OPTS ?= $(FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)

# Generate package manifests.
packagemanifests: kustomize manifests
operator-sdk generate kustomize manifests -q
$(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)
```
Comment on lines +126 to +145
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch - kind of a bummer that we have to duplicate this entire block because of the single manifests dependency on the packagemanifests target.

This is one of those things that makes organization on our docs site extremely difficult when dealing with three operator types.

I'm almost to the point where I could be convinced to duplicate this (or some portion of this) doc (and other docs with similar issues) for each operator type.

This is okay for now, but definitely something we could think about improving later.

Copy link
Contributor Author

@camilamacedo86 camilamacedo86 Jul 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we need to clean up the docs .. keeping it mind for follow-ups. My suggestion here was added just a note for Ansible/Helm since we need just remove the manifests. However, @estroz thought that would be easier understand by duplicating which is true as well/.


**For Helm/Ansible-based Operator projects**

```make
# Options for "packagemanifests".
ifneq ($(origin FROM_VERSION), undefined)
Expand All @@ -137,9 +160,9 @@ endif
PKG_MAN_OPTS ?= $(FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)

# Generate package manifests.
packagemanifests: manifests
packagemanifests: kustomize
operator-sdk generate kustomize manifests -q
kustomize build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)
$(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)
```

By default `make packagemanifests` will generate a CSV, a package manifest file, and copy CRDs in the package manifests format:
Expand Down