@@ -19,18 +19,23 @@ import (
1919 "fmt"
2020 "io/ioutil"
2121 "os"
22+ "path/filepath"
23+ "strings"
2224
2325 "sigs.k8s.io/kubebuilder/v3/pkg/config"
2426 cfgv3 "sigs.k8s.io/kubebuilder/v3/pkg/config/v3"
2527
2628 "github.com/operator-framework/operator-sdk/internal/util/projutil"
2729)
2830
31+ // Version of `opm` to download and use for building index images.
32+ // This version's release artifacts *must* contain a binary for multiple arches; certain releases do not.
33+ const opmVersion = "v1.15.1"
34+
2935// RunInit modifies the project scaffolded by kubebuilder's Init plugin.
3036func RunInit (cfg config.Config ) error {
3137 // Only run these if project version is v3.
32- isV3 := cfg .GetVersion ().Compare (cfgv3 .Version ) == 0
33- if ! isV3 {
38+ if cfg .GetVersion ().Compare (cfgv3 .Version ) != 0 {
3439 return nil
3540 }
3641
@@ -43,26 +48,44 @@ func RunInit(cfg config.Config) error {
4348
4449// initUpdateMakefile updates a vanilla kubebuilder Makefile with operator-sdk recipes.
4550func initUpdateMakefile (cfg config.Config , filePath string ) error {
51+ operatorType := projutil .PluginKeyToOperatorType (cfg .GetLayout ())
52+ if operatorType == projutil .OperatorTypeUnknown {
53+ return fmt .Errorf ("unsupported plugin key %q" , cfg .GetLayout ())
54+ }
55+
4656 makefileBytes , err := ioutil .ReadFile (filePath )
4757 if err != nil {
4858 return err
4959 }
5060
5161 // Prepend bundle variables.
52- makefileBytes = append ([]byte (makefileBundleVarFragment ), makefileBytes ... )
62+ projectName := cfg .GetProjectName ()
63+ if projectName == "" {
64+ dir , err := os .Getwd ()
65+ if err != nil {
66+ return fmt .Errorf ("error getting current directory: %v" , err )
67+ }
68+ projectName = strings .ToLower (filepath .Base (dir ))
69+ }
70+ makefileBytes = append ([]byte (fmt .Sprintf (makefileBundleVarFragment , cfg .GetDomain (), projectName )), makefileBytes ... )
5371
5472 // Append bundle recipes.
55- operatorType := projutil .PluginKeyToOperatorType (cfg .GetLayout ())
5673 switch operatorType {
57- case projutil .OperatorTypeUnknown :
58- return fmt .Errorf ("unsupported plugin key %q" , cfg .GetLayout ())
5974 case projutil .OperatorTypeGo :
6075 makefileBytes = append (makefileBytes , []byte (makefileBundleFragmentGo )... )
6176 default :
6277 makefileBytes = append (makefileBytes , []byte (makefileBundleFragmentNonGo )... )
6378 }
79+ makefileBytes = append (makefileBytes , []byte (makefileBundleBuildPushFragment )... )
6480
65- makefileBytes = append (makefileBytes , []byte (makefileBundleBuildFragment )... )
81+ // Append catalog recipes.
82+ switch operatorType {
83+ case projutil .OperatorTypeGo :
84+ makefileBytes = append (makefileBytes , []byte (fmt .Sprintf (makefileOPMFragmentGo , opmVersion ))... )
85+ default :
86+ makefileBytes = append (makefileBytes , []byte (fmt .Sprintf (makefileOPMFragmentNonGo , opmVersion ))... )
87+ }
88+ makefileBytes = append (makefileBytes , []byte (makefileCatalogBuildFragment )... )
6689
6790 var mode os.FileMode = 0644
6891 if info , err := os .Stat (filePath ); err != nil {
@@ -73,14 +96,14 @@ func initUpdateMakefile(cfg config.Config, filePath string) error {
7396
7497// Makefile fragments to add to the base Makefile.
7598const (
76- makefileBundleVarFragment = `# VERSION defines the project version for the bundle.
99+ makefileBundleVarFragment = `# VERSION defines the project version for the bundle.
77100# Update this value when you upgrade the version of your project.
78101# To re-generate a bundle for another specific version without changing the standard setup, you can:
79102# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
80103# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
81104VERSION ?= 0.0.1
82105
83- # CHANNELS define the bundle channels used in the bundle.
106+ # CHANNELS define the bundle channels used in the bundle.
84107# Add a new line here if you would like to change its default config. (E.g CHANNELS = "preview,fast,stable")
85108# To re-generate a bundle for other specific channels without changing the standard setup, you can:
86109# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=preview,fast,stable)
@@ -89,7 +112,7 @@ ifneq ($(origin CHANNELS), undefined)
89112BUNDLE_CHANNELS := --channels=$(CHANNELS)
90113endif
91114
92- # DEFAULT_CHANNEL defines the default channel used in the bundle.
115+ # DEFAULT_CHANNEL defines the default channel used in the bundle.
93116# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable")
94117# To re-generate a bundle for any other default channel without changing the default setup, you can:
95118# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)
@@ -99,32 +122,106 @@ BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
99122endif
100123BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
101124
102- # BUNDLE_IMG defines the image:tag used for the bundle.
125+ # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.
126+ # This variable is used to construct full image tags for bundle and catalog images.
127+ #
128+ # For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both
129+ # %[1]s/%[2]s-bundle:$VERSION and %[1]s/%[2]s-catalog:$VERSION.
130+ IMAGE_TAG_BASE ?= %[1]s/%[2]s
131+
132+ # BUNDLE_IMG defines the image:tag used for the bundle.
103133# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)
104- BUNDLE_IMG ?= controller -bundle:$(VERSION)
134+ BUNDLE_IMG ?= $(IMAGE_TAG_BASE) -bundle:v $(VERSION)
105135`
106136
107137 makefileBundleFragmentGo = `
108- .PHONY: bundle ## Generate bundle manifests and metadata, then validate generated files.
109- bundle: manifests kustomize
138+ .PHONY: bundle
139+ bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.
110140 operator-sdk generate kustomize manifests -q
111141 cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
112142 $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
113143 operator-sdk bundle validate ./bundle
114144`
115145
116146 makefileBundleFragmentNonGo = `
117- .PHONY: bundle ## Generate bundle manifests and metadata, then validate generated files.
118- bundle: kustomize
147+ .PHONY: bundle
148+ bundle: kustomize ## Generate bundle manifests and metadata, then validate generated files.
119149 operator-sdk generate kustomize manifests -q
120150 cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
121151 $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
122152 operator-sdk bundle validate ./bundle
123153`
124154
125- makefileBundleBuildFragment = `
126- .PHONY: bundle-build ## Build the bundle image.
127- bundle-build:
155+ makefileBundleBuildPushFragment = `
156+ .PHONY: bundle-build
157+ bundle-build: ## Build the bundle image.
128158 docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
159+
160+ .PHONY: bundle-push
161+ bundle-push: ## Push the bundle image.
162+ $(MAKE) docker-push IMG=$(BUNDLE_IMG)
163+ `
164+
165+ makefileOPMFragmentGo = `
166+ .PHONY: opm
167+ OPM = ./bin/opm
168+ opm: ## Download opm locally if necessary.
169+ ifeq (,$(wildcard $(OPM)))
170+ ifeq (,$(shell which opm 2>/dev/null))
171+ @{ \
172+ set -e ;\
173+ mkdir -p $(dir $(OPM)) ;\
174+ OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \
175+ curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/%[1]s/$${OS}-$${ARCH}-opm ;\
176+ chmod +x $(OPM) ;\
177+ }
178+ else
179+ OPM = $(shell which opm)
180+ endif
181+ endif
182+ `
183+
184+ makefileOPMFragmentNonGo = `
185+ .PHONY: opm
186+ OPM = ./bin/opm
187+ opm: ## Download opm locally if necessary.
188+ ifeq (,$(wildcard $(OPM)))
189+ ifeq (,$(shell which opm 2>/dev/null))
190+ @{ \
191+ set -e ;\
192+ mkdir -p $(dir $(OPM)) ;\
193+ curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/%[1]s/$(OS)-$(ARCH)-opm ;\
194+ chmod +x $(OPM) ;\
195+ }
196+ else
197+ OPM = $(shell which opm)
198+ endif
199+ endif
200+ `
201+
202+ makefileCatalogBuildFragment = `
203+ # A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).
204+ # These images MUST exist in a registry and be pull-able.
205+ BUNDLE_IMGS ?= $(BUNDLE_IMG)
206+
207+ # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).
208+ CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)
209+
210+ # Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.
211+ ifneq ($(origin CATALOG_BASE_IMG), undefined)
212+ FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)
213+ endif
214+
215+ # Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.
216+ # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:
217+ # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator
218+ .PHONY: catalog-build
219+ catalog-build: opm ## Build a catalog image.
220+ $(OPM) index add --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
221+
222+ # Push the catalog image.
223+ .PHONY: catalog-push
224+ catalog-push: ## Push a catalog image.
225+ $(MAKE) docker-push IMG=$(CATALOG_IMG)
129226`
130227)
0 commit comments