Skip to content

Commit 56b50ac

Browse files
Allows OLM subcommands work for Helm/Ansible new layout (#3341)
**Description of the change:** - fix OLM subcommands to be able to get the operator name via the project name in the project file or the current directory. - add e2e tests to ensure that the bundle subcommands are working for projects scaffolds with Helm plugin and the new layout. - upgrade the version of kb used
1 parent ad2759e commit 56b50ac

File tree

12 files changed

+196
-17
lines changed

12 files changed

+196
-17
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ require (
4040
rsc.io/letsencrypt v0.0.3 // indirect
4141
sigs.k8s.io/controller-runtime v0.6.1
4242
sigs.k8s.io/controller-tools v0.3.0
43-
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b
43+
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e
4444
sigs.k8s.io/yaml v1.2.0
4545
)
4646

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,8 +1078,8 @@ sigs.k8s.io/controller-runtime v0.6.1-0.20200724132623-e50c7b819263 h1:NXplhERc8
10781078
sigs.k8s.io/controller-runtime v0.6.1-0.20200724132623-e50c7b819263/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
10791079
sigs.k8s.io/controller-tools v0.3.0 h1:y3YD99XOyWaXkiF1kd41uRvfp/64teWcrEZFuHxPhJ4=
10801080
sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
1081-
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b h1:FhUDioJh37CVomwCLftxP4AbW+gy/lw0QObz8QYe2VY=
1082-
sigs.k8s.io/kubebuilder v1.0.9-0.20200723213622-353f7a6ba73b/go.mod h1:lkExAOdnNf9BGrvi4lWHCMo1fa6xtENt/QVwDhWpK+c=
1081+
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e h1:S2x0oyND+3EZbO3u9Iqw0qZt1ijPInWXGxkQqfm/zgI=
1082+
sigs.k8s.io/kubebuilder v1.0.9-0.20200724202016-21f9343e992e/go.mod h1:lkExAOdnNf9BGrvi4lWHCMo1fa6xtENt/QVwDhWpK+c=
10831083
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
10841084
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
10851085
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=

internal/cmd/operator-sdk/generate/bundle/bundle.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,20 @@ https://github.com/operator-framework/operator-registry/#manifest-format
105105
const defaultRootDir = "bundle"
106106

107107
// setDefaults sets defaults useful to all modes of this subcommand.
108-
func (c *bundleCmd) setDefaults(cfg *config.Config) {
108+
func (c *bundleCmd) setDefaults(cfg *config.Config) error {
109109
if c.operatorName == "" {
110-
c.operatorName = filepath.Base(cfg.Repo)
110+
projectName, err := genutil.GetOperatorName(cfg)
111+
if err != nil {
112+
return err
113+
}
114+
c.operatorName = projectName
111115
}
112116
// A default channel can be inferred if there is only one channel. Don't infer
113117
// default otherwise; the user must set this value.
114118
if c.defaultChannel == "" && strings.Count(c.channels, ",") == 0 {
115119
c.defaultChannel = c.channels
116120
}
121+
return nil
117122
}
118123

119124
// validateManifests validates c for bundle manifests generation.

internal/cmd/operator-sdk/generate/bundle/cmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ func NewCmd() *cobra.Command {
7272
if err != nil {
7373
return fmt.Errorf("error reading configuration: %v", err)
7474
}
75-
c.setDefaults(cfg)
75+
76+
if err := c.setDefaults(cfg); err != nil {
77+
return err
78+
}
7679

7780
// Validate command args before running so a preceding mode doesn't run
7881
// before a following validation fails.

internal/cmd/operator-sdk/generate/internal/genutil.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ import (
2121
"io"
2222
"os"
2323
"path/filepath"
24+
"strings"
25+
26+
"k8s.io/apimachinery/pkg/util/validation"
2427

2528
"github.com/blang/semver"
2629
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2730
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
31+
"sigs.k8s.io/kubebuilder/pkg/model/config"
2832
"sigs.k8s.io/yaml"
2933
)
3034

@@ -173,3 +177,24 @@ func IsNotExist(path string) bool {
173177
_, err := os.Stat(path)
174178
return err != nil && errors.Is(err, os.ErrNotExist)
175179
}
180+
181+
// GetOperatorName returns the name of the operator which is by default the projectName attribute of the PROJECT file
182+
// However, the Go projects built with the plugin version v2 has not this attribute and then, for this case
183+
// the operatorName will be the current directory.
184+
func GetOperatorName(cfg *config.Config) (string, error) {
185+
if cfg.ProjectName != "" {
186+
return cfg.ProjectName, nil
187+
}
188+
if cfg.IsV3() {
189+
return "", errors.New("project config file must contain 'projectName'")
190+
}
191+
dir, err := os.Getwd()
192+
if err != nil {
193+
return "", fmt.Errorf("error getting current directory: %v", err)
194+
}
195+
projectName := strings.ToLower(filepath.Base(dir))
196+
if err := validation.IsDNS1123Label(projectName); err != nil {
197+
return "", fmt.Errorf("project name (%s) is invalid: %v", projectName, err)
198+
}
199+
return projectName, nil
200+
}

internal/cmd/operator-sdk/generate/kustomize/manifests.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/spf13/pflag"
2424
"sigs.k8s.io/kubebuilder/pkg/model/config"
2525

26+
genutil "github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal"
2627
gencsv "github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion"
2728
"github.com/operator-framework/operator-sdk/internal/plugins/util/kustomize"
2829
"github.com/operator-framework/operator-sdk/internal/util/projutil"
@@ -97,7 +98,10 @@ func newManifestsCmd() *cobra.Command {
9798
if err != nil {
9899
return fmt.Errorf("error reading configuration: %v", err)
99100
}
100-
c.setDefaults(cfg)
101+
102+
if err := c.setDefaults(cfg); err != nil {
103+
return err
104+
}
101105

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

129133
// setDefaults sets command defaults.
130-
func (c *manifestsCmd) setDefaults(cfg *config.Config) {
134+
func (c *manifestsCmd) setDefaults(cfg *config.Config) error {
131135
if c.operatorName == "" {
132-
c.operatorName = filepath.Base(cfg.Repo)
136+
projectName, err := genutil.GetOperatorName(cfg)
137+
if err != nil {
138+
return err
139+
}
140+
c.operatorName = projectName
133141
}
134142

135143
if c.inputDir == "" {
@@ -145,6 +153,7 @@ func (c *manifestsCmd) setDefaults(cfg *config.Config) {
145153
c.apisDir = "api"
146154
}
147155
}
156+
return nil
148157
}
149158

150159
// kustomization.yaml file contents for manifests. this should always be written to

internal/cmd/operator-sdk/generate/packagemanifests/cmd.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ func NewCmd() *cobra.Command {
6363
if err != nil {
6464
log.Fatal(fmt.Errorf("error reading configuration: %v", err))
6565
}
66-
c.setDefaults(cfg)
66+
if err := c.setDefaults(cfg); err != nil {
67+
return err
68+
}
6769

6870
if err = c.validate(); err != nil {
6971
return fmt.Errorf("invalid command options: %v", err)

internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,13 @@ https://github.com/operator-framework/operator-registry/#manifest-format
7979
const defaultRootDir = "packagemanifests"
8080

8181
// setDefaults sets command defaults.
82-
func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) {
82+
func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) error {
8383
if c.operatorName == "" {
84-
c.operatorName = filepath.Base(cfg.Repo)
84+
projectName, err := genutil.GetOperatorName(cfg)
85+
if err != nil {
86+
return err
87+
}
88+
c.operatorName = projectName
8589
}
8690

8791
if c.inputDir == "" {
@@ -92,6 +96,7 @@ func (c *packagemanifestsCmd) setDefaults(cfg *config.Config) {
9296
c.outputDir = defaultRootDir
9397
}
9498
}
99+
return nil
95100
}
96101

97102
// validate validates c for package manifests generation.

test/e2e-helm/e2e_helm_olm_test.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,88 @@
1515
package e2e_helm_test
1616

1717
import (
18+
"fmt"
19+
"os/exec"
20+
"path"
1821
"path/filepath"
22+
"strings"
1923

2024
. "github.com/onsi/ginkgo" //nolint:golint
25+
. "github.com/onsi/gomega" //nolint:golint
2126

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

25-
var _ = PDescribe("Integrating Helm Projects with OLM", func() {
30+
var _ = Describe("Integrating Helm Projects with OLM", func() {
2631
Context("with operator-sdk", func() {
32+
const operatorVersion = "0.0.1"
33+
2734
BeforeEach(func() {
28-
By("Turning off interactive prompts for all generation tasks.")
35+
By("turning off interactive prompts for all generation tasks.")
2936
replace := "operator-sdk generate kustomize manifests"
3037
testutils.ReplaceInFile(filepath.Join(tc.Dir, "Makefile"), replace, replace+" --interactive=false")
3138
})
3239

3340
AfterEach(func() {
41+
By("destroying the deployed package manifests-formatted operator")
42+
cleanupPkgManCmd := exec.Command(tc.BinaryName, "cleanup", "packagemanifests",
43+
"--operator-version", operatorVersion,
44+
"--timeout", "4m")
45+
_, _ = tc.Run(cleanupPkgManCmd)
46+
47+
By("uninstalling CRD's")
48+
_ = tc.Make("uninstall")
3449
})
3550

36-
It("Should allow generate the OLM bundle and run it", func() {
51+
It("should generate and run a valid OLM bundle and packagemanifests", func() {
52+
By("building the bundle")
53+
err := tc.Make("bundle")
54+
Expect(err).NotTo(HaveOccurred())
55+
56+
By("validating the bundle")
57+
bundleValidateCmd := exec.Command(tc.BinaryName, "bundle", "validate", "bundle")
58+
_, err = tc.Run(bundleValidateCmd)
59+
Expect(err).NotTo(HaveOccurred())
60+
61+
By("building the operator bundle image")
62+
// Use the existing image tag but with a "-bundle" suffix.
63+
imageSplit := strings.SplitN(tc.ImageName, ":", 2)
64+
bundleImage := path.Join("quay.io", imageSplit[0]+"-bundle")
65+
if len(imageSplit) == 2 {
66+
bundleImage += ":" + imageSplit[1]
67+
}
68+
err = tc.Make("bundle-build", "BUNDLE_IMG="+bundleImage)
69+
Expect(err).NotTo(HaveOccurred())
70+
71+
By("loading the project image into Kind cluster")
72+
err = tc.LoadImageToKindClusterWithName(bundleImage)
73+
Expect(err).Should(Succeed())
74+
75+
By("adding the 'packagemanifests' rule to the Makefile")
76+
err = tc.AddPackagemanifestsTarget()
77+
Expect(err).Should(Succeed())
78+
79+
By("generating the operator package manifests")
80+
err = tc.Make("packagemanifests")
81+
Expect(err).NotTo(HaveOccurred())
82+
83+
By("updating clusterserviceversion with the manager image")
84+
testutils.ReplaceInFile(
85+
filepath.Join(tc.Dir, "packagemanifests", operatorVersion,
86+
fmt.Sprintf("e2e-%s.clusterserviceversion.yaml", tc.TestSuffix)),
87+
"controller:latest", tc.ImageName)
88+
89+
By("installing crds to run packagemanifests")
90+
err = tc.Make("install")
91+
Expect(err).NotTo(HaveOccurred())
92+
93+
By("running the package")
94+
runPkgManCmd := exec.Command(tc.BinaryName, "run", "packagemanifests",
95+
"--install-mode", "AllNamespaces",
96+
"--operator-version", operatorVersion,
97+
"--timeout", "4m")
98+
_, err = tc.Run(runPkgManCmd)
99+
Expect(err).NotTo(HaveOccurred())
37100
})
38101
})
39102
})

test/internal/utils.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"io/ioutil"
2020
"os"
2121
"os/exec"
22+
"path/filepath"
2223
"strings"
2324

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

31+
// Makefile fragments to add to the base Makefile just to ensure the packagemanifests feature
32+
const makefilePackagemanifests = `
33+
# Options for "packagemanifests".
34+
ifneq ($(origin CHANNEL), undefined)
35+
PKG_CHANNELS := --channel=$(CHANNEL)
36+
endif
37+
ifeq ($(IS_CHANNEL_DEFAULT), 1)
38+
PKG_IS_DEFAULT_CHANNEL := --default-channel
39+
endif
40+
PKG_MAN_OPTS ?= $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)
41+
42+
# Generate package manifests.
43+
packagemanifests: kustomize
44+
operator-sdk generate kustomize manifests -q --interactive=false
45+
$(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)
46+
`
47+
3048
// TestContext wraps kubebuilder's e2e TestContext.
3149
type TestContext struct {
3250
*kbtestutils.TestContext
@@ -58,6 +76,23 @@ func (tc TestContext) KustomizeBuild(dir string) ([]byte, error) {
5876
return tc.Run(exec.Command("kustomize", "build", dir))
5977
}
6078

79+
// AddPackagemanifestsTarget will append the packagemanifests target to the makefile
80+
// in order to test the steps described in the docs.
81+
// More info: https://master.sdk.operatorframework.io/docs/olm-integration/generation/#package-manifests-formats
82+
func (tc TestContext) AddPackagemanifestsTarget() error {
83+
makefileBytes, err := ioutil.ReadFile(filepath.Join(tc.Dir, "Makefile"))
84+
if err != nil {
85+
return err
86+
}
87+
88+
makefileBytes = append([]byte(makefilePackagemanifests), makefileBytes...)
89+
err = ioutil.WriteFile(filepath.Join(tc.Dir, "Makefile"), makefileBytes, 0644)
90+
if err != nil {
91+
return err
92+
}
93+
return nil
94+
}
95+
6196
// ReplaceInFile replaces all instances of old with new in the file at path.
6297
func ReplaceInFile(path, old, new string) {
6398
info, err := os.Stat(path)
@@ -68,3 +103,11 @@ func ReplaceInFile(path, old, new string) {
68103
err = ioutil.WriteFile(path, []byte(s), info.Mode())
69104
ExpectWithOffset(1, err).NotTo(HaveOccurred())
70105
}
106+
107+
// LoadImageToKindCluster loads a local docker image with the name informed to the kind cluster
108+
func (tc TestContext) LoadImageToKindClusterWithName(image string) error {
109+
kindOptions := []string{"load", "docker-image", image}
110+
cmd := exec.Command("kind", kindOptions...)
111+
_, err := tc.Run(cmd)
112+
return err
113+
}

0 commit comments

Comments
 (0)