Skip to content

plugin: write Makefile recipes for generate bundle subcommand#2860

Merged
estroz merged 1 commit intooperator-framework:masterfrom
estroz:feature/csv-stdin
Jun 9, 2020
Merged

plugin: write Makefile recipes for generate bundle subcommand#2860
estroz merged 1 commit intooperator-framework:masterfrom
estroz:feature/csv-stdin

Conversation

@estroz
Copy link
Copy Markdown
Member

@estroz estroz commented Apr 17, 2020

Description of the change:
Changes:

  • operator-sdk init writes config/bundle/kustomization.yaml and adds bundle and bundle-build recipes that generate a bundle on disk and build a bundle image, respectively.
  • operator-sdk create api manages config/samples/kustomization.yaml so kustomize build config/bundle retrieves custom resource samples.

Motivation for the change:

Example workflow:

$ operator-sdk init
$ operator-sdk create api --group ship --version v1beta1 --kind Frigate

Then invoke:

$ make bundle 
/home/estroz/go/bin/controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle -q --kustomize
kustomize build config/bundle | operator-sdk generate bundle -q --manifests --metadata --overwrite --version 0.0.1
$ make bundle-build
docker build -f bundle.Dockerfile -t controller-manager-bundle:latest .

TODO:

Reference PR: #2956

/kind feature

@estroz estroz added the kubebuilder-integration Relates to rewriting the SDK in Kubebuilder plugin form label Apr 17, 2020
@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 17, 2020
@estroz estroz force-pushed the feature/csv-stdin branch 2 times, most recently from bf718cb to e73639e Compare April 17, 2020 21:20
@estroz estroz force-pushed the feature/csv-stdin branch from e73639e to 7d0f684 Compare April 17, 2020 22:41
@openshift-ci-robot openshift-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 19, 2020
@joelanford
Copy link
Copy Markdown
Member

Overall looks like a great start! A few comments:

  • I'm not a huge fan of introducing a new update subcommand for this. Is there a way that operator-sdk update bundle can be folded into operator-sdk generate bundle?

    I think one question we need to answer is this: Do we or users care about persisting the result of operator-sdk update bundle -q? If not, then can operator-sdk generate bundle do the marker parsing and CSV building in memory, so that only the base UI metadata needs to be persisted?

  • IIRC, the bundle manifests directory has to have a file in it with a clusterserviceversion.yaml suffix. Do we need to split out memcached-operator.bundle.yaml into its constituent parts?

@estroz
Copy link
Copy Markdown
Member Author

estroz commented Apr 21, 2020

@joelanford Perhaps it would be better to fold update bundle into generate bundle; when in-binary CSV generation is removed in favor of kustomize build, the UI metadata generation component in generate bundle can stick around.

As for CSV file suffix: do you mean that is a requirement in the SDK (generate csv) or elsewhere?

@joelanford
Copy link
Copy Markdown
Member

@joelanford Perhaps it would be better to fold update bundle into generate bundle; when in-binary CSV generation is removed in favor of kustomize build, the UI metadata generation component in generate bundle can stick around.

I think the make target in this PR is pretty close to what I imagined. I'm just wondering if the entrypoint can be operator-sdk bundle generate and we use a flag or another argument to run the kustomize generation vs the bundle directory creation. For example:

  • operator-sdk bundle generate manifests
  • operator-sdk bundle generate directory

kustomize build config/default | operator-sdk bundle generate manifests:

  • creates ./config/bundle/base/clusterserviceversion.yaml if not present (this is the base containing only the non-derivable metadata). This is populated by prompting the user for input.
  • creates ./config/bundle/patches/* which are the CSV patches to add the CRD sections, the roles, deployment, alm-examples, etc. These are all derived from the Go APIs and from kustomize output from other ./config kustomizations. We maybe could shell out to kustomize if nothing is present on STDIN?
  • creates ./config/bundle/kustomization.yaml (if not present) that ties together the above files and includes ./config/crd so that the CRDs end up in the kustomize output for config/bundle.

kustomize build config/bundle | operator-sdk bundle generate directory:

  • gets all of the bundle resources from STDIN (or maybe shells out to kustomize)
  • deletes and then re-creates <bundle-dir>/manifests/ with each of the bundle manifest YAMLs
  • creates <bundle-dir>/metadata/annotations.yaml if not present (anything here we need to or can update automatically?)
  • creates <bundle-dir>/Dockerfile if not present

So the make target could be:

bundle: manifests
	kustomize build config/default | operator-sdk generate bundle manifests
	kustomize build config/bundle  | operator-sdk generate bundle directory

As for CSV file suffix: do you mean that is a requirement in the SDK (generate csv) or elsewhere?

I swear I read something about OLM or the operator-registry knowing what a bundle directory is by searching for a file with a clusterserviceversion.yaml suffix. But now I can't find that. 🤷‍♂️

@estroz
Copy link
Copy Markdown
Member Author

estroz commented Apr 22, 2020

I think we're on the right track. I'd still like to initially separate the timing of metadata generation from actually creating the bundle, even if generate bundle has the ability to do both, while allowing an interactive prompt at later stages in case a kubebuilder user is migrating to operator-sdk. More importantly though I want to provide both a simple and deeper OLM/bundle workflow. I've modified an example workflow from my comment to illustrate a simplified bundle experience:

Normal kubebuilder workflow

The following few commands are no different than the normal kubebuilder workflow; their behavior differs slightly:

Interactive prompt for UI metadata on init:

$ operator-sdk init
Interactive CSV metadata prompt. Please fill in the following UI fields:
DisplayName: Memcached Operator
...
Icon file path: path/to/icon.png

Create APIs:

$ operator-sdk create api --group cache --version v1 --kind Memcached

Create or update all CRD bases after Go types are created or modified, and update the CSV base:

$ make manifests
controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle --update-bases --interactive=false

Additional bundle workflow

Here's where we add to the normal kubebuilder workflow, after we've added APIs. We can run the following SDK-specific make recipes to work with bundles. Each recipe except run-olm gives an interactive prompt if a bundle kustomize base does not exist:

Generate a bundle on disk:

$ make manifests-olm
## Calls the 'manifests' recipe
controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle --update-bases
## Generate the bundle and metadata.
kustomize build config/olm-catalog | operator-sdk generate bundle --output-dir config/olm-catalog

Create a bundle image:

$ make bundle-build IMG=quay.io/example/memcached-operator:v0.0.1
## Calls the 'manifests' recipe
controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle --update-bases
## Creates a bundle in-memory then builds an image.
kustomize build config/olm-catalog | operator-sdk generate bundle --stdout | operator-sdk bundle create $(IMG)

Run directly with OLM:

$ make run-olm
## Calls the 'manifests' recipe
controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle --update-bases --interactive=false
## Creates a bundle in-memory then installs it with OLM.
kustomize build config/olm-catalog | operator-sdk generate bundle --stdout | operator-sdk run --olm

generate bundle and bundle create exist as separate commands in my example to allow fine-grained control over each step of the process if you want it, ex. in a pipeline with pre-generated bundles/metadata. If you want things to "just work", then use any of those three make recipes. Once we move to kustomize build to generate the entire CSV from a base generate bundle --stdout/--output-dir will no longer be needed and that functionality can be removed; generate bundle --update-bases will still exist as the default behavior.

One drawback is a potentially confusing CLI if you run operator-sdk --help. I think we can mitigate confusion by adding a message like Most users will only need 'make <recipe>'. Use this command directly only if you know what you are doing.

@estroz
Copy link
Copy Markdown
Member Author

estroz commented Apr 23, 2020

/cc @dmesser @shawn-hurley

Thoughts on the above two CLI proposals?

@estroz estroz force-pushed the feature/csv-stdin branch from 7d0f684 to e9fbc11 Compare April 23, 2020 21:15
@openshift-ci-robot openshift-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 23, 2020
@estroz estroz force-pushed the feature/csv-stdin branch 2 times, most recently from dd7b458 to 6211e8d Compare April 23, 2020 21:21
@estroz estroz force-pushed the feature/csv-stdin branch from 37f619a to 819893f Compare May 27, 2020 04:02
@estroz
Copy link
Copy Markdown
Member Author

estroz commented May 27, 2020

@hasbro17 can you take another look at this? Changes:

  • Added command help text and examples.
  • init now scaffolds config/bundle/kustomization.yaml instead of generate bundle --kustomize, which makes a little more sense to me because then users won't be dependent on running the kustomize base generator before running kustomize build config/bundle | operator-sdk generate bundle
    • Neither way works without running make manifests first, but that's fine because neither does kustomize build config/default.

@estroz estroz force-pushed the feature/csv-stdin branch from 819893f to f450016 Compare May 27, 2020 04:09
@hasbro17
Copy link
Copy Markdown
Contributor

init now scaffolds config/bundle/kustomization.yaml instead of generate bundle --kustomize

@estroz Don't you mean "init" now scaffolds config/bundle/kustomization.yaml instead of "create api"?
From my understanding generate bundle --kustomize only generated config/bundle/bases/... and not config/bundle/kustomization.yaml.

Copy link
Copy Markdown
Contributor

@hasbro17 hasbro17 left a comment

Choose a reason for hiding this comment

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

LGTM to scaffolding config/bundle/kustomize on init since it's not API specific.

@camilamacedo86
Copy link
Copy Markdown
Contributor

camilamacedo86 commented May 27, 2020

Hi @estroz and @hasbro17,

The current behaviour to follow the Quick Start should not be affected

I am as a user would like to create the project and not a bundle. However, the basic steps are asking the bundle/CSV info when I run make install. It is happening because the make manifest will call the bundle. However, should not mandatory generate a bundle for all projects. Many users do not care about OLM and are not looking to integrate the project with. Is it make sense?

IMO we can simplify here by just adding the new makefile targets but we should not change the existents ones.

The operator-sdk generate bundle -q --kustomize should be called just when we call make bundle or make build-bundle.

See:

See here all steps
camilamacedo@Camilas-MacBook-Pro ~/go/src $ mkdir pr-bundle
camilamacedo@Camilas-MacBook-Pro ~/go/src $ cd pr-bundle/
camilamacedo@Camilas-MacBook-Pro ~/go/src/pr-bundle $ operator-sdk init --domain my.domain
Writing scaffold for you to edit...
Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.6.0
Update go.mod:
$ go mod tidy
Running make:
$ make
/Users/camilamacedo/go/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go build -o bin/manager main.go
Next: define a resource with:
$ operator-sdk create api
camilamacedo@Camilas-MacBook-Pro ~/go/src/pr-bundle $ operator-sdk create api --group webapp --version v1 --kind Guestbook
Create Resource [y/n]
y
Create Controller [y/n]
y
Writing scaffold for you to edit...
api/v1/guestbook_types.go
controllers/guestbook_controller.go
Running make:
$ make
/Users/camilamacedo/go/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go build -o bin/manager main.go
camilamacedo@Camilas-MacBook-Pro ~/go/src/pr-bundle $ make install
/Users/camilamacedo/go/bin/controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle -q --kustomize

Display name for the operator (required): 
> 

The make bundle is not working

it is fixed now 👍

Comment thread cmd/operator-sdk/generate/bundle/bundle.go
const (
//nolint:lll
examples = `
# Using the example 'memcached-operator' and assuming a directory structure
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is required to add the tree? What value does it bring?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It isn't strictly necessary, although other commands show trees.

operator-sdk generate bundle -q --kustomize

Display name for the operator (required):
> memcached-operator
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is required to add its output?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nope, just helps the user know what expected output should be. I can see this drifting from actual output though.

Comment thread cmd/operator-sdk/generate/bundle/bundle.go Outdated
$ operator-sdk bundle validate config/bundle
$ docker build -f bundle.Dockerfile -t quay.io/$USERNAME/memcached-operator-bundle:v0.0.1 .
Sending build context to Docker daemon 42.33MB
Step 1/9 : FROM scratch
Copy link
Copy Markdown
Contributor

@camilamacedo86 camilamacedo86 May 27, 2020

Choose a reason for hiding this comment

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

Is required to add the output?

Comment thread cmd/operator-sdk/generate/bundle/bundle.go
Comment thread internal/plugins/golang/init.go
}

// kustomization for bundles.
const bundleKustomization = `resources:
Copy link
Copy Markdown
Contributor

@camilamacedo86 camilamacedo86 May 27, 2020

Choose a reason for hiding this comment

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

Could we add a note for we try to improve its structure and have something that will follow up the KB layout?

E.g pkg/scaffold/internal/templates/bundle/makefile.go where would have the new bundle targets.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

These should live here now, then can be moved if we change anything else about the Makefile.

Comment thread cmd/operator-sdk/generate/bundle/bundle.go Outdated
@estroz
Copy link
Copy Markdown
Member Author

estroz commented May 27, 2020

@camilamacedo86 lets have UX discussions in operator-framework/enhancements#16.

@hasbro17
Copy link
Copy Markdown
Contributor

@estroz Actually I just tested what @camilamacedo86 pointed out and I'm not sure if this was always the case but after scaffolding a basic project without intending to write CSVs or bundles I'm still forced to input the metadata for the CSV bases on make manifest or make install:

$ operator-sdk init --repo=github.com/hasbro17/memcached-operator --domain=example.com
...

$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached
...

$ make manifests
/Users/haseeb/work/go-space/bin//controller-gen "crd:trivialVersions=true" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
operator-sdk generate bundle -q --kustomize

Display name for the operator (required):
...

This kind of forces CSVs and bundles into the workflow by default rather than making it opt-in like we had with generate csv or generate bundle in the old layout.

@hasbro17
Copy link
Copy Markdown
Contributor

@estroz Nvm just saw the comment for UX discussions. Ignore my previous comment.

Copy link
Copy Markdown
Contributor

@camilamacedo86 camilamacedo86 left a comment

Choose a reason for hiding this comment

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

Just to clarifies:

IMO it is the broker to move forward with this PR. Any other required change/improvements could indeed be done in a follow-up.

c/c @estroz @hasbro17 @joelanford

@estroz estroz force-pushed the feature/csv-stdin branch 2 times, most recently from 3e596f9 to 004be66 Compare June 3, 2020 16:45
@estroz estroz requested a review from camilamacedo86 June 3, 2020 16:46
project layout to use to generate bundles

cmd/operator-sdk/generate: generate a kustomization.yaml in config/bundle
so a user can 'kustomize build config/bundle' to generate generator input

internal/plugins: the Init plugin will append 'bundle' and 'bundle-build'
recipes to the Makefile to generate a bundle on-disk and build a bundle
image, respectively, using 'generate bundle'; it will also modify the
'manifests' recipe so it runs 'generate bundle --kustomize'; the
CreateAPI plugin will scaffold a kustomization.yaml in config/samples
so they are included in bundle generator input
@estroz estroz force-pushed the feature/csv-stdin branch from 004be66 to fe7daba Compare June 3, 2020 17:24
Copy link
Copy Markdown
Contributor

@camilamacedo86 camilamacedo86 left a comment

Choose a reason for hiding this comment

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

I executed the quick start steps and the steps described https://github.com/operator-framework/enhancements/pull/16/files and I could not face issues with. So, it shows OK for me.

/lgtm
/approve

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jun 3, 2020
@estroz estroz merged commit d8d9314 into operator-framework:master Jun 9, 2020
@estroz estroz deleted the feature/csv-stdin branch June 9, 2020 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kubebuilder-integration Relates to rewriting the SDK in Kubebuilder plugin form lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants