Repository: operator-framework/operator-sdk
Pull request #4736 (2021-04-08 21:53:37)

doc: CSV marker for fixing olm-crds-have-resources-test
<!--

Welcome to the Operator SDK! Before contributing, make sure to:

- Read the contributing guidelines https://github.com/operator-framework/operator-sdk/blob/master/CONTRIBUTING.MD
- Rebase your branch on the latest upstream master
- Link any relevant issues, PR's, or documentation
- When fixing an issue, add "Closes #<ISSUE_NUMBER>"
- Follow the below checklist if making a user-facing change 

-->

**Description of the change:**
Documentation update and typo fix

**Motivation for the change:**
No clear steps to resolve scorecard test issue for go operator

**Checklist**

If the pull request includes user-facing changes, extra documentation is required:
- [ ] Add a new changelog fragment in `changelog/fragments` (see [`changelog/fragments/00-template.yaml`](https://github.com/operator-framework/operator-sdk/tree/master/changelog/fragments/00-template.yaml))
- [ ] Add or update relevant sections of the docs website in [`website/content/en/docs`](https://github.com/operator-framework/operator-sdk/tree/master/website/content/en/docs)


openshift-ci-robot: New changes are detected. LGTM label has been removed.

Patch:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..85bd4820
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,26 @@
+version: 2
+updates:
+  - package-ecosystem: docker
+    directory: "/images/ansible-operator"
+    schedule:
+      interval: daily
+  - package-ecosystem: docker
+    directory: "/images/custom-scorecard-tests"
+    schedule:
+      interval: daily
+  - package-ecosystem: docker
+    directory: "/images/helm-operator"
+    schedule:
+      interval: daily
+  - package-ecosystem: docker
+    directory: "/images/operator-sdk"
+    schedule:
+      interval: daily
+  - package-ecosystem: docker
+    directory: "/images/scorecard-test"
+    schedule:
+      interval: daily
+  - package-ecosystem: docker
+    directory: "/images/scorecard-test-kuttl"
+    schedule:
+      interval: daily
diff --git a/Makefile b/Makefile
index f747d7c3..cafb7234 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ SHELL = /bin/bash
 # This value must be updated to the release tag of the most recent release, a change that must
 # occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this
 # version is moved to a separate repo and release process.
-export IMAGE_VERSION = v1.5.0
+export IMAGE_VERSION = v1.6.1
 # Build-time variables to inject into binaries
 export SIMPLE_VERSION = $(shell (test "$(shell git describe)" = "$(shell git describe --abbrev=0)" && echo $(shell git describe)) || echo $(shell git describe --abbrev=0)+git)
 export GIT_VERSION = $(shell git describe --dirty --tags --always)
diff --git a/changelog/fragments/add-componentconfig-flag.yaml b/changelog/fragments/add-componentconfig-flag.yaml
new file mode 100644
index 00000000..3bb0f39f
--- /dev/null
+++ b/changelog/fragments/add-componentconfig-flag.yaml
@@ -0,0 +1,28 @@
+entries:
+  - description: >
+      For Ansible- and Helm-based operators, add the `--config` flag, which was mistakenly
+      not added to either ansible-/helm-operator binary when file support was originally added.
+    kind: bugfix
+    migration:
+      header: Add the manager config patch to config/default/kustomization.yaml
+      body: >
+        The scaffolded `--config` flag was not added to either ansible-/helm-operator binary
+        when [config file](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html)
+        support was originally added, so does not currently work.
+        The `--config` flag supports configuration of both binaries by file;
+        this method of configuration only applies to the underlying
+        [controller manager](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Manager),
+        not the operator as a whole. To optionally configure the operator's Deployment
+        with a config file, make the following update to config/default/kustomization.yaml:
+
+        ```diff
+        # If you want your controller-manager to expose the /metrics
+        # endpoint w/o any authn/z, please comment the following line.
+        - manager_auth_proxy_patch.yaml
+        +
+        +# Mount the controller config file for loading manager configurations
+        +# through a ComponentConfig type
+        +- manager_config_patch.yaml
+        ```
+
+        This feature is opt-in: flags can be used as-is or to override config file values.
diff --git a/changelog/fragments/add-declarative.yaml b/changelog/fragments/add-declarative.yaml
deleted file mode 100644
index ceec21f0..00000000
--- a/changelog/fragments/add-declarative.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      For Golang-based operators, added the `declarative.go/v1` plugin which customizes initialized projects with patterns from [kubernetes-sigs/kubebuilder-declarative-pattern](https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern). (e.g `operator-sdk create api --plugins=go/v3,declarative`)
-    kind: "addition"
-    breaking: false
diff --git a/changelog/fragments/add-plugins.yaml b/changelog/fragments/add-plugins.yaml
deleted file mode 100644
index fc39ab0d..00000000
--- a/changelog/fragments/add-plugins.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      Added `kustomize.common/v1` plugin which scaffolds the a commonly used project base that leverages `kustomize`.
-    kind: "addition"
-    breaking: false
diff --git a/changelog/fragments/add_common_kb.yaml b/changelog/fragments/add_common_kb.yaml
deleted file mode 100644
index 30b40888..00000000
--- a/changelog/fragments/add_common_kb.yaml
+++ /dev/null
@@ -1,60 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      (ansible/v1,helm/v1) Add componentConfig option. For further information check [here](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html)
-    kind: "addition"
-    breaking: false
-    migration:
-      header: (ansible/v1,helm/v1) Add componentConfig option.
-      body: >
-        To add this option your project you will need to:
-        - Create the file [/config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/v1.6.0/testdata/ansible/memcached-operator/config/default/manager_config_patch.yaml).
-        - Create the file [/config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/v1.6.0/testdata/ansible/memcached-operator/config/manager/controller_manager_config.yaml) .
-        - Update the `config/default/kustomization.yaml` by adding:
-          ```yaml
-          # Mount the controller config file for loading manager configurations
-          # through a ComponentConfig type
-          #- manager_config_patch.yaml
-          ```
-        - Update the `config/manager/kustomization.yaml` by adding:
-          ```yaml
-          generatorOptions:
-            disableNameSuffixHash: true
-
-          configMapGenerator:
-          - files:
-            - controller_manager_config.yaml
-            name: manager-config
-          apiVersion: kustomize.config.k8s.io/v1beta1
-          kind: Kustomization
-          images:
-          - name: controller
-            newName: quay.io/example/memcached-operator
-            newTag: v0.0.1
-          ```
-  - description: >
-      (golang/v3) Not scaffold the specific webhooks config manifests by default 
-    kind: "bugfix"
-
-    # Is this a breaking change?
-    breaking: false
-  - description: >
-      (ansible/v1,helm/v1) Add rules for leader election
-    kind: "addition"
-
-    # Is this a breaking change?
-    breaking: false
-    migration:
-      header: (ansible/v1,helm/v1) Add rules for leader election.
-      body: >
-        Add the rule for the `apiGroups` `coordination.k8s.io` and the resource `leases` in config/rbac/leader_election_role.yaml:
-        ```yaml
-        rules:
-          - apiGroups:
-              - ""
-              - coordination.k8s.io
-            resources:
-              - configmaps
-              - leases
-        ```
diff --git a/changelog/fragments/alpha-config-gen.yaml b/changelog/fragments/alpha-config-gen.yaml
deleted file mode 100644
index 78676f21..00000000
--- a/changelog/fragments/alpha-config-gen.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-entries:
-  - description: >
-      Added [`alpha config-gen`](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/config-gen),
-      a kustomize plugin to specialize configuration for kubebuilder-style projects. This feature is *alpha*
-      and subject to breaking changes.
-    kind: addition
diff --git a/changelog/fragments/ansible-2.10.7.yaml b/changelog/fragments/ansible-2.10.7.yaml
deleted file mode 100644
index ed142a4d..00000000
--- a/changelog/fragments/ansible-2.10.7.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Bumped ansible and ansible-base in ansible-operator-base and ansible-operator images
-      to 2.10.7 for a security fix.
-    kind: change
diff --git a/changelog/fragments/ansible-dep-bump.yaml b/changelog/fragments/ansible-dep-bump.yaml
deleted file mode 100644
index 5f5c8348..00000000
--- a/changelog/fragments/ansible-dep-bump.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-entries:
-  - description: |
-      For Ansible-based Operators: Update Python dependencies.
-        - openshift (0.11.2 -> 0.12.0)
-        - kubernetes (11.0.0 -> 12.0.1)
-        - ansible-runner (1.4.6 -> 1.4.7)
-        - ansible (2.9.15 -> 2.9.19)
-    kind: "change"
-    breaking: false
-
-  - description: |
-      (ansible/v1) Update scaffolded requirements.yml to pull in newer versions of the Ansible collections.
-        - community.kubernetes (1.1.1 -> 1.2.1)
-        - operator_sdk.util (0.1.0 -> 0.2.0)
-    kind: "change"
-    breaking: false
-    migration:
-      header: (ansible/v1) Update Ansible collections
-      body: >
-        In your requirements.yml, change the `version` field for community.kubernetes to `1.2.1`,
-        and the `version` field for `operator_sdk.util` to `0.2.0`.
diff --git a/changelog/fragments/ansible-helm-flags.yaml b/changelog/fragments/ansible-helm-flags.yaml
deleted file mode 100644
index d2defe30..00000000
--- a/changelog/fragments/ansible-helm-flags.yaml
+++ /dev/null
@@ -1,109 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      (ansible/v1, helm/v1) The flags `--enable-leader-election` and `--metrics-addr` were deprecated in favor of `--leader-elect` and `--metrics-bind-address`, respectively, to follow upstream conventions.
-
-    # kind is one of:
-    # - addition
-    # - change
-    # - deprecation
-    # - removal
-    # - bugfix
-    kind: "deprecation"
-
-    # Is this a breaking change?
-    breaking: false
-
-    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-    #
-    # The generator auto-detects the PR number from the commit
-    # message in which this file was originally added.
-    #
-    # What is the pull request number (without the "#")?
-    # pull_request_override: 0
-
-
-    # Migration can be defined to automatically add a section to
-    # the migration guide. This is required for breaking changes.
-    migration:
-      header: (helm/v1) Replace deprecated leader election and metrics address flags
-      body: >
-        Replace deprecated flags `--enable-leader-election` and `--metrics-addr` with `--leader-elect` and `--metrics-bind-address`, respectively.
-  - description: >
-      (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
-
-    # kind is one of:
-    # - addition
-    # - change
-    # - deprecation
-    # - removal
-    # - bugfix
-    kind: "change"
-
-    # Is this a breaking change?
-    breaking: false
-
-    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-    #
-    # The generator auto-detects the PR number from the commit
-    # message in which this file was originally added.
-    #
-    # What is the pull request number (without the "#")?
-    # pull_request_override: 0
-
-
-    # Migration can be defined to automatically add a section to
-    # the migration guide. This is required for breaking changes.
-    migration:
-      header: (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
-      body: >
-        Add the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:
-        ```yaml
-        - "--health-probe-bind-address=:8081"
-        - "--metrics-bind-address=127.0.0.1:8080"
-        - "--leader-elect"
-        ```
-  - description: >
-      (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
-
-    # kind is one of:
-    # - addition
-    # - change
-    # - deprecation
-    # - removal
-    # - bugfix
-    kind: "change"
-
-    # Is this a breaking change?
-    breaking: false
-
-    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-    #
-    # The generator auto-detects the PR number from the commit
-    # message in which this file was originally added.
-    #
-    # What is the pull request number (without the "#")?
-    # pull_request_override: 0
-
-
-    # Migration can be defined to automatically add a section to
-    # the migration guide. This is required for breaking changes.
-    migration:
-      header: (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
-      body: >
-        Add the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:
-        ```yaml
-        - "--health-probe-bind-address=:6789"
-        - "--metrics-bind-address=127.0.0.1:6789"
-        - "--leader-elect"
-        ```
-
-
-
-
-
-
diff --git a/changelog/fragments/ansible-helm-makefile-help.yaml b/changelog/fragments/ansible-helm-makefile-help.yaml
deleted file mode 100644
index fed0ba39..00000000
--- a/changelog/fragments/ansible-helm-makefile-help.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      (helm/v1, ansible/v1) Added Makefile `help` target
-
-    # kind is one of:
-    # - addition
-    # - change
-    # - deprecation
-    # - removal
-    # - bugfix
-    kind: "addition"
-
-    # Is this a breaking change?
-    breaking: false
-
-    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-    #
-    # The generator auto-detects the PR number from the commit
-    # message in which this file was originally added.
-    #
-    # What is the pull request number (without the "#")?
-    # pull_request_override: 0
-
-
-    # Migration can be defined to automatically add a section to
-    # the migration guide. This is required for breaking changes.
-    migration:
-      header: (helm/v1, ansible/v1) Add `help` target to Makefile.
-      body: >
-        Ansible/Helm projects now provide a Makefile `help` target, similar to a `--help` flag.
-        You can copy and paste this target from the relevant sample's Makefile
-        ([helm]((https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/helm/memcached-operator/Makefile), [ansible]((https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/ansible/memcached-operator/Makefile)).
diff --git a/changelog/fragments/ansible-helm-ssc.yaml b/changelog/fragments/ansible-helm-ssc.yaml
deleted file mode 100644
index 28e1035d..00000000
--- a/changelog/fragments/ansible-helm-ssc.yaml
+++ /dev/null
@@ -1,46 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      ansible/v1, helm/v1) Added `securityContext`'s to the manager's Deployment to disallow running as root user.
-
-    # kind is one of:
-    # - addition
-    # - change
-    # - deprecation
-    # - removal
-    # - bugfix
-    kind: "addition"
-
-    # Is this a breaking change?
-    breaking: false
-
-    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-    #
-    # The generator auto-detects the PR number from the commit
-    # message in which this file was originally added.
-    #
-    # What is the pull request number (without the "#")?
-    # pull_request_override: 0
-
-
-    # Migration can be defined to automatically add a section to
-    # the migration guide. This is required for breaking changes.
-    migration:
-      header: (ansible/v1, helm/v1) Add `securityContext`'s to your manager's Deployment.
-      body: >
-        In `config/manager/manager.yaml`, add the following security contexts:
-        ```yaml
-        spec:
-          ...
-          template:
-            ...
-            spec:
-              securityContext:
-                runAsNonRoot: true
-              containers:
-              - name: manager
-                securityContext:
-                  allowPrivilegeEscalation: false
-        ```
diff --git a/changelog/fragments/bugfix-csv-webhooks.yaml b/changelog/fragments/bugfix-csv-webhooks.yaml
deleted file mode 100644
index 6d519f56..00000000
--- a/changelog/fragments/bugfix-csv-webhooks.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-entries:
-  - description: >
-      (manifests/v2) Added a `config/manifests` kustomize patch to remove the cert-manager
-      volume and volumeMount from manifests destined for `generate <bundle|packagemanifests>`
-    kind: bugfix
-    migration:
-      header: (manifests/v2) Add a kustomize patch to remove the cert-manager volume/volumeMount from your CSV
-      body: >
-        OLM does [not yet support cert-manager](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements),
-        so a JSON patch was added to remove this volume and mount such that
-        OLM can itself create and manage certs for your Operator.
-
-        In `config/manifests/kustomization.yaml`, add the following:
-
-        ```yaml
-        patchesJson6902:
-        - target:
-            group: apps
-            version: v1
-            kind: Deployment
-            name: controller-manager
-            namespace: system
-          patch: |-
-            # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs.
-            # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.
-            - op: remove
-              path: /spec/template/spec/containers/1/volumeMounts/0
-            # Remove the "cert" volume, since OLM will create and mount a set of certs.
-            # Update the indices in this path if adding or removing volumes in the manager's Deployment.
-            - op: remove
-              path: /spec/template/spec/volumes/0
-        ```
diff --git a/changelog/fragments/ca-secret-name-run-bundle.yaml b/changelog/fragments/ca-secret-name-run-bundle.yaml
deleted file mode 100644
index 222abf84..00000000
--- a/changelog/fragments/ca-secret-name-run-bundle.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure
-      the registry Pod with an in-cluster certificate Secret to use TLS with a private registry.
-    kind: addition
diff --git a/changelog/fragments/change-scImagePolicy.yaml b/changelog/fragments/change-scImagePolicy.yaml
new file mode 100644
index 00000000..57bab779
--- /dev/null
+++ b/changelog/fragments/change-scImagePolicy.yaml
@@ -0,0 +1,5 @@
+entries:
+  - description: >
+      "Changed default image Pull Policy to Always for scorecard"
+    kind: change
+    breaking: false
diff --git a/changelog/fragments/helm-handle-list-kind.yaml b/changelog/fragments/helm-handle-list-kind.yaml
deleted file mode 100644
index 6192990f..00000000
--- a/changelog/fragments/helm-handle-list-kind.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      For Helm-based operators, fixes handling of `kind: List` whereby the 
-      operator fails when trying to set watch on the object. The fix now sets
-      the watch on the objects of the list instead. 
-
-    kind: "bugfix"
-
-    breaking: false
diff --git a/changelog/fragments/helm-uninstall-wait-anno.yml b/changelog/fragments/helm-uninstall-wait-anno.yml
deleted file mode 100644
index 19e9b835..00000000
--- a/changelog/fragments/helm-uninstall-wait-anno.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-entries:
-  - description: >
-      For Helm based-operators, added annotation `helm.sdk.operatorframework.io/uninstall-wait: "true"`
-      to allow all resources to be deleted before removing the custom resource's finalizer.
-    kind: "addition"
-    breaking: false
diff --git a/changelog/fragments/kubebuilder-646f742.yaml b/changelog/fragments/kubebuilder-646f742.yaml
deleted file mode 100644
index adfe352b..00000000
--- a/changelog/fragments/kubebuilder-646f742.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-entries:
-  - description: >
-      (go/v2, go/v3, ansible/v1, helm/v1) Fixed the Prometheus `ServiceMonitor` metrics endpoint,
-      which was not configured to be scraped correctly.
-    kind: bugfix
-    migration:
-      header: (go/v2, go/v3, ansible/v1, helm/v1) Add scheme, token, and TLS config to the Prometheus `ServiceMonitor` metrics endpoint.
-      body: >
-        The `/metrics` endpoint, while specifying the `https` port on the manager Pod, was not actually configured
-        to serve over https because no tlsConfig was set. Since kube-rbac-proxy secures this endpoint as a
-        manager sidecar, using the service account token mounted into the Pod by default corrects this problem.
-
-        The changes should look like:
-
-        ```diff
-        # config/prometheus/monitor.yaml
-
-        spec:
-           endpoints:
-             - path: /metrics
-               port: https
-        +      scheme: https
-        +      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
-        +      tlsConfig:
-        +        insecureSkipVerify: true
-           selector:
-             matchLabels:
-               control-plane: controller-manager
-        ```
-
-        **Note:** if you have removed kube-rbac-proxy from your project, make sure to secure the `/metrics`
-        endpoint using a proper [TLS configuration](https://prometheus.io/docs/guides/tls-encryption/).
diff --git a/changelog/fragments/make-catalog-build.yaml b/changelog/fragments/make-catalog-build.yaml
deleted file mode 100644
index 02787af1..00000000
--- a/changelog/fragments/make-catalog-build.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-entries:
-  - description: >
-      (go/v2, go/v3, ansible/v1, helm/v1) Added the `opm` and `catalog-build` Makefile targets to
-      download [`opm`](https://github.com/operator-framework/operator-registry/blob/v1.15.1/docs/design/opm-tooling.md)
-      and build operator catalogs either from scratch or an existing catalog.
-    kind: addition
-    migration:
-      header: (go/v2, go/v3, ansible/v1, helm/v1) Add `opm` and `catalog-build` Makefile targets
-      body: >
-        The `opm` and `catalog-build` Makefile targets were added so operator developers who
-        want to create their own catalogs for their operator or add their operator's bundle(s) to an
-        existing catalog can do so. If this sounds like you, add the following lines to the bottom
-        of your Makefile:
-
-        ```make
-        .PHONY: opm
-        OPM = ./bin/opm
-        opm:
-        ifeq (,$(wildcard $(OPM)))
-        ifeq (,$(shell which opm 2>/dev/null))
-        	@{ \
-        	set -e ;\
-        	mkdir -p $(dir $(OPM)) ;\
-        	curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCH)-opm ;\
-        	chmod +x $(OPM) ;\
-        	}
-        else
-        OPM = $(shell which opm)
-        endif
-        endif
-
-        BUNDLE_IMGS ?= $(BUNDLE_IMG)
-        CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)
-        ifneq ($(origin CATALOG_BASE_IMG), undefined)
-        FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)
-        endif
-        .PHONY: catalog-build
-        catalog-build: opm
-        	$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
-
-        # Push the catalog image.
-        .PHONY: catalog-push
-        catalog-push:
-        	$(MAKE) docker-push IMG=$(CATALOG_IMG)
-        ```
-
-        If updating a Go operator project, additionally add the following Makefile variables:
-
-        ```make
-        OS = $(shell go env GOOS)
-        ARCH = $(shell go env GOARCH)
-        ```
-  - description: >
-      (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables
-      to allow one line bundle and catalog image builds.
-    kind: change
-    migration:
-      header: (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables
-      body: >
-        The following Makefile changes were made to allow `make bundle-build bundle-push catalog-build catalog-push`
-        and encode image repo/namespace information in the Makefile by default:
-
-        ```diff
-        +IMAGE_TAG_BASE ?= <registry>/<operator name>
-        +
-        -BUNDLE_IMG ?= controller-bundle:$(VERSION)
-        +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
-        ```
-
-        For example, if `IMAGE_TAG_BASE ?= foo/bar-operator` then running `make bundle-build bundle-push catalog-build catalog-push`
-        would build `foo/bar-operator-bundle:v0.0.1` and `foo/bar-operator-catalog:v0.0.1` then push them to the
-        `docker.io/foo` namespaced registry.
diff --git a/changelog/fragments/mark-variables-unsafe.yaml b/changelog/fragments/mark-variables-unsafe.yaml
deleted file mode 100644
index 933b6266..00000000
--- a/changelog/fragments/mark-variables-unsafe.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Mark the input variables from custom resources as unsafe by default in Ansible operators. 
-    kind: bugfix
-    breaking: false
diff --git a/changelog/fragments/optional-flags-cleanup.yaml b/changelog/fragments/optional-flags-cleanup.yaml
deleted file mode 100644
index 67f03584..00000000
--- a/changelog/fragments/optional-flags-cleanup.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Added new optional flags `--delete-all`, `--delete-crds` and `--delete-operator-groups` to the cleanup command
-    kind: "addition"
-    breaking: false
diff --git a/changelog/fragments/pin-ansible-galaxy-collections.yaml b/changelog/fragments/pin-ansible-galaxy-collections.yaml
deleted file mode 100644
index 3f4cadf7..00000000
--- a/changelog/fragments/pin-ansible-galaxy-collections.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-  - description: >
-      For Ansible-based operators, collections as main dependencies for the operator installed with ansible-galaxy are
-      pinned to specific versions to prevent hard to track bugs.
-
-    kind: change
-
-    # Is this a breaking change?
-    breaking: false
diff --git a/changelog/fragments/run-bundle-with-secret.yaml b/changelog/fragments/run-bundle-with-secret.yaml
deleted file mode 100644
index 9ecb4f26..00000000
--- a/changelog/fragments/run-bundle-with-secret.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-entries:
-  - description: >
-      Added `--service-account` to `run bundle` and `run bundle-upgrade` to bind
-      registry objects to a non-default service account.
-    kind: addition
-  - description: >
-      Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure
-      the registry Pod with an in-cluster docker config Secret
-      to pull bundle images from private registries.
-    kind: addition
diff --git a/changelog/fragments/service_account.yaml b/changelog/fragments/service_account.yaml
deleted file mode 100644
index a593b6b8..00000000
--- a/changelog/fragments/service_account.yaml
+++ /dev/null
@@ -1,86 +0,0 @@
-# entries is a list of entries to include in
-# release notes and/or the migration guide
-entries:
-    - description: >
-          (ansible/v1, helm/v1) Create and bind to a non-default service account ([kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070))
-      kind: "addition"
-      breaking: false
-
-        # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS
-        # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!
-        #
-        # The generator auto-detects the PR number from the commit
-        # message in which this file was originally added.
-        #
-        # What is the pull request number (without the "#")?
-        # pull_request_override: 0
-
-
-        # Migration can be defined to automatically add a section to
-        # the migration guide. This is required for breaking changes.
-      migration:
-          header: (ansible/v1, helm/v1) Add a `system:controller-manager` ServiceAccount to your project.
-          body: >
-              A non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`,
-              to improve security for operators installed in shared namespaces. To add this ServiceAccount
-              to your project, do the following:
-              ```sh
-              # Create the ServiceAccount.
-              cat <<EOF > config/rbac/service_account.yaml
-              apiVersion: v1
-              kind: ServiceAccount
-              metadata:
-                name: controller-manager
-                namespace: system
-              EOF
-              # Add it to the list of RBAC resources.
-              echo "- service_account.yaml" >> config/rbac/kustomization.yaml
-              # Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.
-              find config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \;
-              # Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName.
-              sed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\1serviceAccountName: controller-manager\n\1\2/g' config/manager/manager.yaml
-              ```
-              The changes should look like:
-              ```diff
-              # config/manager/manager.yaml
-                         requests:
-                           cpu: 100m
-                           memory: 20Mi
-              +      serviceAccountName: controller-manager
-                     terminationGracePeriodSeconds: 10
-              # config/rbac/auth_proxy_role_binding.yaml
-                 name: proxy-role
-               subjects:
-               - kind: ServiceAccount
-              -  name: default
-              +  name: controller-manager
-                 namespace: system
-              # config/rbac/kustomization.yaml
-               resources:
-              +- service_account.yaml
-               - role.yaml
-               - role_binding.yaml
-               - leader_election_role.yaml
-              # config/rbac/leader_election_role_binding.yaml
-                 name: leader-election-role
-               subjects:
-               - kind: ServiceAccount
-              -  name: default
-              +  name: controller-manager
-                 namespace: system
-              # config/rbac/role_binding.yaml
-                 name: manager-role
-               subjects:
-               - kind: ServiceAccount
-              -  name: default
-              +  name: controller-manager
-                 namespace: system
-              # config/rbac/service_account.yaml
-              +apiVersion: v1
-              +kind: ServiceAccount
-              +metadata:
-              +  name: controller-manager
-              +  namespace: system
-              ```
-
-
diff --git a/changelog/fragments/update-ansible-collections.yaml b/changelog/fragments/update-ansible-collections.yaml
deleted file mode 100644
index 18f59e50..00000000
--- a/changelog/fragments/update-ansible-collections.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Update community Kubernetes Ansible collection to version 1.1.1
-    kind: "change"
-    breaking: false
diff --git a/changelog/fragments/urllib3-1.26.4.yaml b/changelog/fragments/urllib3-1.26.4.yaml
deleted file mode 100644
index 7bfdf21c..00000000
--- a/changelog/fragments/urllib3-1.26.4.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-entries:
-  - description: >
-      Bumped urllib3 in ansible-operator-base and ansible-operator images to 1.26.4
-      for a security fix.
-    kind: change
diff --git a/changelog/fragments/use-pipenv-for-python-package-installation.yaml b/changelog/fragments/use-pipenv-for-python-package-installation.yaml
deleted file mode 100644
index 8d33c195..00000000
--- a/changelog/fragments/use-pipenv-for-python-package-installation.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-entries:
-  - description: >
-      For Ansible-based operators, Python package installation in the Docker
-      image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning
-      both the main installed packages and their subdependencies. This prevents
-      installing conflicting (sub)dependencies
-
-    kind: change
-
-    breaking: false
-
-  - description: >
-      For Ansible-based operators, the Python following packages were updated:
-      `openshift` was updated to 0.11.2, `ansible-runner` was updated to 1.4.6.
-
-    kind: change
-
-    breaking: false
diff --git a/changelog/generated/v1.6.0.md b/changelog/generated/v1.6.0.md
new file mode 100644
index 00000000..3d416a28
--- /dev/null
+++ b/changelog/generated/v1.6.0.md
@@ -0,0 +1,49 @@
+## v1.6.0
+
+### Additions
+
+- For Golang-based operators, added the `declarative.go/v1` plugin which customizes initialized projects with patterns from [kubernetes-sigs/kubebuilder-declarative-pattern](https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern). (e.g `operator-sdk create api --plugins=go/v3,declarative`). ([#4731](https://github.com/operator-framework/operator-sdk/pull/4731))
+- Added `kustomize.common/v1` plugin which scaffolds the a commonly used project base that leverages `kustomize`. ([#4730](https://github.com/operator-framework/operator-sdk/pull/4730))
+- (ansible/v1, helm/v1) Added the option to configure `ansible-operator` and `helm-operator` with a [component config](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html). ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- (ansible/v1, helm/v1) Add rules for leader election. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- Added [`alpha config-gen`](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/config-gen), a kustomize plugin to specialize configuration for kubebuilder-style projects. This feature is *alpha* and subject to breaking changes. ([#4670](https://github.com/operator-framework/operator-sdk/pull/4670))
+- (helm/v1, ansible/v1) Added Makefile `help` target. ([#4660](https://github.com/operator-framework/operator-sdk/pull/4660))
+- (ansible/v1, helm/v1) Added `securityContext`'s to the manager's Deployment to disallow running as root user. ([#4655](https://github.com/operator-framework/operator-sdk/pull/4655))
+- Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster certificate Secret to use TLS with a private registry. ([#4703](https://github.com/operator-framework/operator-sdk/pull/4703))
+- For Helm based-operators, added annotation `helm.sdk.operatorframework.io/uninstall-wait: "true"` to allow all resources to be deleted before removing the custom resource's finalizer. ([#4487](https://github.com/operator-framework/operator-sdk/pull/4487))
+- (go/v2, go/v3, ansible/v1, helm/v1) Added the `opm` and `catalog-build` Makefile targets to download [`opm`](https://github.com/operator-framework/operator-registry/blob/v1.15.1/docs/design/opm-tooling.md) and build operator catalogs either from scratch or an existing catalog. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))
+- Added new optional flags `--delete-all`, `--delete-crds` and `--delete-operator-groups` to the cleanup command. ([#4619](https://github.com/operator-framework/operator-sdk/pull/4619))
+- Added `--service-account` to `run bundle` and `run bundle-upgrade` to bind registry objects to a non-default service account. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))
+- Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster docker config Secret to pull bundle images from private registries. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))
+- (ansible/v1, helm/v1) Create and bind controller-manager to a non-default service account ([kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070)). ([#4653](https://github.com/operator-framework/operator-sdk/pull/4653))
+
+### Changes
+
+- For Ansible-based Operators: Update Python dependencies.
+  - openshift (0.11.2 -> 0.12.0)
+  - kubernetes (11.0.0 -> 12.0.1)
+  - ansible-runner (1.4.6 -> 1.4.7)
+  - ansible (2.9.15 -> 2.9.19). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))
+- (ansible/v1) Update scaffolded requirements.yml to pull in newer versions of the Ansible collections.
+  - community.kubernetes (1.1.1 -> 1.2.1)
+  - operator_sdk.util (0.1.0 -> 0.2.0). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))
+- (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+- (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+- (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables to allow one line bundle and catalog image builds. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))
+- For Ansible-based operators, collections as main dependencies for the operator installed with ansible-galaxy are pinned to specific versions to prevent hard to track bugs. ([#4529](https://github.com/operator-framework/operator-sdk/pull/4529))
+- Update community Kubernetes Ansible collection to version 1.1.1. ([#4594](https://github.com/operator-framework/operator-sdk/pull/4594))
+- Bumped urllib3 in ansible-operator-base and ansible-operator images to 1.26.4 for a security fix. ([#4723](https://github.com/operator-framework/operator-sdk/pull/4723))
+- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))
+- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))
+
+### Deprecations
+
+- (ansible/v1, helm/v1) The flags `--enable-leader-election` and `--metrics-addr` were deprecated in favor of `--leader-elect` and `--metrics-bind-address`, respectively, to follow upstream conventions. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+
+### Bug Fixes
+
+- (go/v3) Create webhook manifests in `config/` on running `create webhook`, not `init`. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- (manifests/v2) Added a `config/manifests` kustomize patch to remove the cert-manager volume and volumeMount from manifests destined for `generate <bundle|packagemanifests>`. ([#4623](https://github.com/operator-framework/operator-sdk/pull/4623))
+- For Helm-based operators, fixed handling of `kind: List` whereby the operator fails when trying to set watch on the object. Watches are created for objects in the list instead. ([#4682](https://github.com/operator-framework/operator-sdk/pull/4682))
+- (go/v2, go/v3, ansible/v1, helm/v1) Fixed the Prometheus `ServiceMonitor` metrics endpoint, which was not configured to be scraped correctly. ([#4680](https://github.com/operator-framework/operator-sdk/pull/4680))
+- In Ansible-based operators, mark the input variables from custom resources as unsafe by default. ([#4566](https://github.com/operator-framework/operator-sdk/pull/4566))
diff --git a/changelog/generated/v1.6.1.md b/changelog/generated/v1.6.1.md
new file mode 100644
index 00000000..68cd7adc
--- /dev/null
+++ b/changelog/generated/v1.6.1.md
@@ -0,0 +1,49 @@
+## v1.6.1
+
+### Additions
+
+- For Golang-based operators, added the `declarative.go/v1` plugin which customizes initialized projects with patterns from [kubernetes-sigs/kubebuilder-declarative-pattern](https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern). (e.g `operator-sdk create api --plugins=go/v3,declarative`). ([#4731](https://github.com/operator-framework/operator-sdk/pull/4731))
+- Added `kustomize.common/v1` plugin which scaffolds the a commonly used project base that leverages `kustomize`. ([#4730](https://github.com/operator-framework/operator-sdk/pull/4730))
+- (ansible/v1, helm/v1) Added the option to configure `ansible-operator` and `helm-operator` with a [component config](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html). ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- (ansible/v1, helm/v1) Add rules for leader election. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- Added [`alpha config-gen`](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/config-gen), a kustomize plugin to specialize configuration for kubebuilder-style projects. This feature is *alpha* and subject to breaking changes. ([#4670](https://github.com/operator-framework/operator-sdk/pull/4670))
+- (helm/v1, ansible/v1) Added Makefile `help` target. ([#4660](https://github.com/operator-framework/operator-sdk/pull/4660))
+- (ansible/v1, helm/v1) Added `securityContext`'s to the manager's Deployment to disallow running as root user. ([#4655](https://github.com/operator-framework/operator-sdk/pull/4655))
+- Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster certificate Secret to use TLS with a private registry. ([#4703](https://github.com/operator-framework/operator-sdk/pull/4703))
+- For Helm based-operators, added annotation `helm.sdk.operatorframework.io/uninstall-wait: "true"` to allow all resources to be deleted before removing the custom resource's finalizer. ([#4487](https://github.com/operator-framework/operator-sdk/pull/4487))
+- (go/v2, go/v3, ansible/v1, helm/v1) Added the `opm` and `catalog-build` Makefile targets to download [`opm`](https://github.com/operator-framework/operator-registry/blob/v1.15.1/docs/design/opm-tooling.md) and build operator catalogs either from scratch or an existing catalog. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))
+- Added new optional flags `--delete-all`, `--delete-crds` and `--delete-operator-groups` to the cleanup command. ([#4619](https://github.com/operator-framework/operator-sdk/pull/4619))
+- Added `--service-account` to `run bundle` and `run bundle-upgrade` to bind registry objects to a non-default service account. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))
+- Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster docker config Secret to pull bundle images from private registries. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))
+- (ansible/v1, helm/v1) Create and bind controller-manager to a non-default service account ([kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070)). ([#4653](https://github.com/operator-framework/operator-sdk/pull/4653))
+
+### Changes
+
+- For Ansible-based Operators: Update Python dependencies.
+  - openshift (0.11.2 -> 0.12.0)
+  - kubernetes (11.0.0 -> 12.0.1)
+  - ansible-runner (1.4.6 -> 1.4.7)
+  - ansible (2.9.15 -> 2.9.19). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))
+- (ansible/v1) Update scaffolded requirements.yml to pull in newer versions of the Ansible collections.
+  - community.kubernetes (1.1.1 -> 1.2.1)
+  - operator_sdk.util (0.1.0 -> 0.2.0). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))
+- (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+- (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+- (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables to allow one line bundle and catalog image builds. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))
+- For Ansible-based operators, collections as main dependencies for the operator installed with ansible-galaxy are pinned to specific versions to prevent hard to track bugs. ([#4529](https://github.com/operator-framework/operator-sdk/pull/4529))
+- Update community Kubernetes Ansible collection to version 1.1.1. ([#4594](https://github.com/operator-framework/operator-sdk/pull/4594))
+- Bumped urllib3 in ansible-operator-base and ansible-operator images to 1.26.4 for a security fix. ([#4723](https://github.com/operator-framework/operator-sdk/pull/4723))
+- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))
+- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))
+
+### Deprecations
+
+- (ansible/v1, helm/v1) The flags `--enable-leader-election` and `--metrics-addr` were deprecated in favor of `--leader-elect` and `--metrics-bind-address`, respectively, to follow upstream conventions. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))
+
+### Bug Fixes
+
+- (go/v3) Create webhook manifests in `config/` on running `create webhook`, not `init`. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))
+- (manifests/v2) Added a `config/manifests` kustomize patch to remove the cert-manager volume and volumeMount from manifests destined for `generate <bundle|packagemanifests>`. ([#4623](https://github.com/operator-framework/operator-sdk/pull/4623))
+- For Helm-based operators, fixed handling of `kind: List` whereby the operator fails when trying to set watch on the object. Watches are created for objects in the list instead. ([#4682](https://github.com/operator-framework/operator-sdk/pull/4682))
+- (go/v2, go/v3, ansible/v1, helm/v1) Fixed the Prometheus `ServiceMonitor` metrics endpoint, which was not configured to be scraped correctly. ([#4680](https://github.com/operator-framework/operator-sdk/pull/4680))
+- In Ansible-based operators, mark the input variables from custom resources as unsafe by default. ([#4566](https://github.com/operator-framework/operator-sdk/pull/4566))
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 6c0338fb..126b89aa 100644
--- a/go.mod
+++ b/go.mod
@@ -34,9 +34,9 @@ require (
 	k8s.io/client-go v0.20.2
 	k8s.io/kubectl v0.20.2
 	rsc.io/letsencrypt v0.0.3 // indirect
-	sigs.k8s.io/controller-runtime v0.8.2
+	sigs.k8s.io/controller-runtime v0.8.3
 	sigs.k8s.io/controller-tools v0.5.0
-	sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210411191801-c7525d748153
+	sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210415223022-9f90d1a3c3cc
 	sigs.k8s.io/yaml v1.2.0
 )
 
diff --git a/go.sum b/go.sum
index aa1f88dd..633ff930 100644
--- a/go.sum
+++ b/go.sum
@@ -1550,15 +1550,15 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyz
 sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=
 sigs.k8s.io/controller-runtime v0.8.0 h1:s0dYdo7lQgJiAf+alP82PRwbz+oAqL3oSyMQ18XRDOc=
 sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4=
-sigs.k8s.io/controller-runtime v0.8.2 h1:SBWmI0b3uzMIUD/BIXWNegrCeZmPJ503pOtwxY0LPHM=
-sigs.k8s.io/controller-runtime v0.8.2/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
+sigs.k8s.io/controller-runtime v0.8.3 h1:GMHvzjTmaWHQB8HadW+dIvBoJuLvZObYJ5YoZruPRao=
+sigs.k8s.io/controller-runtime v0.8.3/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
 sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
 sigs.k8s.io/controller-tools v0.4.1 h1:VkuV0MxlRPmRu5iTgBZU4UxUX2LiR99n3sdQGRxZF4w=
 sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU=
 sigs.k8s.io/controller-tools v0.5.0 h1:3u2RCwOlp0cjCALAigpOcbAf50pE+kHSdueUosrC/AE=
 sigs.k8s.io/controller-tools v0.5.0/go.mod h1:JTsstrMpxs+9BUj6eGuAaEb6SDSPTeVtUyp0jmnAM/I=
-sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210411191801-c7525d748153 h1:zNScO/WTy8ZTg3lxnjm1y/oHcZgKJx0IY4axJCHKSE0=
-sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210411191801-c7525d748153/go.mod h1:eVtLdWzmvL1ixDYLlVrvQe8wjpikJVoSOg5PghTk2Lw=
+sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210415223022-9f90d1a3c3cc h1:laR4sYUQabBCltK1WnyvA5Bde+f/0aiPogArXWfnBBs=
+sigs.k8s.io/kubebuilder/v3 v3.0.0-alpha.0.0.20210415223022-9f90d1a3c3cc/go.mod h1:KJLAKkOvgXZ2+1REJqFmoseez1tgg5Qoz0zFeJorrSo=
 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/kustomize/kyaml v0.10.10 h1:caAxDDkaXZp+0kDsZVik4leFJV8LCy09PdVqpaoNeF4=
diff --git a/hack/generate/samples/internal/ansible/advanced_molecule.go b/hack/generate/samples/internal/ansible/advanced_molecule.go
index 951ef1ae..43165f77 100644
--- a/hack/generate/samples/internal/ansible/advanced_molecule.go
+++ b/hack/generate/samples/internal/ansible/advanced_molecule.go
@@ -24,7 +24,6 @@ import (
 	kbtestutils "sigs.k8s.io/kubebuilder/v3/test/e2e/utils"
 
 	"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg"
-	"github.com/operator-framework/operator-sdk/internal/testutils"
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
@@ -33,9 +32,18 @@ type AdvancedMolecule struct {
 	ctx *pkg.SampleContext
 }
 
-// NewMoleculeAnsible return a MoleculeAnsible
-func NewAdvancedMolecule(ctx *pkg.SampleContext) AdvancedMolecule {
-	return AdvancedMolecule{ctx}
+// GenerateAdvancedMoleculeSample will call all actions to create the directory and generate the sample
+// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
+// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
+// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
+func GenerateAdvancedMoleculeSample(binaryPath, samplesPath string) {
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "advanced-molecule-operator"),
+		"GO111MODULE=on")
+	pkg.CheckError("generating Ansible Molecule Advanced Operator context", err)
+
+	molecule := AdvancedMolecule{&ctx}
+	molecule.Prepare()
+	molecule.Run()
 }
 
 // Prepare the Context for the Memcached Ansible Sample
@@ -518,17 +526,3 @@ const originalPlaybookFragment = `---
 const inventorysampleFragment = `name: inventorytest-sample
   annotations:
     "ansible.sdk.operatorframework.io/verbosity": "0"`
-
-// GenerateMoleculeAnsibleSample will call all actions to create the directory and generate the sample
-// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
-// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
-// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
-func GenerateMoleculeAdvancedAnsibleSample(path string) {
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(path, "advanced-molecule-operator"),
-		"GO111MODULE=on")
-	pkg.CheckError("generating Ansible Molecule Advanced Operator context", err)
-
-	molecule := NewAdvancedMolecule(&ctx)
-	molecule.Prepare()
-	molecule.Run()
-}
diff --git a/hack/generate/samples/internal/ansible/generate.go b/hack/generate/samples/internal/ansible/generate.go
new file mode 100644
index 00000000..2d0321e0
--- /dev/null
+++ b/hack/generate/samples/internal/ansible/generate.go
@@ -0,0 +1,23 @@
+// Copyright 2021 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 ansible
+
+import (
+	"path/filepath"
+)
+
+func GenerateMemcachedSamples(binaryPath, rootPath string) {
+	GenerateMemcachedSample(binaryPath, filepath.Join(rootPath, "ansible"))
+}
diff --git a/hack/generate/samples/internal/ansible/memcached.go b/hack/generate/samples/internal/ansible/memcached.go
index b3263bf5..cd9a5af3 100644
--- a/hack/generate/samples/internal/ansible/memcached.go
+++ b/hack/generate/samples/internal/ansible/memcached.go
@@ -27,20 +27,29 @@ import (
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
-// MemcachedAnsible defines the context for the sample
-type MemcachedAnsible struct {
+// Memcached defines the context for the sample
+type Memcached struct {
 	ctx *pkg.SampleContext
 }
 
-// NewMemcachedAnsible return a MemcachedAnsible
-func NewMemcachedAnsible(ctx *pkg.SampleContext) MemcachedAnsible {
-	return MemcachedAnsible{ctx}
+// GenerateMemcachedSample will call all actions to create the directory and generate the sample
+// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
+// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
+// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
+func GenerateMemcachedSample(binaryPath, samplesPath string) {
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"),
+		"GO111MODULE=on")
+	pkg.CheckError("generating Ansible memcached context", err)
+
+	memcached := Memcached{&ctx}
+	memcached.Prepare()
+	memcached.Run()
 }
 
 // Prepare the Context for the Memcached Ansible Sample
 // Note that sample directory will be re-created and the context data for the sample
 // will be set such as the domain and GVK.
-func (ma *MemcachedAnsible) Prepare() {
+func (ma *Memcached) Prepare() {
 	log.Infof("destroying directory for memcached Ansible samples")
 	ma.ctx.Destroy()
 
@@ -56,7 +65,7 @@ func (ma *MemcachedAnsible) Prepare() {
 }
 
 // Run the steps to create the Memcached Ansible Sample
-func (ma *MemcachedAnsible) Run() {
+func (ma *Memcached) Run() {
 	log.Infof("creating the project")
 	err := ma.ctx.Init(
 		"--plugins", "ansible",
@@ -87,7 +96,7 @@ func (ma *MemcachedAnsible) Run() {
 }
 
 // addingMoleculeMockData will customize the molecule data
-func (ma *MemcachedAnsible) addingMoleculeMockData() {
+func (ma *Memcached) addingMoleculeMockData() {
 	log.Infof("adding molecule test for Ansible task")
 	moleculeTaskPath := filepath.Join(ma.ctx.Dir, "molecule", "default", "tasks",
 		fmt.Sprintf("%s_test.yml", strings.ToLower(ma.ctx.Kind)))
@@ -98,7 +107,7 @@ func (ma *MemcachedAnsible) addingMoleculeMockData() {
 }
 
 // addingAnsibleTask will add the Ansible Task and update the sample
-func (ma *MemcachedAnsible) addingAnsibleTask() {
+func (ma *Memcached) addingAnsibleTask() {
 	log.Infof("adding Ansible task and variable")
 	err := kbtestutils.InsertCode(filepath.Join(ma.ctx.Dir, "roles", strings.ToLower(ma.ctx.Kind),
 		"tasks", "main.yml"),
@@ -117,17 +126,3 @@ func (ma *MemcachedAnsible) addingAnsibleTask() {
 		"foo: bar", "size: 1")
 	pkg.CheckError("updating sample CR", err)
 }
-
-// GenerateMemcachedAnsibleSample will call all actions to create the directory and generate the sample
-// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
-// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
-// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
-func GenerateMemcachedAnsibleSample(samplesPath string) {
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "ansible", "memcached-operator"),
-		"GO111MODULE=on")
-	pkg.CheckError("generating Ansible memcached context", err)
-
-	memcached := NewMemcachedAnsible(&ctx)
-	memcached.Prepare()
-	memcached.Run()
-}
diff --git a/hack/generate/samples/internal/ansible/memcached_molecule.go b/hack/generate/samples/internal/ansible/memcached_molecule.go
index add57b9a..5faad2f1 100644
--- a/hack/generate/samples/internal/ansible/memcached_molecule.go
+++ b/hack/generate/samples/internal/ansible/memcached_molecule.go
@@ -24,24 +24,33 @@ import (
 	kbtestutils "sigs.k8s.io/kubebuilder/v3/test/e2e/utils"
 
 	"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg"
-	"github.com/operator-framework/operator-sdk/internal/testutils"
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
-// MoleculeAnsible defines the context for the sample
-type MoleculeAnsible struct {
-	ctx *pkg.SampleContext
+// MemcachedMolecule defines the context for the sample
+type MemcachedMolecule struct {
+	ctx  *pkg.SampleContext
+	Base Memcached
 }
 
-// NewMoleculeAnsible return a MoleculeAnsible
-func NewMoleculeAnsible(ctx *pkg.SampleContext) MoleculeAnsible {
-	return MoleculeAnsible{ctx}
+// GenerateMoleculeSample will call all actions to create the directory and generate the sample
+// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
+// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
+// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
+func GenerateMoleculeSample(binaryPath, samplesPath string) {
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-molecule-operator"),
+		"GO111MODULE=on")
+	pkg.CheckError("generating Ansible Moleule memcached context", err)
+
+	molecule := MemcachedMolecule{ctx: &ctx, Base: Memcached{&ctx}}
+	molecule.Prepare()
+	molecule.Run()
 }
 
 // Prepare the Context for the Memcached Ansible Sample
 // Note that sample directory will be re-created and the context data for the sample
 // will be set such as the domain and GVK.
-func (ma *MoleculeAnsible) Prepare() {
+func (ma *MemcachedMolecule) Prepare() {
 	log.Infof("destroying directory for memcached Ansible samples")
 	ma.ctx.Destroy()
 
@@ -57,9 +66,8 @@ func (ma *MoleculeAnsible) Prepare() {
 }
 
 // Run the steps to create the Memcached Ansible Sample
-func (ma *MoleculeAnsible) Run() {
-	memcached := NewMemcachedAnsible(ma.ctx)
-	memcached.Run()
+func (ma *MemcachedMolecule) Run() {
+	ma.Base.Run()
 
 	moleculeTaskPath := filepath.Join(ma.ctx.Dir, "molecule", "default", "tasks",
 		fmt.Sprintf("%s_test.yml", strings.ToLower(ma.ctx.Kind)))
@@ -163,17 +171,3 @@ func (ma *MoleculeAnsible) Run() {
 		fixmeAssert, "")
 	pkg.CheckError("replacing foo_test.yml", err)
 }
-
-// GenerateMoleculeAnsibleSample will call all actions to create the directory and generate the sample
-// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
-// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
-// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
-func GenerateMoleculeAnsibleSample(path string) {
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(path, "memcached-molecule-operator"),
-		"GO111MODULE=on")
-	pkg.CheckError("generating Ansible Moleule memcached context", err)
-
-	molecule := NewMoleculeAnsible(&ctx)
-	molecule.Prepare()
-	molecule.Run()
-}
diff --git a/hack/generate/samples/internal/go/generate.go b/hack/generate/samples/internal/go/generate.go
index 2969a04e..df8895f1 100644
--- a/hack/generate/samples/internal/go/generate.go
+++ b/hack/generate/samples/internal/go/generate.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package pkg
+package golang
 
 import (
 	"path/filepath"
@@ -21,7 +21,7 @@ import (
 	golangv3 "github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go/v3"
 )
 
-func GenerateMemcachedGoWithWebhooksSample(rootPath string) {
-	golangv2.GenerateMemcachedGoWithWebhooksSample(filepath.Join(rootPath, "go", "v2"))
-	golangv3.GenerateMemcachedGoWithWebhooksSample(filepath.Join(rootPath, "go", "v3"))
+func GenerateMemcachedSamples(binaryPath, rootPath string) {
+	golangv2.GenerateMemcachedSample(binaryPath, filepath.Join(rootPath, "go", "v2"))
+	golangv3.GenerateMemcachedSample(binaryPath, filepath.Join(rootPath, "go", "v3"))
 }
diff --git a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go
index e6b6c8c4..110a7f31 100644
--- a/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go
+++ b/hack/generate/samples/internal/go/v2/memcached_with_webhooks.go
@@ -28,20 +28,27 @@ import (
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
-// MemcachedGoWithWebhooks defines the Memcached Sample in GO using webhooks
-type MemcachedGoWithWebhooks struct {
+// Memcached defines the Memcached Sample in GO using webhooks
+type Memcached struct {
 	ctx *pkg.SampleContext
 }
 
-// MemcachedGoWithWebhooks return a MemcachedGoWithWebhooks
-func NewMemcachedGoWithWebhooks(ctx *pkg.SampleContext) MemcachedGoWithWebhooks {
-	return MemcachedGoWithWebhooks{ctx}
+// GenerateMemcachedSample will call all actions to create the directory and generate the sample
+// Note that it should NOT be called in the e2e tests.
+func GenerateMemcachedSample(binaryPath, samplesPath string) {
+	log.Infof("starting to generate Go memcached sample with webhooks")
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
+	pkg.CheckError("generating Go memcached with webhooks context", err)
+
+	memcached := Memcached{&ctx}
+	memcached.Prepare()
+	memcached.Run()
 }
 
 // Prepare the Context for the Memcached with WebHooks Go Sample
 // Note that sample directory will be re-created and the context data for the sample
 // will be set such as the domain and GVK.
-func (mh *MemcachedGoWithWebhooks) Prepare() {
+func (mh *Memcached) Prepare() {
 	log.Infof("destroying directory for Memcached with Webhooks Go samples")
 	mh.ctx.Destroy()
 
@@ -57,7 +64,7 @@ func (mh *MemcachedGoWithWebhooks) Prepare() {
 }
 
 // Run the steps to create the Memcached with Webhooks Go Sample
-func (mh *MemcachedGoWithWebhooks) Run() {
+func (mh *Memcached) Run() {
 	log.Infof("creating the project")
 	err := mh.ctx.Init(
 		"--plugins", "go/v2",
@@ -108,7 +115,7 @@ func (mh *MemcachedGoWithWebhooks) Run() {
 }
 
 // uncommentDefaultKustomization will uncomment code in config/default/kustomization.yaml
-func (mh *MemcachedGoWithWebhooks) uncommentDefaultKustomization() {
+func (mh *Memcached) uncommentDefaultKustomization() {
 	var err error
 	kustomization := filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml")
 	log.Info("uncommenting config/default/kustomization.yaml to enable webhooks and ca injection")
@@ -159,7 +166,7 @@ func (mh *MemcachedGoWithWebhooks) uncommentDefaultKustomization() {
 }
 
 // uncommentManifestsKustomization will uncomment code in config/manifests/kustomization.yaml
-func (mh *MemcachedGoWithWebhooks) uncommentManifestsKustomization() {
+func (mh *Memcached) uncommentManifestsKustomization() {
 	var err error
 	kustomization := filepath.Join(mh.ctx.Dir, "config", "manifests", "kustomization.yaml")
 	log.Info("uncommenting config/manifests/kustomization.yaml to enable webhooks in OLM")
@@ -185,7 +192,7 @@ func (mh *MemcachedGoWithWebhooks) uncommentManifestsKustomization() {
 }
 
 // implementingWebhooks will customize the kind wekbhok file
-func (mh *MemcachedGoWithWebhooks) implementingWebhooks() {
+func (mh *Memcached) implementingWebhooks() {
 	log.Infof("implementing webhooks")
 	webhookPath := filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_webhook.go",
 		strings.ToLower(mh.ctx.Kind)))
@@ -208,7 +215,7 @@ func (mh *MemcachedGoWithWebhooks) implementingWebhooks() {
 }
 
 // implementingController will customize the Controller
-func (mh *MemcachedGoWithWebhooks) implementingController() {
+func (mh *Memcached) implementingController() {
 	controllerPath := filepath.Join(mh.ctx.Dir, "controllers", fmt.Sprintf("%s_controller.go",
 		strings.ToLower(mh.ctx.Kind)))
 
@@ -252,7 +259,7 @@ func (mh *MemcachedGoWithWebhooks) implementingController() {
 
 // nolint:gosec
 // implementingAPI will customize the API
-func (mh *MemcachedGoWithWebhooks) implementingAPI() {
+func (mh *Memcached) implementingAPI() {
 	typeFilePath := filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind)))
 
 	log.Infof("implementing api spec")
@@ -285,18 +292,6 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() {
 	pkg.CheckError("updating sample", err)
 }
 
-// GenerateMemcachedGoWithWebhooksSample will call all actions to create the directory and generate the sample
-// Note that it should NOT be called in the e2e tests.
-func GenerateMemcachedGoWithWebhooksSample(samplesPath string) {
-	log.Infof("starting to generate Go memcached sample with webhooks")
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
-	pkg.CheckError("generating Go memcached with webhooks context", err)
-
-	memcached := NewMemcachedGoWithWebhooks(&ctx)
-	memcached.Prepare()
-	memcached.Run()
-}
-
 const rbacFragment = `
 //+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update
 //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
diff --git a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go
index cd2a210a..67e8283f 100644
--- a/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go
+++ b/hack/generate/samples/internal/go/v3/memcached_with_webhooks.go
@@ -28,20 +28,27 @@ import (
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
-// MemcachedGoWithWebhooks defines the Memcached Sample in GO using webhooks
-type MemcachedGoWithWebhooks struct {
+// Memcached defines the Memcached Sample in GO using webhooks
+type Memcached struct {
 	ctx *pkg.SampleContext
 }
 
-// MemcachedGoWithWebhooks return a MemcachedGoWithWebhooks
-func NewMemcachedGoWithWebhooks(ctx *pkg.SampleContext) MemcachedGoWithWebhooks {
-	return MemcachedGoWithWebhooks{ctx}
+// GenerateMemcachedSample will call all actions to create the directory and generate the sample
+// Note that it should NOT be called in the e2e tests.
+func GenerateMemcachedSample(binaryPath, samplesPath string) {
+	log.Infof("starting to generate Go memcached sample with webhooks")
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
+	pkg.CheckError("generating Go memcached with webhooks context", err)
+
+	memcached := Memcached{&ctx}
+	memcached.Prepare()
+	memcached.Run()
 }
 
 // Prepare the Context for the Memcached with WebHooks Go Sample
 // Note that sample directory will be re-created and the context data for the sample
 // will be set such as the domain and GVK.
-func (mh *MemcachedGoWithWebhooks) Prepare() {
+func (mh *Memcached) Prepare() {
 	log.Infof("destroying directory for Memcached with Webhooks Go samples")
 	mh.ctx.Destroy()
 
@@ -57,7 +64,7 @@ func (mh *MemcachedGoWithWebhooks) Prepare() {
 }
 
 // Run the steps to create the Memcached with Webhooks Go Sample
-func (mh *MemcachedGoWithWebhooks) Run() {
+func (mh *Memcached) Run() {
 	log.Infof("creating the project")
 	err := mh.ctx.Init(
 		"--plugins", "go/v3",
@@ -108,7 +115,7 @@ func (mh *MemcachedGoWithWebhooks) Run() {
 }
 
 // uncommentDefaultKustomization will uncomment code in config/default/kustomization.yaml
-func (mh *MemcachedGoWithWebhooks) uncommentDefaultKustomization() {
+func (mh *Memcached) uncommentDefaultKustomization() {
 	var err error
 	kustomization := filepath.Join(mh.ctx.Dir, "config", "default", "kustomization.yaml")
 	log.Info("uncommenting config/default/kustomization.yaml to enable webhooks and ca injection")
@@ -159,7 +166,7 @@ func (mh *MemcachedGoWithWebhooks) uncommentDefaultKustomization() {
 }
 
 // uncommentManifestsKustomization will uncomment code in config/manifests/kustomization.yaml
-func (mh *MemcachedGoWithWebhooks) uncommentManifestsKustomization() {
+func (mh *Memcached) uncommentManifestsKustomization() {
 	var err error
 	kustomization := filepath.Join(mh.ctx.Dir, "config", "manifests", "kustomization.yaml")
 	log.Info("uncommenting config/manifests/kustomization.yaml to enable webhooks in OLM")
@@ -185,7 +192,7 @@ func (mh *MemcachedGoWithWebhooks) uncommentManifestsKustomization() {
 }
 
 // implementingWebhooks will customize the kind wekbhok file
-func (mh *MemcachedGoWithWebhooks) implementingWebhooks() {
+func (mh *Memcached) implementingWebhooks() {
 	log.Infof("implementing webhooks")
 	webhookPath := filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_webhook.go",
 		strings.ToLower(mh.ctx.Kind)))
@@ -209,7 +216,7 @@ func (mh *MemcachedGoWithWebhooks) implementingWebhooks() {
 }
 
 // implementingController will customize the Controller
-func (mh *MemcachedGoWithWebhooks) implementingController() {
+func (mh *Memcached) implementingController() {
 	controllerPath := filepath.Join(mh.ctx.Dir, "controllers", fmt.Sprintf("%s_controller.go",
 		strings.ToLower(mh.ctx.Kind)))
 
@@ -250,7 +257,7 @@ func (mh *MemcachedGoWithWebhooks) implementingController() {
 
 // nolint:gosec
 // implementingAPI will customize the API
-func (mh *MemcachedGoWithWebhooks) implementingAPI() {
+func (mh *Memcached) implementingAPI() {
 	err := kbtestutils.InsertCode(
 		filepath.Join(mh.ctx.Dir, "api", mh.ctx.Version, fmt.Sprintf("%s_types.go", strings.ToLower(mh.ctx.Kind))),
 		fmt.Sprintf("type %sSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file", mh.ctx.Kind),
@@ -280,18 +287,6 @@ func (mh *MemcachedGoWithWebhooks) implementingAPI() {
 	pkg.CheckError("updating sample", err)
 }
 
-// GenerateMemcachedGoWithWebhooksSample will call all actions to create the directory and generate the sample
-// Note that it should NOT be called in the e2e tests.
-func GenerateMemcachedGoWithWebhooksSample(samplesPath string) {
-	log.Infof("starting to generate Go memcached sample with webhooks")
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
-	pkg.CheckError("generating Go memcached with webhooks context", err)
-
-	memcached := NewMemcachedGoWithWebhooks(&ctx)
-	memcached.Prepare()
-	memcached.Run()
-}
-
 const rbacFragment = `
 //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
 //+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch`
diff --git a/hack/generate/samples/internal/helm/generate.go b/hack/generate/samples/internal/helm/generate.go
new file mode 100644
index 00000000..771bd367
--- /dev/null
+++ b/hack/generate/samples/internal/helm/generate.go
@@ -0,0 +1,23 @@
+// Copyright 2021 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 helm
+
+import (
+	"path/filepath"
+)
+
+func GenerateMemcachedSamples(binaryPath, rootPath string) {
+	GenerateMemcachedSample(binaryPath, filepath.Join(rootPath, "helm"))
+}
diff --git a/hack/generate/samples/internal/helm/memcached.go b/hack/generate/samples/internal/helm/memcached.go
index eaa917ed..7888a4ff 100644
--- a/hack/generate/samples/internal/helm/memcached.go
+++ b/hack/generate/samples/internal/helm/memcached.go
@@ -25,20 +25,29 @@ import (
 	"github.com/operator-framework/operator-sdk/internal/util"
 )
 
-// MemcachedHelm defines the Memcached Sample in Helm
-type MemcachedHelm struct {
+// Memcached defines the Memcached Sample in Helm
+type Memcached struct {
 	ctx *pkg.SampleContext
 }
 
-// NewMemcachedHelm return a MemcachedHelm
-func NewMemcachedHelm(ctx *pkg.SampleContext) MemcachedHelm {
-	return MemcachedHelm{ctx}
+// GenerateMemcachedSample will call all actions to create the directory and generate the sample
+// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
+// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
+// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
+func GenerateMemcachedSample(binaryPath, samplesPath string) {
+	ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"),
+		"GO111MODULE=on")
+	pkg.CheckError("generating Helm memcached context", err)
+
+	memcached := Memcached{&ctx}
+	memcached.Prepare()
+	memcached.Run()
 }
 
 // Prepare the Context for the Memcached Helm Sample
 // Note that sample directory will be re-created and the context data for the sample
 // will be set such as the domain and GVK.
-func (mh *MemcachedHelm) Prepare() {
+func (mh *Memcached) Prepare() {
 	log.Infof("destroying directory for memcached helm samples")
 	mh.ctx.Destroy()
 
@@ -54,7 +63,7 @@ func (mh *MemcachedHelm) Prepare() {
 }
 
 // Run runs the steps to generate the sample
-func (mh *MemcachedHelm) Run() {
+func (mh *Memcached) Run() {
 	// When operator-sdk scaffolds Helm projects, it tries to use the discovery API of a Kubernetes
 	// cluster to intelligently build the RBAC rules that the operator will require based on the
 	// content of the helm chart.
@@ -103,19 +112,6 @@ func (mh *MemcachedHelm) Run() {
 	pkg.CheckError("striping bundle annotations", err)
 }
 
-// GenerateMemcachedHelmSample will call all actions to create the directory and generate the sample
-// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT
-// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files
-// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.
-func GenerateMemcachedHelmSample(samplesPath string) {
-	ctx, err := pkg.NewSampleContext(testutils.BinaryName, filepath.Join(samplesPath, "helm", "memcached-operator"), "GO111MODULE=on")
-	pkg.CheckError("generating Helm memcached context", err)
-
-	memcached := NewMemcachedHelm(&ctx)
-	memcached.Prepare()
-	memcached.Run()
-}
-
 const policyRolesFragment = `
 ##
 ## Rules customized for cache.example.com/v1alpha1, Kind: Memcached
diff --git a/hack/generate/samples/molecule/generate.go b/hack/generate/samples/molecule/generate.go
index 69f33026..5deceedb 100644
--- a/hack/generate/samples/molecule/generate.go
+++ b/hack/generate/samples/molecule/generate.go
@@ -29,46 +29,50 @@ import (
 // This generate is used to run the e2e molecule tests
 func main() {
 	var (
-		// binaryName allow inform the binary that should be used.
+		// binaryPath allow inform the binary that should be used.
 		// By default it is operator-sdk
-		binaryName string
+		binaryPath string
 
-		// path is the path provided to generate the molecule sample
-		path string
+		// samplesRoot is the path provided to generate the molecule sample
+		samplesRoot string
 
 		// sample is the name of the mock was selected to be generated
 		sample string
 	)
 
-	// testdata is the path where all samples are generate
-	const testdata = "/testdata/"
-
-	flag.StringVar(&binaryName, "bin", testutils.BinaryName, "Binary path that should be used")
-	flag.StringVar(&path, "path", "", "Path where the molecule should be called")
-	flag.StringVar(&sample, "sample", "", "To generate only the selected option. Options: [advanced,memcached]")
+	flag.StringVar(&binaryPath, "bin", testutils.BinaryName, "Binary path that should be used")
+	flag.StringVar(&samplesRoot, "samples-root", "", "Path where molecule samples should be generated")
+	flag.StringVar(&sample, "sample", "", "To generate only the selected option. Options: [advanced, memcached]")
 
 	flag.Parse()
 
+	// Make the binary path absolute if pathed, for reproducibility and debugging purposes.
+	if dir, _ := filepath.Split(binaryPath); dir != "" {
+		tmp, err := filepath.Abs(binaryPath)
+		if err != nil {
+			log.Fatalf("Failed to make binary path %q absolute: %v", binaryPath, err)
+		}
+		binaryPath = tmp
+	}
+
 	// If no path be provided then the Molecule sample will be create in the testdata/ansible dir
 	// It can be helpful to check the mock data used in the e2e molecule tests as to develop this sample
 	// By default this mock is ignored in the .gitignore
-	if strings.TrimSpace(path) == "" {
+	if strings.TrimSpace(samplesRoot) == "" {
 		currentPath, err := os.Getwd()
 		if err != nil {
-			log.Error(err)
-			os.Exit(1)
+			log.Fatal(err)
 		}
-		path = filepath.Join(currentPath, testdata, "ansible")
+		samplesRoot = filepath.Join(currentPath, "testdata", "ansible")
 	}
 
-	log.Infof("creating Ansible Molecule Mock Sample")
-	log.Infof("using the path: (%v)", path)
+	log.Infof("creating Ansible Molecule Mock Samples under %s", samplesRoot)
 
 	if sample == "" || sample == "memcached" {
-		ansible.GenerateMoleculeAnsibleSample(path)
+		ansible.GenerateMoleculeSample(binaryPath, samplesRoot)
 	}
 
 	if sample == "" || sample == "advanced" {
-		ansible.GenerateMoleculeAdvancedAnsibleSample(path)
+		ansible.GenerateAdvancedMoleculeSample(binaryPath, samplesRoot)
 	}
 }
diff --git a/images/ansible-operator/base.Dockerfile b/images/ansible-operator/base.Dockerfile
index f91c9eba..c908219f 100644
--- a/images/ansible-operator/base.Dockerfile
+++ b/images/ansible-operator/base.Dockerfile
@@ -2,7 +2,7 @@
 # It is built with dependencies that take a while to download, thus speeding
 # up ansible deploy jobs.
 
-FROM registry.access.redhat.com/ubi8/ubi:8.3-227
+FROM registry.access.redhat.com/ubi8/ubi:8.3-297
 ARG TARGETARCH
 
 RUN mkdir -p /etc/ansible \
diff --git a/images/helm-operator/Dockerfile b/images/helm-operator/Dockerfile
index 7b674974..90bf1ca6 100644
--- a/images/helm-operator/Dockerfile
+++ b/images/helm-operator/Dockerfile
@@ -17,7 +17,7 @@ COPY . .
 RUN GOOS=linux GOARCH=$TARGETARCH make build/helm-operator
 
 # Final image.
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-298
 
 ENV HOME=/opt/helm \
     USER_NAME=helm \
diff --git a/images/operator-sdk/Dockerfile b/images/operator-sdk/Dockerfile
index 71dbde57..3d29d371 100644
--- a/images/operator-sdk/Dockerfile
+++ b/images/operator-sdk/Dockerfile
@@ -17,7 +17,7 @@ COPY . .
 RUN GOOS=linux GOARCH=$TARGETARCH make build/operator-sdk
 
 # Final image.
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-298
 
 RUN microdnf install -y golang make which
 
diff --git a/internal/ansible/flags/flag.go b/internal/ansible/flags/flag.go
index 49cadfba..23daa77c 100644
--- a/internal/ansible/flags/flag.go
+++ b/internal/ansible/flags/flag.go
@@ -19,6 +19,8 @@ import (
 	"time"
 
 	"github.com/spf13/pflag"
+	"k8s.io/client-go/tools/leaderelection/resourcelock"
+	"sigs.k8s.io/controller-runtime/pkg/manager"
 )
 
 // Flags - Options to be used by an ansible operator
@@ -37,18 +39,26 @@ type Flags struct {
 	LeaderElectionNamespace string
 	GracefulShutdownTimeout time.Duration
 	AnsibleArgs             string
+
+	// Path to a controller-runtime componentconfig file.
+	// If this is empty, use default values.
+	ManagerConfigPath string
+
+	// If not nil, used to deduce which flags were set in the CLI.
+	flagSet *pflag.FlagSet
 }
 
-const AnsibleRolesPathEnvVar = "ANSIBLE_ROLES_PATH"
-const AnsibleCollectionsPathEnvVar = "ANSIBLE_COLLECTIONS_PATH"
+const (
+	AnsibleRolesPathEnvVar       = "ANSIBLE_ROLES_PATH"
+	AnsibleCollectionsPathEnvVar = "ANSIBLE_COLLECTIONS_PATH"
+)
 
 // AddTo - Add the ansible operator flags to the the flagset
 func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
-	flagSet.DurationVar(&f.ReconcilePeriod,
-		"reconcile-period",
-		time.Minute,
-		"Default reconcile period for controllers",
-	)
+	// Store flagset internally to be used for lookups later.
+	f.flagSet = flagSet
+
+	// Ansible flags.
 	flagSet.StringVar(&f.WatchesFile,
 		"watches-file",
 		"./watches.yaml",
@@ -59,11 +69,6 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 		true,
 		"The ansible operator will inject owner references unless this flag is false",
 	)
-	flagSet.IntVar(&f.MaxConcurrentReconciles,
-		"max-concurrent-reconciles",
-		runtime.NumCPU(),
-		"Maximum number of concurrent reconciles for controllers. Overridden by environment variable.",
-	)
 	flagSet.IntVar(&f.AnsibleVerbosity,
 		"ansible-verbosity",
 		2,
@@ -77,9 +82,36 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 	flagSet.StringVar(&f.AnsibleCollectionsPath,
 		"ansible-collections-path",
 		"",
-		"Path to installed Ansible Collections. If set, collections should be located in {{value}}/ansible_collections/. If unset, collections are assumed to be in ~/.ansible/collections or /usr/share/ansible/collections.",
+		"Path to installed Ansible Collections. If set, collections should be located in {{value}}/ansible_collections/. "+
+			"If unset, collections are assumed to be in ~/.ansible/collections or /usr/share/ansible/collections.",
+	)
+	flagSet.StringVar(&f.AnsibleArgs,
+		"ansible-args",
+		"",
+		"Ansible args. Allows user to specify arbitrary arguments for ansible-based operators.",
+	)
+
+	// Controller flags.
+	flagSet.DurationVar(&f.ReconcilePeriod,
+		"reconcile-period",
+		time.Minute,
+		"Default reconcile period for controllers",
+	)
+	flagSet.IntVar(&f.MaxConcurrentReconciles,
+		"max-concurrent-reconciles",
+		runtime.NumCPU(),
+		"Maximum number of concurrent reconciles for controllers. Overridden by environment variable.",
+	)
+
+	// Controller manager flags.
+	flagSet.StringVar(&f.ManagerConfigPath,
+		"config",
+		"",
+		"The controller will load its initial configuration from this file. "+
+			"Omit this flag to use the default configuration values. "+
+			"Command-line flags override configuration from this file.",
 	)
-	// todo:remove it for 2.0.0
+	// TODO(2.0.0): remove
 	flagSet.StringVar(&f.MetricsBindAddress,
 		"metrics-addr",
 		":8080",
@@ -91,15 +123,14 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 		":8080",
 		"The address the metric endpoint binds to",
 	)
-	// todo: for Go/Helm the port used is: 8081
+	// TODO(2.0.0): for Go/Helm the port used is: 8081
 	// update it to keep the project aligned to the other
-	// types for 2.0
 	flagSet.StringVar(&f.ProbeAddr,
 		"health-probe-bind-address",
 		":6789",
 		"The address the probe endpoint binds to.",
 	)
-	// todo:remove it for 2.0.0
+	// TODO(2.0.0): remove
 	flagSet.BoolVar(&f.LeaderElection,
 		"enable-leader-election",
 		false,
@@ -131,9 +162,43 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 		"The amount of time that will be spent waiting"+
 			" for runners to gracefully exit.",
 	)
-	flagSet.StringVar(&f.AnsibleArgs,
-		"ansible-args",
-		"",
-		"Ansible args. Allows user to specify arbitrary arguments for ansible-based operators.",
-	)
+}
+
+// ToManagerOptions uses the flag set in f to configure options.
+// Values of options take precedence over flag defaults,
+// as values are assume to have been explicitly set.
+func (f *Flags) ToManagerOptions(options manager.Options) manager.Options {
+	// Alias FlagSet.Changed so options are still updated when fields are empty.
+	changed := func(flagName string) bool {
+		return f.flagSet.Changed(flagName)
+	}
+	if f.flagSet == nil {
+		changed = func(flagName string) bool { return false }
+	}
+
+	// TODO(2.0.0): remove metrics-addr
+	if changed("metrics-bind-address") || changed("metrics-addr") || options.MetricsBindAddress == "" {
+		options.MetricsBindAddress = f.MetricsBindAddress
+	}
+	if changed("health-probe-bind-address") || options.HealthProbeBindAddress == "" {
+		options.HealthProbeBindAddress = f.ProbeAddr
+	}
+	// TODO(2.0.0): remove enable-leader-election
+	if changed("leader-elect") || changed("enable-leader-election") || !options.LeaderElection {
+		options.LeaderElection = f.LeaderElection
+	}
+	if changed("leader-election-id") || options.LeaderElectionID == "" {
+		options.LeaderElectionID = f.LeaderElectionID
+	}
+	if changed("leader-election-namespace") || options.LeaderElectionNamespace == "" {
+		options.LeaderElectionNamespace = f.LeaderElectionNamespace
+	}
+	if options.LeaderElectionResourceLock == "" {
+		options.LeaderElectionResourceLock = resourcelock.ConfigMapsResourceLock
+	}
+	if changed("graceful-shutdown-timeout") || options.GracefulShutdownTimeout == nil {
+		options.GracefulShutdownTimeout = &f.GracefulShutdownTimeout
+	}
+
+	return options
 }
diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go
index a1c17f53..88ca079c 100644
--- a/internal/cmd/ansible-operator/run/cmd.go
+++ b/internal/cmd/ansible-operator/run/cmd.go
@@ -25,7 +25,7 @@ import (
 
 	"github.com/spf13/cobra"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/client-go/tools/leaderelection/resourcelock"
+	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/cache"
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
 	"sigs.k8s.io/controller-runtime/pkg/healthz"
@@ -82,25 +82,43 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 	printVersion()
 	metrics.RegisterBuildInfo(crmetrics.Registry)
 
+	// Load config options from the config at f.ManagerConfigPath.
+	// These options will not override those set by flags.
+	var (
+		options manager.Options
+		err     error
+	)
+	if f.ManagerConfigPath != "" {
+		cfgLoader := ctrl.ConfigFile().AtPath(f.ManagerConfigPath)
+		if options, err = options.AndFrom(cfgLoader); err != nil {
+			log.Error(err, "Unable to load the manager config file")
+			os.Exit(1)
+		}
+	}
+	exitIfUnsupported(options)
+
 	cfg, err := config.GetConfig()
 	if err != nil {
 		log.Error(err, "Failed to get config.")
 		os.Exit(1)
 	}
 
+	// TODO(2.0.0): remove
 	// Deprecated: OPERATOR_NAME environment variable is an artifact of the
 	// legacy operator-sdk project scaffolding. Flag `--leader-election-id`
 	// should be used instead.
 	if operatorName, found := os.LookupEnv("OPERATOR_NAME"); found {
 		log.Info("Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.")
-		if cmd.Flags().Lookup("leader-election-id").Changed {
+		if cmd.Flags().Changed("leader-election-id") {
 			log.Info("Ignoring OPERATOR_NAME environment variable since --leader-election-id is set")
-		} else {
-			f.LeaderElectionID = operatorName
+		} else if options.LeaderElectionID == "" {
+			// Only set leader election ID using OPERATOR_NAME if unset everywhere else,
+			// since this env var is deprecated.
+			options.LeaderElectionID = operatorName
 		}
 	}
 
-	//todo: remove the following checks for 2.0.0 they are required just because of the flags deprecation
+	//TODO(2.0.0): remove the following checks. they are required just because of the flags deprecation
 	if cmd.Flags().Changed("leader-elect") && cmd.Flags().Changed("enable-leader-election") {
 		log.Error(errors.New("only one of --leader-elect and --enable-leader-election may be set"), "invalid flags usage")
 		os.Exit(1)
@@ -113,20 +131,15 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 
 	// Set default manager options
 	// TODO: probably should expose the host & port as an environment variables
-	options := manager.Options{
-		MetricsBindAddress:         f.MetricsBindAddress,
-		HealthProbeBindAddress:     f.ProbeAddr,
-		LeaderElection:             f.LeaderElection,
-		LeaderElectionID:           f.LeaderElectionID,
-		LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock,
-		LeaderElectionNamespace:    f.LeaderElectionNamespace,
-		ClientBuilder:              clientbuilder.NewUnstructedCached(),
-		GracefulShutdownTimeout:    &f.GracefulShutdownTimeout,
+	options = f.ToManagerOptions(options)
+	if options.ClientBuilder == nil {
+		options.ClientBuilder = clientbuilder.NewUnstructedCached()
 	}
 
 	namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
 	log = log.WithValues("Namespace", namespace)
 	if found {
+		log.V(1).Info("Setting namespace with value in %s", k8sutil.WatchNamespaceEnvVar)
 		if namespace == metav1.NamespaceAll {
 			log.Info("Watching all namespaces.")
 			options.Namespace = metav1.NamespaceAll
@@ -139,9 +152,9 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 				options.Namespace = namespace
 			}
 		}
-	} else {
-		log.Info(fmt.Sprintf("%v environment variable not set. Watching all namespaces.",
-			k8sutil.WatchNamespaceEnvVar))
+	} else if options.Namespace == "" {
+		log.Info(fmt.Sprintf("Watch namespaces not configured by environment variable %s or file. "+
+			"Watching all namespaces.", k8sutil.WatchNamespaceEnvVar))
 		options.Namespace = metav1.NamespaceAll
 	}
 
@@ -202,7 +215,7 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 		}, w.Blacklist)
 	}
 
-	// todo: remove when a upper version be bumped
+	// TODO(2.0.0): remove
 	err = mgr.AddHealthzCheck("ping", healthz.Ping)
 	if err != nil {
 		log.Error(err, "Failed to add Healthz check.")
@@ -219,7 +232,7 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 		RESTMapper:        mgr.GetRESTMapper(),
 		ControllerMap:     cMap,
 		OwnerInjection:    f.InjectOwnerRef,
-		WatchedNamespaces: []string{namespace},
+		WatchedNamespaces: strings.Split(namespace, ","),
 	})
 	if err != nil {
 		log.Error(err, "Error starting proxy.")
@@ -240,6 +253,27 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 	log.Info("Exiting.")
 }
 
+// exitIfUnsupported prints an error containing unsupported field names and exits
+// if any of those fields are not their default values.
+func exitIfUnsupported(options manager.Options) {
+	var keys []string
+	// The below options are webhook-specific, which is not supported by ansible.
+	if options.CertDir != "" {
+		keys = append(keys, "certDir")
+	}
+	if options.Host != "" {
+		keys = append(keys, "host")
+	}
+	if options.Port != 0 {
+		keys = append(keys, "port")
+	}
+
+	if len(keys) > 0 {
+		log.Error(fmt.Errorf("%s set in manager options", strings.Join(keys, ", ")), "unsupported fields")
+		os.Exit(1)
+	}
+}
+
 // getAnsibleDebugLog return the value from the ANSIBLE_DEBUG_LOGS it order to
 // print the full Ansible logs
 func getAnsibleDebugLog() bool {
diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go
index c3742d3b..198313bf 100644
--- a/internal/cmd/helm-operator/run/cmd.go
+++ b/internal/cmd/helm-operator/run/cmd.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/spf13/cobra"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/client-go/tools/leaderelection/resourcelock"
+	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/cache"
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
 	"sigs.k8s.io/controller-runtime/pkg/healthz"
@@ -79,25 +79,43 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 	printVersion()
 	metrics.RegisterBuildInfo(crmetrics.Registry)
 
+	// Load config options from the config at f.ManagerConfigPath.
+	// These options will not override those set by flags.
+	var (
+		options manager.Options
+		err     error
+	)
+	if f.ManagerConfigPath != "" {
+		cfgLoader := ctrl.ConfigFile().AtPath(f.ManagerConfigPath)
+		if options, err = options.AndFrom(cfgLoader); err != nil {
+			log.Error(err, "Unable to load the manager config file")
+			os.Exit(1)
+		}
+	}
+	exitIfUnsupported(options)
+
 	cfg, err := config.GetConfig()
 	if err != nil {
 		log.Error(err, "Failed to get config.")
 		os.Exit(1)
 	}
 
+	// TODO(2.0.0): remove
 	// Deprecated: OPERATOR_NAME environment variable is an artifact of the
 	// legacy operator-sdk project scaffolding. Flag `--leader-election-id`
 	// should be used instead.
 	if operatorName, found := os.LookupEnv("OPERATOR_NAME"); found {
 		log.Info("Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.")
-		if cmd.Flags().Lookup("leader-election-id").Changed {
+		if cmd.Flags().Changed("leader-election-id") {
 			log.Info("Ignoring OPERATOR_NAME environment variable since --leader-election-id is set")
-		} else {
-			f.LeaderElectionID = operatorName
+		} else if options.LeaderElectionID == "" {
+			// Only set leader election ID using OPERATOR_NAME if unset everywhere else,
+			// since this env var is deprecated.
+			options.LeaderElectionID = operatorName
 		}
 	}
 
-	//todo: remove the following checks for 2.0.0 they are required just because of the flags deprecation
+	//TODO(2.0.0): remove the following checks. they are required just because of the flags deprecation
 	if cmd.Flags().Changed("leader-elect") && cmd.Flags().Changed("enable-leader-election") {
 		log.Error(errors.New("only one of --leader-elect and --enable-leader-election may be set"), "invalid flags usage")
 		os.Exit(1)
@@ -109,19 +127,15 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 	}
 
 	// Set default manager options
-	options := manager.Options{
-		MetricsBindAddress:         f.MetricsBindAddress,
-		HealthProbeBindAddress:     f.ProbeAddr,
-		LeaderElection:             f.LeaderElection,
-		LeaderElectionID:           f.LeaderElectionID,
-		LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock,
-		LeaderElectionNamespace:    f.LeaderElectionNamespace,
-		ClientBuilder:              clientbuilder.NewUnstructedCached(),
+	options = f.ToManagerOptions(options)
+	if options.ClientBuilder == nil {
+		options.ClientBuilder = clientbuilder.NewUnstructedCached()
 	}
 
 	namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
 	log = log.WithValues("Namespace", namespace)
 	if found {
+		log.V(1).Info("Setting namespace with value in %s", k8sutil.WatchNamespaceEnvVar)
 		if namespace == metav1.NamespaceAll {
 			log.Info("Watching all namespaces.")
 			options.Namespace = metav1.NamespaceAll
@@ -134,9 +148,9 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 				options.Namespace = namespace
 			}
 		}
-	} else {
-		log.Info(fmt.Sprintf("%v environment variable not set. Watching all namespaces.",
-			k8sutil.WatchNamespaceEnvVar))
+	} else if options.Namespace == "" {
+		log.Info(fmt.Sprintf("Watch namespaces not configured by environment variable %s or file. "+
+			"Watching all namespaces.", k8sutil.WatchNamespaceEnvVar))
 		options.Namespace = metav1.NamespaceAll
 	}
 
@@ -183,3 +197,24 @@ func run(cmd *cobra.Command, f *flags.Flags) {
 		os.Exit(1)
 	}
 }
+
+// exitIfUnsupported prints an error containing unsupported field names and exits
+// if any of those fields are not their default values.
+func exitIfUnsupported(options manager.Options) {
+	var keys []string
+	// The below options are webhook-specific, which is not supported by ansible.
+	if options.CertDir != "" {
+		keys = append(keys, "certDir")
+	}
+	if options.Host != "" {
+		keys = append(keys, "host")
+	}
+	if options.Port != 0 {
+		keys = append(keys, "port")
+	}
+
+	if len(keys) > 0 {
+		log.Error(fmt.Errorf("%s set in manager options", strings.Join(keys, ", ")), "unsupported fields")
+		os.Exit(1)
+	}
+}
diff --git a/internal/cmd/operator-sdk/cli/cli.go b/internal/cmd/operator-sdk/cli/cli.go
index 15b5375a..ad634338 100644
--- a/internal/cmd/operator-sdk/cli/cli.go
+++ b/internal/cmd/operator-sdk/cli/cli.go
@@ -69,13 +69,6 @@ func Run() error {
 // This CLI can run kubebuilder commands and certain SDK specific commands that are aligned for
 // the kubebuilder project layout
 func GetPluginsCLIAndRoot() (*cli.CLI, *cobra.Command) {
-	ansibleBundle, _ := plugin.NewBundle("ansible"+plugins.DefaultNameQualifier, plugin.Version{Number: 1},
-		kustomizev1.Plugin{},
-		ansiblev1.Plugin{},
-		manifestsv2.Plugin{},
-		scorecardv2.Plugin{},
-	)
-
 	// todo: Export the bundles KB and then change here to use the bundles exported instead
 	// more info: https://github.com/kubernetes-sigs/kubebuilder/pull/2112
 	gov2Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, golangv2.Plugin{}.Version(),
@@ -90,6 +83,12 @@ func GetPluginsCLIAndRoot() (*cli.CLI, *cobra.Command) {
 		manifestsv2.Plugin{},
 		scorecardv2.Plugin{},
 	)
+	ansibleBundle, _ := plugin.NewBundle("ansible"+plugins.DefaultNameQualifier, plugin.Version{Number: 1},
+		kustomizev1.Plugin{},
+		ansiblev1.Plugin{},
+		manifestsv2.Plugin{},
+		scorecardv2.Plugin{},
+	)
 	helmBundle, _ := plugin.NewBundle("helm"+plugins.DefaultNameQualifier, plugin.Version{Number: 1},
 		kustomizev1.Plugin{},
 		helmv1.Plugin{},
diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go
index b731e71e..0986cc0b 100644
--- a/internal/cmd/operator-sdk/generate/bundle/bundle.go
+++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go
@@ -20,6 +20,7 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"sort"
 	"strings"
 	"text/template"
 
@@ -286,6 +287,7 @@ func (c bundleCmd) runMetadata() error {
 	for key, value := range metricsannotations.MakeBundleMetadataLabels(c.layout) {
 		values.OtherLabels = append(values.OtherLabels, fmt.Sprintf("%s=%s", key, value))
 	}
+	sort.Strings(values.OtherLabels)
 
 	// Write each file.
 	metadataDir := filepath.Join(c.outputDir, "metadata")
diff --git a/internal/helm/flags/flag.go b/internal/helm/flags/flag.go
index b64a2f71..bddc0a35 100644
--- a/internal/helm/flags/flag.go
+++ b/internal/helm/flags/flag.go
@@ -19,6 +19,8 @@ import (
 	"time"
 
 	"github.com/spf13/pflag"
+	"k8s.io/client-go/tools/leaderelection/resourcelock"
+	"sigs.k8s.io/controller-runtime/pkg/manager"
 )
 
 // Flags - Options to be used by a helm operator
@@ -31,21 +33,48 @@ type Flags struct {
 	LeaderElectionNamespace string
 	MaxConcurrentReconciles int
 	ProbeAddr               string
+
+	// Path to a controller-runtime componentconfig file.
+	// If this is empty, use default values.
+	ManagerConfigPath string
+
+	// If not nil, used to deduce which flags were set in the CLI.
+	flagSet *pflag.FlagSet
 }
 
 // AddTo - Add the helm operator flags to the the flagset
 func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
+	// Store flagset internally to be used for lookups later.
+	f.flagSet = flagSet
+
+	// Helm flags.
+	flagSet.StringVar(&f.WatchesFile,
+		"watches-file",
+		"./watches.yaml",
+		"Path to the watches file to use",
+	)
+
+	// Controller flags.
 	flagSet.DurationVar(&f.ReconcilePeriod,
 		"reconcile-period",
 		time.Minute,
 		"Default reconcile period for controllers",
 	)
-	flagSet.StringVar(&f.WatchesFile,
-		"watches-file",
-		"./watches.yaml",
-		"Path to the watches file to use",
+	flagSet.IntVar(&f.MaxConcurrentReconciles,
+		"max-concurrent-reconciles",
+		runtime.NumCPU(),
+		"Maximum number of concurrent reconciles for controllers.",
 	)
-	// todo:remove it for 2.0.0
+
+	// Controller manager flags.
+	flagSet.StringVar(&f.ManagerConfigPath,
+		"config",
+		"",
+		"The controller will load its initial configuration from this file. "+
+			"Omit this flag to use the default configuration values. "+
+			"Command-line flags override configuration from this file.",
+	)
+	// TODO(2.0.0): remove
 	flagSet.StringVar(&f.MetricsBindAddress,
 		"metrics-addr",
 		":8080",
@@ -57,15 +86,14 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 		":8080",
 		"The address the metric endpoint binds to",
 	)
-	// todo: for Go/Helm the port used is: 8081
+	// TODO(2.0.0): for Go/Helm the port used is: 8081
 	// update it to keep the project aligned to the other
-	// types for 2.0
 	flagSet.StringVar(&f.ProbeAddr,
 		"health-probe-bind-address",
 		":8081",
 		"The address the probe endpoint binds to.",
 	)
-	// todo:remove it for 2.0.0
+	// TODO(2.0.0): remove
 	flagSet.BoolVar(&f.LeaderElection,
 		"enable-leader-election",
 		false,
@@ -91,9 +119,40 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
 			" holding the leader lock (required if running locally with leader"+
 			" election enabled).",
 	)
-	flagSet.IntVar(&f.MaxConcurrentReconciles,
-		"max-concurrent-reconciles",
-		runtime.NumCPU(),
-		"Maximum number of concurrent reconciles for controllers.",
-	)
+}
+
+// ToManagerOptions uses the flag set in f to configure options.
+// Values of options take precedence over flag defaults,
+// as values are assume to have been explicitly set.
+func (f *Flags) ToManagerOptions(options manager.Options) manager.Options {
+	// Alias FlagSet.Changed so options are still updated when fields are empty.
+	changed := func(flagName string) bool {
+		return f.flagSet.Changed(flagName)
+	}
+	if f.flagSet == nil {
+		changed = func(flagName string) bool { return false }
+	}
+
+	// TODO(2.0.0): remove metrics-addr
+	if changed("metrics-bind-address") || changed("metrics-addr") || options.MetricsBindAddress == "" {
+		options.MetricsBindAddress = f.MetricsBindAddress
+	}
+	if changed("health-probe-bind-address") || options.HealthProbeBindAddress == "" {
+		options.HealthProbeBindAddress = f.ProbeAddr
+	}
+	// TODO(2.0.0): remove enable-leader-election
+	if changed("leader-elect") || changed("enable-leader-election") || !options.LeaderElection {
+		options.LeaderElection = f.LeaderElection
+	}
+	if changed("leader-election-id") || options.LeaderElectionID == "" {
+		options.LeaderElectionID = f.LeaderElectionID
+	}
+	if changed("leader-election-namespace") || options.LeaderElectionNamespace == "" {
+		options.LeaderElectionNamespace = f.LeaderElectionNamespace
+	}
+	if options.LeaderElectionResourceLock == "" {
+		options.LeaderElectionResourceLock = resourcelock.ConfigMapsResourceLock
+	}
+
+	return options
 }
diff --git a/internal/plugins/ansible/v1/api.go b/internal/plugins/ansible/v1/api.go
index 89db9c8a..5f1e8d77 100644
--- a/internal/plugins/ansible/v1/api.go
+++ b/internal/plugins/ansible/v1/api.go
@@ -26,6 +26,7 @@ import (
 	pluginutil "sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds"
+	"github.com/operator-framework/operator-sdk/internal/plugins/util"
 )
 
 const (
@@ -135,6 +136,13 @@ func (p *createAPISubcommand) InjectResource(res *resource.Resource) error {
 }
 
 func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
+	if err := util.RemoveKustomizeCRDManifests(); err != nil {
+		return fmt.Errorf("error removing kustomization CRD manifests: %v", err)
+	}
+	if err := util.UpdateKustomizationsCreateAPI(); err != nil {
+		return fmt.Errorf("error updating kustomization.yaml files: %v", err)
+	}
+
 	scaffolder := scaffolds.NewCreateAPIScaffolder(p.config, *p.resource, p.options.DoRole, p.options.DoPlaybook)
 	scaffolder.InjectFS(fs)
 	if err := scaffolder.Scaffold(); err != nil {
diff --git a/internal/plugins/ansible/v1/init.go b/internal/plugins/ansible/v1/init.go
index 8b67e8ab..207c8dd4 100644
--- a/internal/plugins/ansible/v1/init.go
+++ b/internal/plugins/ansible/v1/init.go
@@ -26,6 +26,7 @@ import (
 	"sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds"
+	sdkpluginutil "github.com/operator-framework/operator-sdk/internal/plugins/util"
 	sdkutil "github.com/operator-framework/operator-sdk/internal/util"
 )
 
@@ -109,7 +110,7 @@ func (p *initSubcommand) InjectConfig(c config.Config) error {
 
 func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {
 	if err := addInitCustomizations(p.config.GetProjectName()); err != nil {
-		return fmt.Errorf("unable to scaffold the ansible customizations : %s", err)
+		return fmt.Errorf("error updating init manifests: %s", err)
 	}
 
 	scaffolder := scaffolds.NewInitScaffolder(p.config)
@@ -164,7 +165,8 @@ func addInitCustomizations(projectName string) error {
 	if err != nil {
 		return err
 	}
-	err = sdkutil.InsertCode("config/default/manager_auth_proxy_patch.yaml",
+	managerProxyPatchFile := filepath.Join("config", "default", "manager_auth_proxy_patch.yaml")
+	err = sdkutil.InsertCode(managerProxyPatchFile,
 		"- \"--leader-elect\"",
 		fmt.Sprintf("\n        - \"--leader-election-id=%s\"", projectName))
 	if err != nil {
@@ -203,17 +205,18 @@ func addInitCustomizations(projectName string) error {
 	if err != nil {
 		return err
 	}
-	err = sdkutil.ReplaceInFile("config/default/manager_auth_proxy_patch.yaml", "8081", "6789")
+	err = sdkutil.ReplaceInFile(managerProxyPatchFile, "8081", "6789")
 	if err != nil {
 		return err
 	}
-	err = sdkutil.ReplaceInFile("config/manager/controller_manager_config.yaml", "8081", "6789")
+
+	managerConfigFile := filepath.Join("config", "manager", "controller_manager_config.yaml")
+	err = sdkutil.ReplaceInFile(managerConfigFile, "8081", "6789")
 	if err != nil {
 		return err
 	}
-
 	// Remove the webhook option for the componentConfig since webhooks are not supported by ansible
-	err = sdkutil.ReplaceInFile("config/manager/controller_manager_config.yaml", "webhook:\n  port: 9443", "")
+	err = sdkutil.ReplaceInFile(managerConfigFile, "webhook:\n  port: 9443", "")
 	if err != nil {
 		return err
 	}
@@ -228,5 +231,9 @@ func addInitCustomizations(projectName string) error {
 		return err
 	}
 
+	if err := sdkpluginutil.UpdateKustomizationsInit(); err != nil {
+		return fmt.Errorf("error updating kustomization.yaml files: %v", err)
+	}
+
 	return nil
 }
diff --git a/internal/plugins/ansible/v1/scaffolds/api.go b/internal/plugins/ansible/v1/scaffolds/api.go
index a3529f3d..f6902bf2 100644
--- a/internal/plugins/ansible/v1/scaffolds/api.go
+++ b/internal/plugins/ansible/v1/scaffolds/api.go
@@ -27,7 +27,6 @@ import (
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac"
-	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/molecule/mdefault"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/playbooks"
 	ansibleroles "github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/roles"
@@ -74,22 +73,17 @@ func (s *apiScaffolder) Scaffold() error {
 		machinery.WithResource(&s.resource),
 	)
 
-	var createAPITemplates []machinery.Builder
-	createAPITemplates = append(createAPITemplates,
-		&rbac.CRDViewerRole{},
-		&rbac.CRDEditorRole{},
+	createAPITemplates := []machinery.Builder{
 		&rbac.ManagerRoleUpdater{},
-
 		&crd.CRD{},
 		&crd.Kustomization{},
-		&samples.CR{},
 		&templates.WatchesUpdater{
 			GeneratePlaybook: s.doPlaybook,
 			GenerateRole:     s.doRole,
 			PlaybooksDir:     constants.PlaybooksDir,
 		},
 		&mdefault.ResourceTest{},
-	)
+	}
 
 	if s.doRole {
 		createAPITemplates = append(createAPITemplates,
diff --git a/internal/plugins/ansible/v1/scaffolds/init.go b/internal/plugins/ansible/v1/scaffolds/init.go
index 661585f9..0b3a15d7 100644
--- a/internal/plugins/ansible/v1/scaffolds/init.go
+++ b/internal/plugins/ansible/v1/scaffolds/init.go
@@ -23,7 +23,6 @@ import (
 	"sigs.k8s.io/kubebuilder/v3/pkg/plugins"
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates"
-	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing"
 	"github.com/operator-framework/operator-sdk/internal/plugins/ansible/v1/scaffolds/internal/templates/config/testing/pullpolicy"
@@ -85,10 +84,8 @@ func (s *initScaffolder) Scaffold() error {
 		&templates.RequirementsYml{},
 		&templates.Watches{},
 		&rbac.ManagerRole{},
-		&kdefault.Kustomization{},
 		&roles.Placeholder{},
 		&playbooks.Placeholder{},
-
 		&mdefault.Converge{},
 		&mdefault.Create{},
 		&mdefault.Destroy{},
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go
index 246c5c78..871c00e1 100644
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go
+++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/crd/kustomization.go
@@ -40,11 +40,8 @@ func (f *Kustomization) SetTemplateDefaults() error {
 	if f.Path == "" {
 		f.Path = filepath.Join("config", "crd", "kustomization.yaml")
 	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
 
-	f.TemplateBody = fmt.Sprintf(kustomizationTemplate,
-		machinery.NewMarkerFor(f.Path, resourceMarker),
-	)
+	f.TemplateBody = fmt.Sprintf(kustomizationTemplate, machinery.NewMarkerFor(f.Path, resourceMarker))
 
 	return nil
 }
@@ -53,7 +50,7 @@ const (
 	resourceMarker = "crdkustomizeresource"
 )
 
-// GetMarkers implements file.Inserter
+// GetMarkers implements machinery.Inserter
 func (f *Kustomization) GetMarkers() []machinery.Marker {
 	return []machinery.Marker{
 		machinery.NewMarkerFor(f.Path, resourceMarker),
@@ -65,20 +62,14 @@ const (
 `
 )
 
-// GetCodeFragments implements file.Inserter
+// GetCodeFragments implements machinery.Inserter
 func (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {
-	fragments := make(machinery.CodeFragmentsMap, 3)
-
-	// Generate resource code fragments
-	res := make([]string, 0)
-	res = append(res, fmt.Sprintf(resourceCodeFragment, f.Resource.QualifiedGroup(), f.Resource.Plural))
-
-	// Only store code fragments in the map if the slices are non-empty
-	if len(res) != 0 {
-		fragments[machinery.NewMarkerFor(f.Path, resourceMarker)] = res
+	return machinery.CodeFragmentsMap{
+		// Generate resource code fragments
+		machinery.NewMarkerFor(f.Path, resourceMarker): []string{
+			fmt.Sprintf(resourceCodeFragment, f.Resource.QualifiedGroup(), f.Resource.Plural),
+		},
 	}
-
-	return fragments
 }
 
 var kustomizationTemplate = `# This kustomization.yaml is not intended to be run by itself,
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go
deleted file mode 100644
index 869347d5..00000000
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/kdefault/kustomization.go
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-Copyright 2018 The Kubernetes Authors.
-Modifications 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 kdefault
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &Kustomization{}
-
-// Kustomization scaffolds the kustomization file for the default overlay
-type Kustomization struct {
-	machinery.TemplateMixin
-	machinery.ProjectNameMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *Kustomization) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "default", "kustomization.yaml")
-	}
-
-	f.TemplateBody = kustomizeTemplate
-
-	// For Anible/Helm is no supported webhooks then, we customize
-	// it in the init
-	f.IfExistsAction = machinery.OverwriteFile
-
-	return nil
-}
-
-const kustomizeTemplate = `# Adds namespace to all resources.
-namespace: {{ .ProjectName }}-system
-
-# Value of this field is prepended to the
-# names of all resources, e.g. a deployment named
-# "wordpress" becomes "alices-wordpress".
-# Note that it should also match with the prefix (text before '-') of the namespace
-# field above.
-namePrefix: {{ .ProjectName }}-
-
-# Labels to add to all resources and selectors.
-#commonLabels:
-#  someName: someValue
-
-bases:
-- ../crd
-- ../rbac
-- ../manager
-# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
-#- ../prometheus
-
-patchesStrategicMerge:
-# Protect the /metrics endpoint by putting it behind auth.
-# If you want your controller-manager to expose the /metrics
-# endpoint w/o any authn/z, please comment the following line.
-- manager_auth_proxy_patch.yaml
-`
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go
deleted file mode 100644
index 13a868b8..00000000
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Copyright 2018 The Kubernetes 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 rbac
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &CRDEditorRole{}
-
-// CRDEditorRole scaffolds the config/rbac/<kind>_editor_role.yaml
-type CRDEditorRole struct {
-	machinery.TemplateMixin
-	machinery.ResourceMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *CRDEditorRole) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "rbac", "%[kind]_editor_role.yaml")
-	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
-
-	f.TemplateBody = crdRoleEditorTemplate
-
-	return nil
-}
-
-const crdRoleEditorTemplate = `# permissions for end users to edit {{ .Resource.Plural }}.
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: {{ lower .Resource.Kind }}-editor-role
-rules:
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}
-  verbs:
-  - create
-  - delete
-  - get
-  - list
-  - patch
-  - update
-  - watch
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}/status
-  verbs:
-  - get
-`
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go
deleted file mode 100644
index b0fe36d5..00000000
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Copyright 2018 The Kubernetes 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 rbac
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &CRDViewerRole{}
-
-// CRDViewerRole scaffolds the config/rbac/<kind>_viewer_role.yaml
-type CRDViewerRole struct {
-	machinery.TemplateMixin
-	machinery.ResourceMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *CRDViewerRole) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "rbac", "%[kind]_viewer_role.yaml")
-	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
-
-	f.TemplateBody = crdRoleViewerTemplate
-
-	return nil
-}
-
-const crdRoleViewerTemplate = `# permissions for end users to view {{ .Resource.Plural }}.
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: {{ lower .Resource.Kind }}-viewer-role
-rules:
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}
-  verbs:
-  - get
-  - list
-  - watch
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}/status
-  verbs:
-  - get
-`
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go
index d1e18324..e7cc3bea 100644
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go
+++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/rbac/role.go
@@ -38,9 +38,8 @@ func (f *ManagerRole) SetTemplateDefaults() error {
 		f.Path = defaultRoleFile
 	}
 
-	f.TemplateBody = fmt.Sprintf(roleTemplate,
-		machinery.NewMarkerFor(f.Path, rulesMarker),
-	)
+	f.TemplateBody = fmt.Sprintf(roleTemplate, machinery.NewMarkerFor(f.Path, rulesMarker))
+
 	return nil
 }
 
diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go
deleted file mode 100644
index 54156fa9..00000000
--- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/samples/cr_sample.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-Copyright 2018 The Kubernetes Authors.
-Modifications 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 samples
-
-import (
-	"path/filepath"
-	"strings"
-	"text/template"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var (
-	_ machinery.Template         = &CR{}
-	_ machinery.UseCustomFuncMap = &CR{}
-)
-
-// CR scaffolds a sample manifest for a CRD.
-type CR struct {
-	machinery.TemplateMixin
-	machinery.ResourceMixin
-
-	Spec string
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *CR) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "samples", "%[group]_%[version]_%[kind].yaml")
-	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
-
-	f.IfExistsAction = machinery.Error
-
-	if len(f.Spec) == 0 {
-		f.Spec = defaultSpecTemplate
-	}
-
-	f.TemplateBody = crSampleTemplate
-	return nil
-}
-
-func indent(spaces int, v string) string {
-	pad := strings.Repeat(" ", spaces)
-	return pad + strings.Replace(v, "\n", "\n"+pad, -1)
-}
-
-// GetFuncMap implements machinery.UseCustomFuncMap
-func (f *CR) GetFuncMap() template.FuncMap {
-	fm := machinery.DefaultFuncMap()
-	fm["indent"] = indent
-	return fm
-}
-
-const defaultSpecTemplate = `foo: bar`
-
-const crSampleTemplate = `apiVersion: {{ .Resource.QualifiedGroup }}/{{ .Resource.Version }}
-kind: {{ .Resource.Kind }}
-metadata:
-  name: {{ lower .Resource.Kind }}-sample
-spec:
-{{ .Spec | indent 2 }}
-`
diff --git a/internal/plugins/helm/v1/api.go b/internal/plugins/helm/v1/api.go
index 1403be1b..9191ea57 100644
--- a/internal/plugins/helm/v1/api.go
+++ b/internal/plugins/helm/v1/api.go
@@ -30,6 +30,7 @@ import (
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil"
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds"
+	"github.com/operator-framework/operator-sdk/internal/plugins/util"
 )
 
 const (
@@ -200,6 +201,13 @@ func (p *createAPISubcommand) InjectResource(res *resource.Resource) error {
 }
 
 func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
+	if err := util.RemoveKustomizeCRDManifests(); err != nil {
+		return fmt.Errorf("error removing kustomization CRD manifests: %v", err)
+	}
+	if err := util.UpdateKustomizationsCreateAPI(); err != nil {
+		return fmt.Errorf("error updating kustomization.yaml files: %v", err)
+	}
+
 	scaffolder := scaffolds.NewAPIScaffolder(p.config, *p.resource, p.chart)
 	scaffolder.InjectFS(fs)
 	if err := scaffolder.Scaffold(); err != nil {
diff --git a/internal/plugins/helm/v1/init.go b/internal/plugins/helm/v1/init.go
index d86be6d8..bb5bdae7 100644
--- a/internal/plugins/helm/v1/init.go
+++ b/internal/plugins/helm/v1/init.go
@@ -26,6 +26,7 @@ import (
 	"sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds"
+	sdkpluginutil "github.com/operator-framework/operator-sdk/internal/plugins/util"
 	sdkutil "github.com/operator-framework/operator-sdk/internal/util"
 )
 
@@ -131,7 +132,7 @@ func (p *initSubcommand) InjectConfig(c config.Config) error {
 
 func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {
 	if err := addInitCustomizations(p.config.GetProjectName()); err != nil {
-		return fmt.Errorf("unable to scaffold the helm customizations : %s", err)
+		return fmt.Errorf("error updating init manifests: %s", err)
 	}
 
 	scaffolder := scaffolds.NewInitScaffolder(p.config)
@@ -190,8 +191,7 @@ func addInitCustomizations(projectName string) error {
 	if err != nil {
 		return err
 	}
-
-	err = sdkutil.InsertCode("config/default/manager_auth_proxy_patch.yaml",
+	err = sdkutil.InsertCode(filepath.Join("config", "default", "manager_auth_proxy_patch.yaml"),
 		"- \"--leader-elect\"",
 		fmt.Sprintf("\n        - \"--leader-election-id=%s\"", projectName))
 	if err != nil {
@@ -208,8 +208,9 @@ func addInitCustomizations(projectName string) error {
 		return err
 	}
 
-	// Remove the webhook option for the componentConfig since webhooks are not supported by helm
-	err = sdkutil.ReplaceInFile("config/manager/controller_manager_config.yaml", "webhook:\n  port: 9443", "")
+	// Remove the webhook option for the componentConfig since webhooks are not supported by ansible
+	err = sdkutil.ReplaceInFile(filepath.Join("config", "manager", "controller_manager_config.yaml"),
+		"webhook:\n  port: 9443", "")
 	if err != nil {
 		return err
 	}
@@ -224,5 +225,9 @@ func addInitCustomizations(projectName string) error {
 		return err
 	}
 
+	if err := sdkpluginutil.UpdateKustomizationsInit(); err != nil {
+		return fmt.Errorf("error updating kustomization.yaml files: %v", err)
+	}
+
 	return nil
 }
diff --git a/internal/plugins/helm/v1/scaffolds/api.go b/internal/plugins/helm/v1/scaffolds/api.go
index 536864be..194668f5 100644
--- a/internal/plugins/helm/v1/scaffolds/api.go
+++ b/internal/plugins/helm/v1/scaffolds/api.go
@@ -93,10 +93,8 @@ func (s *apiScaffolder) Scaffold() error {
 		&templates.WatchesUpdater{ChartPath: chartPath},
 		&crd.CRD{},
 		&crd.Kustomization{},
-		&rbac.CRDEditorRole{},
-		&rbac.CRDViewerRole{},
 		&rbac.ManagerRoleUpdater{Chart: s.chrt},
-		&samples.CRDSample{ChartPath: chartPath, Chart: s.chrt},
+		&samples.CustomResource{ChartPath: chartPath, Chart: s.chrt},
 	); err != nil {
 		return fmt.Errorf("error scaffolding APIs: %w", err)
 	}
diff --git a/internal/plugins/helm/v1/scaffolds/init.go b/internal/plugins/helm/v1/scaffolds/init.go
index 69e2c77c..c1a7eec5 100644
--- a/internal/plugins/helm/v1/scaffolds/init.go
+++ b/internal/plugins/helm/v1/scaffolds/init.go
@@ -26,7 +26,6 @@ import (
 
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil"
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates"
-	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault"
 	"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac"
 	"github.com/operator-framework/operator-sdk/internal/version"
 )
@@ -86,6 +85,5 @@ func (s *initScaffolder) Scaffold() error {
 		},
 		&templates.Watches{},
 		&rbac.ManagerRole{},
-		&kdefault.Kustomization{},
 	)
 }
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go
index 246c5c78..871c00e1 100644
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go
+++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go
@@ -40,11 +40,8 @@ func (f *Kustomization) SetTemplateDefaults() error {
 	if f.Path == "" {
 		f.Path = filepath.Join("config", "crd", "kustomization.yaml")
 	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
 
-	f.TemplateBody = fmt.Sprintf(kustomizationTemplate,
-		machinery.NewMarkerFor(f.Path, resourceMarker),
-	)
+	f.TemplateBody = fmt.Sprintf(kustomizationTemplate, machinery.NewMarkerFor(f.Path, resourceMarker))
 
 	return nil
 }
@@ -53,7 +50,7 @@ const (
 	resourceMarker = "crdkustomizeresource"
 )
 
-// GetMarkers implements file.Inserter
+// GetMarkers implements machinery.Inserter
 func (f *Kustomization) GetMarkers() []machinery.Marker {
 	return []machinery.Marker{
 		machinery.NewMarkerFor(f.Path, resourceMarker),
@@ -65,20 +62,14 @@ const (
 `
 )
 
-// GetCodeFragments implements file.Inserter
+// GetCodeFragments implements machinery.Inserter
 func (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {
-	fragments := make(machinery.CodeFragmentsMap, 3)
-
-	// Generate resource code fragments
-	res := make([]string, 0)
-	res = append(res, fmt.Sprintf(resourceCodeFragment, f.Resource.QualifiedGroup(), f.Resource.Plural))
-
-	// Only store code fragments in the map if the slices are non-empty
-	if len(res) != 0 {
-		fragments[machinery.NewMarkerFor(f.Path, resourceMarker)] = res
+	return machinery.CodeFragmentsMap{
+		// Generate resource code fragments
+		machinery.NewMarkerFor(f.Path, resourceMarker): []string{
+			fmt.Sprintf(resourceCodeFragment, f.Resource.QualifiedGroup(), f.Resource.Plural),
+		},
 	}
-
-	return fragments
 }
 
 var kustomizationTemplate = `# This kustomization.yaml is not intended to be run by itself,
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go
deleted file mode 100644
index 42e9e380..00000000
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/kdefault/kustomization.go
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-Copyright 2018 The Kubernetes Authors.
-Modifications 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 kdefault
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &Kustomization{}
-
-// Kustomization scaffolds the Kustomization file for the default overlay
-type Kustomization struct {
-	machinery.TemplateMixin
-	machinery.ProjectNameMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *Kustomization) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "default", "kustomization.yaml")
-	}
-
-	f.TemplateBody = kustomizeTemplate
-
-	// For Anible/Helm is no supported webhooks then, we customize
-	// it in the init
-	f.IfExistsAction = machinery.OverwriteFile
-
-	return nil
-}
-
-const kustomizeTemplate = `# Adds namespace to all resources.
-namespace: {{ .ProjectName }}-system
-
-# Value of this field is prepended to the
-# names of all resources, e.g. a deployment named
-# "wordpress" becomes "alices-wordpress".
-# Note that it should also match with the prefix (text before '-') of the namespace
-# field above.
-namePrefix: {{ .ProjectName }}-
-
-# Labels to add to all resources and selectors.
-#commonLabels:
-#  someName: someValue
-
-bases:
-- ../crd
-- ../rbac
-- ../manager
-# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
-#- ../prometheus
-
-patchesStrategicMerge:
-# Protect the /metrics endpoint by putting it behind auth.
-# If you want your controller-manager to expose the /metrics
-# endpoint w/o any authn/z, please comment the following line.
-- manager_auth_proxy_patch.yaml
-`
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go
deleted file mode 100644
index 13a868b8..00000000
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_editor_rbac.go
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Copyright 2018 The Kubernetes 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 rbac
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &CRDEditorRole{}
-
-// CRDEditorRole scaffolds the config/rbac/<kind>_editor_role.yaml
-type CRDEditorRole struct {
-	machinery.TemplateMixin
-	machinery.ResourceMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *CRDEditorRole) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "rbac", "%[kind]_editor_role.yaml")
-	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
-
-	f.TemplateBody = crdRoleEditorTemplate
-
-	return nil
-}
-
-const crdRoleEditorTemplate = `# permissions for end users to edit {{ .Resource.Plural }}.
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: {{ lower .Resource.Kind }}-editor-role
-rules:
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}
-  verbs:
-  - create
-  - delete
-  - get
-  - list
-  - patch
-  - update
-  - watch
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}/status
-  verbs:
-  - get
-`
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go
deleted file mode 100644
index b0fe36d5..00000000
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/crd_viewer_rbac.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Copyright 2018 The Kubernetes 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 rbac
-
-import (
-	"path/filepath"
-
-	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
-)
-
-var _ machinery.Template = &CRDViewerRole{}
-
-// CRDViewerRole scaffolds the config/rbac/<kind>_viewer_role.yaml
-type CRDViewerRole struct {
-	machinery.TemplateMixin
-	machinery.ResourceMixin
-}
-
-// SetTemplateDefaults implements machinery.Template
-func (f *CRDViewerRole) SetTemplateDefaults() error {
-	if f.Path == "" {
-		f.Path = filepath.Join("config", "rbac", "%[kind]_viewer_role.yaml")
-	}
-	f.Path = f.Resource.Replacer().Replace(f.Path)
-
-	f.TemplateBody = crdRoleViewerTemplate
-
-	return nil
-}
-
-const crdRoleViewerTemplate = `# permissions for end users to view {{ .Resource.Plural }}.
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
-  name: {{ lower .Resource.Kind }}-viewer-role
-rules:
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}
-  verbs:
-  - get
-  - list
-  - watch
-- apiGroups:
-  - {{ .Resource.QualifiedGroup }}
-  resources:
-  - {{ .Resource.Plural }}/status
-  verbs:
-  - get
-`
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go
index a3ee2b51..e5140183 100644
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go
+++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go
@@ -51,9 +51,8 @@ func (f *ManagerRole) SetTemplateDefaults() error {
 		f.Path = defaultRoleFile
 	}
 
-	f.TemplateBody = fmt.Sprintf(roleTemplate,
-		machinery.NewMarkerFor(f.Path, rulesMarker),
-	)
+	f.TemplateBody = fmt.Sprintf(roleTemplate, machinery.NewMarkerFor(f.Path, rulesMarker))
+
 	return nil
 }
 
diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/custom_resource.go
similarity index 80%
rename from internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go
rename to internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/custom_resource.go
index 04aa6627..ec757433 100644
--- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/crd_sample.go
+++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/custom_resource.go
@@ -29,12 +29,12 @@ import (
 )
 
 var (
-	_ machinery.Template         = &CRDSample{}
-	_ machinery.UseCustomFuncMap = &CRDSample{}
+	_ machinery.Template         = &CustomResource{}
+	_ machinery.UseCustomFuncMap = &CustomResource{}
 )
 
-// CRDSample scaffolds a manifest for CRD sample.
-type CRDSample struct {
+// CustomResource scaffolds a custom resource sample manifest.
+type CustomResource struct {
 	machinery.TemplateMixin
 	machinery.ResourceMixin
 
@@ -44,13 +44,13 @@ type CRDSample struct {
 }
 
 // SetTemplateDefaults implements machinery.Template
-func (f *CRDSample) SetTemplateDefaults() error {
+func (f *CustomResource) SetTemplateDefaults() error {
 	if f.Path == "" {
 		f.Path = filepath.Join("config", "samples", "%[group]_%[version]_%[kind].yaml")
 	}
 	f.Path = f.Resource.Replacer().Replace(f.Path)
 
-	f.IfExistsAction = machinery.Error
+	f.IfExistsAction = machinery.OverwriteFile
 
 	if len(f.Spec) == 0 {
 		f.Spec = defaultSpecTemplate
@@ -67,7 +67,7 @@ func (f *CRDSample) SetTemplateDefaults() error {
 		}
 	}
 
-	f.TemplateBody = crdSampleTemplate
+	f.TemplateBody = customResourceTemplate
 	return nil
 }
 
@@ -77,7 +77,7 @@ func indent(spaces int, v string) string {
 }
 
 // GetFuncMap implements machinery.UseCustomFuncMap
-func (f *CRDSample) GetFuncMap() template.FuncMap {
+func (f *CustomResource) GetFuncMap() template.FuncMap {
 	fm := machinery.DefaultFuncMap()
 	fm["indent"] = indent
 	return fm
@@ -86,7 +86,7 @@ func (f *CRDSample) GetFuncMap() template.FuncMap {
 const defaultSpecTemplate = `foo: bar
 `
 
-const crdSampleTemplate = `apiVersion: {{ .Resource.QualifiedGroup }}/{{ .Resource.Version }}
+const customResourceTemplate = `apiVersion: {{ .Resource.QualifiedGroup }}/{{ .Resource.Version }}
 kind: {{ .Resource.Kind }}
 metadata:
   name: {{ lower .Resource.Kind }}-sample
diff --git a/internal/plugins/util/cleanup.go b/internal/plugins/util/cleanup.go
new file mode 100644
index 00000000..0bda6c13
--- /dev/null
+++ b/internal/plugins/util/cleanup.go
@@ -0,0 +1,139 @@
+// Copyright 2021 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 util
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+
+	log "github.com/sirupsen/logrus"
+
+	"github.com/operator-framework/operator-sdk/internal/util"
+)
+
+// RemoveKustomizeCRDManifests removes items in config/crd relating to CRD conversion webhooks.
+func RemoveKustomizeCRDManifests() error {
+
+	pathsToRemove := []string{
+		filepath.Join("config", "crd", "kustomizeconfig.yaml"),
+	}
+	configPatchesDir := filepath.Join("config", "crd", "patches")
+	webhookPatchMatches, err := filepath.Glob(filepath.Join(configPatchesDir, "webhook_in_*.yaml"))
+	if err != nil {
+		return err
+	}
+	pathsToRemove = append(pathsToRemove, webhookPatchMatches...)
+	cainjectionPatchMatches, err := filepath.Glob(filepath.Join(configPatchesDir, "cainjection_in_*.yaml"))
+	if err != nil {
+		return err
+	}
+	pathsToRemove = append(pathsToRemove, cainjectionPatchMatches...)
+	for _, p := range pathsToRemove {
+		if err := os.RemoveAll(p); err != nil {
+			return err
+		}
+	}
+	children, err := ioutil.ReadDir(configPatchesDir)
+	if err == nil && len(children) == 0 {
+		if err := os.RemoveAll(configPatchesDir); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// UpdateKustomizationsInit updates certain parts of or removes entire kustomization.yaml files
+// that are either not used by certain Init plugins or are created by preceding Init plugins.
+func UpdateKustomizationsInit() error {
+
+	defaultKFile := filepath.Join("config", "default", "kustomization.yaml")
+	if err := util.ReplaceInFile(defaultKFile,
+		`
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+#- ../webhook
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
+#- ../certmanager`, ""); err != nil {
+		return fmt.Errorf("remove %s resources: %v", defaultKFile, err)
+	}
+
+	if err := util.ReplaceInFile(defaultKFile,
+		`
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+#- manager_webhook_patch.yaml
+
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
+# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
+# 'CERTMANAGER' needs to be enabled to use ca injection
+#- webhookcainjection_patch.yaml
+
+# the following config is for teaching kustomize how to do var substitution
+vars:
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
+#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
+#  objref:
+#    kind: Certificate
+#    group: cert-manager.io
+#    version: v1
+#    name: serving-cert # this name should match the one in certificate.yaml
+#  fieldref:
+#    fieldpath: metadata.namespace
+#- name: CERTIFICATE_NAME
+#  objref:
+#    kind: Certificate
+#    group: cert-manager.io
+#    version: v1
+#    name: serving-cert # this name should match the one in certificate.yaml
+#- name: SERVICE_NAMESPACE # namespace of the service
+#  objref:
+#    kind: Service
+#    version: v1
+#    name: webhook-service
+#  fieldref:
+#    fieldpath: metadata.namespace
+#- name: SERVICE_NAME
+#  objref:
+#    kind: Service
+#    version: v1
+#    name: webhook-service
+`, ""); err != nil {
+		return fmt.Errorf("remove %s patch and vars blocks: %v", defaultKFile, err)
+	}
+
+	return nil
+}
+
+// UpdateKustomizationsCreateAPI updates certain parts of or removes entire kustomization.yaml files
+// that are either not used by certain CreateAPI plugins or are created by preceding CreateAPI plugins.
+func UpdateKustomizationsCreateAPI() error {
+
+	crdKFile := filepath.Join("config", "crd", "kustomization.yaml")
+	if crdKBytes, err := ioutil.ReadFile(crdKFile); err != nil && !errors.Is(err, os.ErrNotExist) {
+		log.Debugf("Error reading kustomization for substitution: %v", err)
+	} else if err == nil {
+		if bytes.Contains(crdKBytes, []byte("[WEBHOOK]")) || bytes.Contains(crdKBytes, []byte("[CERTMANAGER]")) {
+			if err := os.RemoveAll(crdKFile); err != nil {
+				log.Debugf("Error removing file prior to scaffold: %v", err)
+			}
+		}
+	}
+
+	return nil
+}
diff --git a/release/Makefile b/release/Makefile
index cd7da91a..15a404b1 100644
--- a/release/Makefile
+++ b/release/Makefile
@@ -24,7 +24,7 @@ release: ## Publish an operator-sdk release, with option for a dry run with DRY_
 ifeq (,$(GIT_VERSION))
 	$(error "GIT_VERSION must be set to a git tag")
 endif
-	$(SCRIPTS_DIR)/fetch goreleaser 0.147.2
+	$(SCRIPTS_DIR)/fetch goreleaser 0.156.0
 	GORELEASER_CURRENT_TAG=$(GIT_VERSION) $(TOOLS_DIR)/goreleaser $(SNAPSHOT_FLAGS) --release-notes=$(CHANGELOG) --parallelism 5
 ifneq ($(DRY_RUN),)
 	rm $(CHANGELOG)
diff --git a/website/config.toml b/website/config.toml
index 74ce4bdd..52f7410e 100644
--- a/website/config.toml
+++ b/website/config.toml
@@ -95,6 +95,10 @@ algolia_docsearch = true
 
 ##RELEASE_ADDME##
 
+[[params.versions]]
+  version = "v1.6"
+  url = "https://v1-6-x.sdk.operatorframework.io"
+
 [[params.versions]]
   version = "v1.5"
   url = "https://v1-5-x.sdk.operatorframework.io"
diff --git a/website/content/en/docs/advanced-topics/scorecard/scorecard.md b/website/content/en/docs/advanced-topics/scorecard/scorecard.md
index 99c1a393..17a4ec13 100644
--- a/website/content/en/docs/advanced-topics/scorecard/scorecard.md
+++ b/website/content/en/docs/advanced-topics/scorecard/scorecard.md
@@ -52,8 +52,8 @@ for an overview of command invocation.
 ## Configuration
 
 The scorecard test execution is driven by a configuration file named `config.yaml`, generated by `make bundle`.  Note that if run `make bundle` that any
-changes you have made to `config.yaml` will be overwritten.  To persist 
-any changes to `config.yaml` you can update the kustomize templates found in the 
+changes you have made to `config.yaml` will be overwritten.  To persist
+any changes to `config.yaml` you can update the kustomize templates found in the
 `config/scorecard` directory.
 The configuration file is located at the following location within your bundle directory (`bundle/` by default):
 ```sh
@@ -114,7 +114,7 @@ $ operator-sdk scorecard <bundle_dir_or_image> [flags]
 
 The scorecard requires a positional argument that holds either the
 on-disk path to your operator bundle or the name of a bundle image.  Note
-that the scorecard does not run your operator but merely uses 
+that the scorecard does not run your operator but merely uses
 the scorecard configuration within the bundle contents to know which tests
 to execute.
 
@@ -180,7 +180,7 @@ The scorecard ships with pre-defined tests that are arranged into suites.
 | --------    | -------- | -------- |
 | Bundle Validation | This test validates the bundle manifests found in the bundle that is passed into scorecard.  If the bundle contents contain errors, then the test result output will include the validator log as well as error messages from the validation library.  See this [document][olm-bundle] for details on bundles.| olm-bundle-validation-test |
 | Provided APIs have validation |This test verifies that the CRDs for the provided CRs contain a validation section and that there is validation for each spec and status field detected in the CR. | olm-crds-have-validation-test |
-| Owned CRDs Have Resources Listed | This test makes sure that the CRDs for each CR provided via the `cr-manifest` option have a `resources` subsection in the [`owned` CRDs section][owned-crds] of the CSV. If the test detects used resources that are not listed in the resources section, it will list them in the suggestions at the end of the test. Users are required to fill out the resources section after initial code generation for this test to pass.  | olm-crds-have-resources-test |
+| Owned CRDs Have Resources Listed | This test makes sure that the CRDs for each CR provided via the `cr-manifest` option have a `resources` subsection in the [`owned` CRDs section][owned-crds] of the CSV. If the test detects used resources that are not listed in the resources section, it will list them in the suggestions at the end of the test. Users are required to fill out the resources section after initial code generation for this test to pass. For Go-based operators, use ClusterServiceVersion [API Markers](/docs/building-operators/golang/references/markers) to add resources. | olm-crds-have-resources-test |
 | Spec Fields With Descriptors | This test verifies that every field in the Custom Resources' spec sections have a corresponding descriptor listed in the CSV.| olm-spec-descriptors-test |
 | Status Fields With Descriptors | This test verifies that every field in the Custom Resources' status sections have a corresponding descriptor listed in the CSV.| olm-status-descriptors-test |
 
diff --git a/website/content/en/docs/building-operators/golang/references/markers.md b/website/content/en/docs/building-operators/golang/references/markers.md
index 7e395e10..7d14a68d 100644
--- a/website/content/en/docs/building-operators/golang/references/markers.md
+++ b/website/content/en/docs/building-operators/golang/references/markers.md
@@ -112,7 +112,7 @@ These examples assume `Memcached`, `MemcachedSpec`, and `MemcachedStatus` are th
 	type MemcachedPods struct {
 		// Size is the size of the memcached deployment.
 		//+operator-sdk:csv:customresourcedefinitions:type=spec
-		//+operator-sdk:csv:customresourcedefinitions.type=status
+		//+operator-sdk:csv:customresourcedefinitions:type=status
 		Size int32 `json:"size"`
 	}
 	```
diff --git a/website/content/en/docs/contribution-guidelines/documentation.md b/website/content/en/docs/contribution-guidelines/documentation.md
index 4ee2a7a9..04f31a26 100644
--- a/website/content/en/docs/contribution-guidelines/documentation.md
+++ b/website/content/en/docs/contribution-guidelines/documentation.md
@@ -33,12 +33,10 @@ hugo server
 
 Any changes will be included in real time.
 
-
 ## Check Docs
 
 `make test-docs` will validate changelog fragments, build doc HTML in a container, and check its links.
 Please consider running this locally before creating a PR to save CI resources.
 
-
 [hugo]:https://gohugo.io/
 [docsy-install]:https://www.docsy.dev/docs/getting-started/#prerequisites-and-installation
diff --git a/website/content/en/docs/contribution-guidelines/plugins.md b/website/content/en/docs/contribution-guidelines/plugins.md
new file mode 100644
index 00000000..e8ab3392
--- /dev/null
+++ b/website/content/en/docs/contribution-guidelines/plugins.md
@@ -0,0 +1,80 @@
+---
+title: Plugins
+linkTitle: Plugins
+weight: 7
+---
+
+## Overview
+
+SDK uses the project [Kubebuilder][kubebuilder] as a library for the CLI and plugins features. For further information see the [Plugins][kb-plugins-doc] document. To better understand its motivations, check the design documentation [Integrating Kubebuilder and Operator SDK][kb-int-sdk].
+
+## SDK Language-based plugins
+
+All language-based operator projects provided by SDK (Ansible/Helm/Golang) follow the Kubebuilder standard and have a common base. The common base is generated using [kustomize][kustomize] which is a project maintained and adopted by Kubernetes community to help work with the Kubernertes manifests (YAML files) that are used to configure the resources on the clusters.
+
+The specific files for each language are scaffolded for the language's plugins. The Operator SDK CLI tool can provide custom plugins and helpers which are common and useful for all language types. To check the common base, you can also run:
+
+```sh
+operator-sdk init --plugins=kustomize
+```
+
+Also, see the topic [Language-based Plugins][kb-language-plugins] to understand how it works.
+
+### Common scaffolds 
+
+Following the default common scaffolds for the projects which are built with SDK.
+
+| File/Directory | Description | 
+| ------ | ----- |
+|  Dockerfile |  Defines the operator(manager) image |  
+|  Makefile |  Provides the helpers and options for the users. (e.g. `make bundle` which generate/update the OLM [bundle][bundle] manifests ) |  
+|  PROJECT |  Project configuration. Stores the data used to do the scaffolds. For further information see [Project Config][kb-project] | 
+|  bundle.Dockerfile | Docker image which is used to provide the helpers to integrate the project with OLM. (e.g. [operator-sdk run ./bundle][sdk-cli-run-bundle]) | 
+|  config/ |  Directory which has all [kustomize's][kustomize] manifest to configure and test the project | 
+
+You can check the [Project Layout][project-layout] to better understand the files and directories scaffolded by SDK CLI, which may be common for each language-type.
+
+## Custom Plugins
+
+By default plugins are used by the Operator SDK to provide the following features:
+
+- [manifests.sdk.operatorframework.io][plugin-manifest]: perform the required scaffolds to provide the helpers to allow the projects to be integrated with OLM. 
+- [scorecard.sdk.operatorframework.io][plugin-scorecard]: perform the required scaffolds to provide the [Scorecard][scorecard] feature.
+
+### Optional/custom plugins
+
+Users can also use custom plugins when they execute the SDK CLI sub-commands as a helper which includes the following options:
+
+```sh
+operator-sdk create api --plugins="go/v3,declarative"
+```
+
+The above example will scaffold custom code in the controllers after an API is created to allow the users to develop solutions using the [kubebuilder declarative pattern][kubebuilder-declarative-pattern]. (e.g [default scaffold][default-scaffold] versus [example][kubebuilder-declarative-pattern-example]).
+
+Note that custom plugins are called via the init sub-command to work as global plugins, and will be added in the `layout` field of the PROJECT file. Any sub-command executed will then also be called.
+
+## Plugins Vision
+
+Maintainers and contributors are able to create their own plugin(s) using the same standards and approaches. These contributions in the future could be added as solutions to be compatible and used with the Operator SDK CLI. Currently, the SDK cannot discover and use plugins that are not shipped or built with its binary. However, it has been discussed in the issue [kubebuilder/issues/1378][kb-issue].
+
+## How to create your own plugins
+
+If you are looking to develop similar solutions to allow users for example to create projects using other languages or that could work as helpers for the projects built with SDK/Kubebuilder projects, then see the [Creating your own plugins][create-your-own-plugins] to see how you can benefit and apply this approach.
+
+[kb-plugins-doc]: https://master.book.kubebuilder.io/plugins/plugins.html
+[kb-int-sdk]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md
+[kb-language-plugins]:https://master.book.kubebuilder.io/plugins/creating-plugins.html#language-based-plugins
+[kustomize]: https://github.com/kubernetes-sigs/kustomize
+[bundle]: https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#operator-bundle
+[kb-project]: https://master.book.kubebuilder.io/reference/project-config.html
+[sdk-cli-run-bundle]: /docs/cli/operator-sdk_run
+[project-layout]: /docs/overview/project-layout
+[plugin-manifest]: https://github.com/operator-framework/operator-sdk/tree/master/internal/plugins/manifests/v2
+[plugin-scorecard]: https://github.com/operator-framework/operator-sdk/tree/master/internal/plugins/scorecard/v2
+[kubebuilder-declarative-pattern]: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern
+[kubebuilder-declarative-pattern-example]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/testdata/project-v3/controllers/firstmate_controller.go
+[default-scaffold]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/testdata/project-v3/controllers/admiral_controller.go
+[kb-issue]: https://github.com/kubernetes-sigs/kubebuilder/issues/1378
+[create-your-own-plugins]: https://master.book.kubebuilder.io/plugins/creating-plugins.html
+[scorecard]: /docs/advanced-topics/scorecard/scorecard/
+[kubebuilder]: https://github.com/kubernetes-sigs/kubebuilder 
diff --git a/website/content/en/docs/contribution-guidelines/releasing.md b/website/content/en/docs/contribution-guidelines/releasing.md
index 715111f3..0a596c18 100644
--- a/website/content/en/docs/contribution-guidelines/releasing.md
+++ b/website/content/en/docs/contribution-guidelines/releasing.md
@@ -1,7 +1,7 @@
 ---
 title: Release Guide
 linkTitle: Releasing
-weight: 30
+weight: 4
 ---
 
 These steps describe how to conduct a release of the operator-sdk repo using example versions.
diff --git a/website/content/en/docs/contribution-guidelines/reporting-issues.md b/website/content/en/docs/contribution-guidelines/reporting-issues.md
index 7ea456bd..52cd02f9 100644
--- a/website/content/en/docs/contribution-guidelines/reporting-issues.md
+++ b/website/content/en/docs/contribution-guidelines/reporting-issues.md
@@ -1,7 +1,7 @@
 ---
 title: Reporting Issues
 linkTitle: Reporting Issues
-weight: 40
+weight: 5
 ---
 
 If any part of the operator-sdk project has bugs or documentation mistakes, please let us know by [opening an issue][operator-sdk-issue]. We treat bugs and mistakes very seriously and believe no issue is too small. Before creating a bug report, please check that an issue reporting the same problem does not already exist.
diff --git a/website/content/en/docs/installation/_index.md b/website/content/en/docs/installation/_index.md
index 6b162acd..cab1dc97 100644
--- a/website/content/en/docs/installation/_index.md
+++ b/website/content/en/docs/installation/_index.md
@@ -36,7 +36,7 @@ export OS=$(uname | awk '{print tolower($0)}')
 Download the binary for your platform:
 
 ```sh
-export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/v1.5.0
+export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.6.1
 curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}
 ```
 
diff --git a/website/content/en/docs/upgrading-sdk-version/v1.6.0.md b/website/content/en/docs/upgrading-sdk-version/v1.6.0.md
new file mode 100644
index 00000000..490a793b
--- /dev/null
+++ b/website/content/en/docs/upgrading-sdk-version/v1.6.0.md
@@ -0,0 +1,278 @@
+---
+title: v1.6.0
+weight: 998994000
+---
+
+## (ansible/v1, helm/v1) Optional: configure `ansible-operator` and `helm-operator` with a component config.
+
+To add this option your project you will need to: 
+- Create the file [config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/default/manager_config_patch.yaml). 
+- Create the file [config/manager/controller_manager_config.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/manager/controller_manager_config.yaml). 
+- Update the `config/default/kustomization.yaml` by adding the following to `resources`:
+  ```yaml
+  resources:
+  ...
+  - manager_config_patch.yaml
+  ```
+- Update the `config/manager/kustomization.yaml` by adding:
+```yaml
+  generatorOptions:
+    disableNameSuffixHash: true
+
+  configMapGenerator:
+  - files:
+    - controller_manager_config.yaml
+    name: manager-config
+  apiVersion: kustomize.config.k8s.io/v1beta1
+  kind: Kustomization
+  images:
+  - name: controller
+    newName: quay.io/example/memcached-operator
+    newTag: v0.0.1
+```
+
+_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._
+
+## (ansible/v1, helm/v1) Add Role rules for leader election.
+
+Add the rule for the `apiGroups` `coordination.k8s.io` and the resource `leases` in config/rbac/leader_election_role.yaml:
+```yaml
+rules:
+  - apiGroups:
+      - ""
+      - coordination.k8s.io
+    resources:
+      - configmaps
+      - leases
+```
+
+_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._
+
+## (ansible/v1) Update Ansible collections
+
+In your requirements.yml, change the `version` field for community.kubernetes to `1.2.1`, and the `version` field for `operator_sdk.util` to `0.2.0`.
+
+_See [#4734](https://github.com/operator-framework/operator-sdk/pull/4734) for more details._
+
+## (helm/v1) Replace deprecated leader election and metrics address flags
+
+Replace deprecated flags `--enable-leader-election` and `--metrics-addr` with `--leader-elect` and `--metrics-bind-address`, respectively.
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
+
+Add the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:
+```yaml
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        args:
+        - "--health-probe-bind-address=:8081"
+        ...
+```
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
+
+Add the arg `--health-probe-bind-address=:6789` to the `config/default/manager_auth_proxy_patch.yaml`:
+```yaml
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        args:
+        - "--health-probe-bind-address=:6789"
+        ...
+```
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (helm/v1, ansible/v1) Add `help` target to Makefile.
+
+Ansible/Helm projects now provide a Makefile `help` target, similar to a `--help` flag. You can copy and paste this target from the relevant sample's Makefile ([helm](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/helm/memcached-operator/Makefile), [ansible](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/ansible/memcached-operator/Makefile)).
+
+_See [#4660](https://github.com/operator-framework/operator-sdk/pull/4660) for more details._
+
+## (ansible/v1, helm/v1) Add `securityContext`'s to your manager's Deployment.
+
+In `config/manager/manager.yaml`, add the following security contexts:
+```yaml
+spec:
+  ...
+  template:
+    ...
+    spec:
+      securityContext:
+        runAsNonRoot: true
+      containers:
+      - name: manager
+        securityContext:
+          allowPrivilegeEscalation: false
+```
+
+_See [#4655](https://github.com/operator-framework/operator-sdk/pull/4655) for more details._
+
+## (manifests/v2) Add a kustomize patch to remove the cert-manager volume/volumeMount from your CSV
+
+OLM does [not yet support cert-manager](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements), so a JSON patch was added to remove this volume and mount such that OLM can itself create and manage certs for your Operator.
+In `config/manifests/kustomization.yaml`, add the following:
+```yaml
+patchesJson6902: 
+- target:
+    group: apps
+    version: v1
+    kind: Deployment
+    name: controller-manager
+    namespace: system
+  patch: |-
+    # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs.
+    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.
+    - op: remove
+      path: /spec/template/spec/containers/1/volumeMounts/0
+    # Remove the "cert" volume, since OLM will create and mount a set of certs.
+    # Update the indices in this path if adding or removing volumes in the manager's Deployment.
+    - op: remove
+      path: /spec/template/spec/volumes/0
+```
+
+_See [#4623](https://github.com/operator-framework/operator-sdk/pull/4623) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Add scheme, token, and TLS config to the Prometheus `ServiceMonitor` metrics endpoint.
+
+The `/metrics` endpoint, while specifying the `https` port on the manager Pod, was not actually configured to serve over https because no tlsConfig was set. Since kube-rbac-proxy secures this endpoint as a manager sidecar, using the service account token mounted into the Pod by default corrects this problem.
+The changes should look like:
+```diff
+# config/prometheus/monitor.yaml
+spec:
+   endpoints:
+     - path: /metrics
+       port: https
++      scheme: https
++      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
++      tlsConfig:
++        insecureSkipVerify: true
+   selector:
+     matchLabels:
+       control-plane: controller-manager
+```
+**Note:** if you have removed kube-rbac-proxy from your project, make sure to secure the `/metrics` endpoint using a proper [TLS configuration](https://prometheus.io/docs/guides/tls-encryption/).
+
+_See [#4680](https://github.com/operator-framework/operator-sdk/pull/4680) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Add `opm` and `catalog-build` Makefile targets
+
+The `opm` and `catalog-build` Makefile targets were added so operator developers who want to create their own catalogs for their operator or add their operator's bundle(s) to an existing catalog can do so. If this sounds like you, add the following lines to the bottom of your Makefile:
+```make
+.PHONY: opm
+OPM = ./bin/opm
+opm:
+ifeq (,$(wildcard $(OPM)))
+ifeq (,$(shell which opm 2>/dev/null))
+	@{ \
+	set -e ;\
+	mkdir -p $(dir $(OPM)) ;\
+	curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCH)-opm ;\
+	chmod +x $(OPM) ;\
+	}
+else 
+OPM = $(shell which opm)
+endif
+endif
+BUNDLE_IMGS ?= $(BUNDLE_IMG) 
+CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif 
+.PHONY: catalog-build
+catalog-build: opm
+	$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
+
+.PHONY: catalog-push
+catalog-push: ## Push the catalog image.
+	$(MAKE) docker-push IMG=$(CATALOG_IMG)
+```
+If updating a Go operator project, additionally add the following Makefile variables:
+```make
+OS = $(shell go env GOOS)
+ARCH = $(shell go env GOARCH)
+```
+
+_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables
+
+The following Makefile changes were made to allow `make bundle-build bundle-push catalog-build catalog-push` and encode image repo/namespace information in the Makefile by default:
+```diff
++IMAGE_TAG_BASE ?= <registry>/<operator name>
++ 
+-BUNDLE_IMG ?= controller-bundle:$(VERSION)
++BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
+```
+
+For example, if `IMAGE_TAG_BASE ?= foo/bar-operator` then running `make bundle-build bundle-push catalog-build catalog-push` would build `foo/bar-operator-bundle:v0.0.1` and `foo/bar-operator-catalog:v0.0.1` then push them to the `docker.io/foo` namespaced registry.
+
+_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._
+
+## (ansible/v1, helm/v1) Add the `controller-manager` ServiceAccount to your project.
+
+A non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`, to improve security for operators installed in shared namespaces. To add this ServiceAccount to your project, do the following: ```sh
+# Create the ServiceAccount.
+cat <<EOF > config/rbac/service_account.yaml apiVersion: v1 
+kind: ServiceAccount
+metadata:
+  name: controller-manager
+  namespace: system
+EOF
+# Add it to the list of RBAC resources.
+echo "- service_account.yaml" >> config/rbac/kustomization.yaml
+# Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.
+find config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \; # Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName. sed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\1serviceAccountName: controller-manager\n\1\2/g' config/manager/manager.yaml
+``` 
+
+The changes should look like: 
+
+```diff 
+# config/manager/manager.yaml
+           requests:
+             cpu: 100m
+             memory: 20Mi
++      serviceAccountName: controller-manager
+       terminationGracePeriodSeconds: 10
+# config/rbac/auth_proxy_role_binding.yaml
+   name: proxy-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default 
++  name: controller-manager
+   namespace: system
+# config/rbac/kustomization.yaml
+ resources:
++- service_account.yaml
+ - role.yaml
+ - role_binding.yaml
+ - leader_election_role.yaml
+# config/rbac/leader_election_role_binding.yaml
+   name: leader-election-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default
++  name: controller-manager
+   namespace: system
+# config/rbac/role_binding.yaml
+   name: manager-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default 
++  name: controller-manager
+   namespace: system
+# config/rbac/service_account.yaml 
++apiVersion: v1 
++kind: ServiceAccount 
++metadata: 
++  name: controller-manager 
++  namespace: system
+```
+
+_See [#4653](https://github.com/operator-framework/operator-sdk/pull/4653) for more details._
diff --git a/website/content/en/docs/upgrading-sdk-version/v1.6.1.md b/website/content/en/docs/upgrading-sdk-version/v1.6.1.md
new file mode 100644
index 00000000..1a9f8265
--- /dev/null
+++ b/website/content/en/docs/upgrading-sdk-version/v1.6.1.md
@@ -0,0 +1,280 @@
+---
+title: v1.6.1
+weight: 998994000
+---
+
+## (ansible/v1, helm/v1) Optional: configure `ansible-operator` and `helm-operator` with a component config.
+
+To add this option your project you will need to: 
+- Create the file [config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/default/manager_config_patch.yaml). 
+- Create the file [config/manager/controller_manager_config.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/manager/controller_manager_config.yaml). 
+- Update the `config/default/kustomization.yaml` by adding the following to `resources`:
+  ```yaml
+  resources:
+  ...
+  - manager_config_patch.yaml
+  ```
+- Update the `config/manager/kustomization.yaml` by adding:
+```yaml
+  generatorOptions:
+    disableNameSuffixHash: true
+
+  configMapGenerator:
+  - files:
+    - controller_manager_config.yaml
+    name: manager-config
+  apiVersion: kustomize.config.k8s.io/v1beta1
+  kind: Kustomization
+  images:
+  - name: controller
+    newName: quay.io/example/memcached-operator
+    newTag: v0.0.1
+```
+
+_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._
+
+## (ansible/v1, helm/v1) Add Role rules for leader election.
+
+Add the rule for the `apiGroups` `coordination.k8s.io` and the resource `leases` in config/rbac/leader_election_role.yaml:
+```yaml
+rules:
+  - apiGroups:
+      - ""
+      - coordination.k8s.io
+    resources:
+      - configmaps
+      - leases
+```
+
+_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._
+
+## (ansible/v1) Update Ansible collections
+
+In your requirements.yml, change the `version` field for community.kubernetes to `1.2.1`, and the `version` field for `operator_sdk.util` to `0.2.0`.
+
+_See [#4734](https://github.com/operator-framework/operator-sdk/pull/4734) for more details._
+
+## (helm/v1) Replace deprecated leader election and metrics address flags
+
+Replace deprecated flags `--enable-leader-election` and `--metrics-addr` with `--leader-elect` and `--metrics-bind-address`, respectively.
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
+
+Add the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:
+```yaml
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        args:
+        - "--health-probe-bind-address=:8081"
+        ...
+```
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.
+
+Add the arg `--health-probe-bind-address=:6789` to the `config/default/manager_auth_proxy_patch.yaml`:
+```yaml
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        args:
+        - "--health-probe-bind-address=:6789"
+        ...
+```
+
+_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._
+
+## (helm/v1, ansible/v1) Add `help` target to Makefile.
+
+Ansible/Helm projects now provide a Makefile `help` target, similar to a `--help` flag. You can copy and paste this target from the relevant sample's Makefile ([helm](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/helm/memcached-operator/Makefile), [ansible](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/ansible/memcached-operator/Makefile)).
+
+_See [#4660](https://github.com/operator-framework/operator-sdk/pull/4660) for more details._
+
+## (ansible/v1, helm/v1) Add `securityContext`'s to your manager's Deployment.
+
+In `config/manager/manager.yaml`, add the following security contexts:
+```yaml
+spec:
+  ...
+  template:
+    ...
+    spec:
+      securityContext:
+        runAsNonRoot: true
+      containers:
+      - name: manager
+        securityContext:
+          allowPrivilegeEscalation: false
+```
+
+_See [#4655](https://github.com/operator-framework/operator-sdk/pull/4655) for more details._
+
+## (manifests/v2) Add a kustomize patch to remove the cert-manager volume/volumeMount from your CSV
+
+OLM does [not yet support cert-manager](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements), so a JSON patch was added to remove this volume and mount such that OLM can itself create and manage certs for your Operator.
+In `config/manifests/kustomization.yaml`, add the following:
+```yaml
+patchesJson6902: 
+- target:
+    group: apps
+    version: v1
+    kind: Deployment
+    name: controller-manager
+    namespace: system
+  patch: |-
+    # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs.
+    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.
+    - op: remove
+      path: /spec/template/spec/containers/1/volumeMounts/0
+    # Remove the "cert" volume, since OLM will create and mount a set of certs.
+    # Update the indices in this path if adding or removing volumes in the manager's Deployment.
+    - op: remove
+      path: /spec/template/spec/volumes/0
+```
+
+_See [#4623](https://github.com/operator-framework/operator-sdk/pull/4623) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Add scheme, token, and TLS config to the Prometheus `ServiceMonitor` metrics endpoint.
+
+The `/metrics` endpoint, while specifying the `https` port on the manager Pod, was not actually configured to serve over https because no tlsConfig was set. Since kube-rbac-proxy secures this endpoint as a manager sidecar, using the service account token mounted into the Pod by default corrects this problem.
+The changes should look like:
+```diff
+# config/prometheus/monitor.yaml
+spec:
+   endpoints:
+     - path: /metrics
+       port: https
++      scheme: https
++      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
++      tlsConfig:
++        insecureSkipVerify: true
+   selector:
+     matchLabels:
+       control-plane: controller-manager
+```
+**Note:** if you have removed kube-rbac-proxy from your project, make sure to secure the `/metrics` endpoint using a proper [TLS configuration](https://prometheus.io/docs/guides/tls-encryption/).
+
+_See [#4680](https://github.com/operator-framework/operator-sdk/pull/4680) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Add `opm` and `catalog-build` Makefile targets
+
+The `opm` and `catalog-build` Makefile targets were added so operator developers who want to create their own catalogs for their operator or add their operator's bundle(s) to an existing catalog can do so. If this sounds like you, add the following lines to the bottom of your Makefile:
+```make
+.PHONY: opm
+OPM = ./bin/opm
+opm:
+ifeq (,$(wildcard $(OPM)))
+ifeq (,$(shell which opm 2>/dev/null))
+	@{ \
+	set -e ;\
+	mkdir -p $(dir $(OPM)) ;\
+	curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.15.1/$(OS)-$(ARCH)-opm ;\
+	chmod +x $(OPM) ;\
+	}
+else 
+OPM = $(shell which opm)
+endif
+endif
+BUNDLE_IMGS ?= $(BUNDLE_IMG) 
+CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif 
+.PHONY: catalog-build
+catalog-build: opm
+	$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)
+
+.PHONY: catalog-push
+catalog-push: ## Push the catalog image.
+	$(MAKE) docker-push IMG=$(CATALOG_IMG)
+```
+If updating a Go operator project, additionally add the following Makefile variables:
+```make
+OS = $(shell go env GOOS)
+ARCH = $(shell go env GOARCH)
+```
+
+_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._
+
+## (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables
+
+The following Makefile changes were made to allow `make bundle-build bundle-push catalog-build catalog-push` and encode image repo/namespace information in the Makefile by default:
+```diff
++IMAGE_TAG_BASE ?= <registry>/<operator name>
++ 
+-BUNDLE_IMG ?= controller-bundle:$(VERSION)
++BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
+```
+
+For example, if `IMAGE_TAG_BASE ?= foo/bar-operator` then running `make bundle-build bundle-push catalog-build catalog-push` would build `foo/bar-operator-bundle:v0.0.1` and `foo/bar-operator-catalog:v0.0.1` then push them to the `docker.io/foo` namespaced registry.
+
+_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._
+
+## (ansible/v1, helm/v1) Add the `controller-manager` ServiceAccount to your project.
+
+A non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`, to improve security for operators installed in shared namespaces. To add this ServiceAccount to your project, do the following: ```sh
+# Create the ServiceAccount.
+cat <<EOF > config/rbac/service_account.yaml apiVersion: v1 
+kind: ServiceAccount
+metadata:
+  name: controller-manager
+  namespace: system
+EOF
+# Add it to the list of RBAC resources.
+echo "- service_account.yaml" >> config/rbac/kustomization.yaml
+# Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.
+find config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \; 
+# Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName. 
+sed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\1serviceAccountName: controller-manager\n\1\2/g' config/manager/manager.yaml
+```
+
+The changes should look like: 
+
+```diff 
+# config/manager/manager.yaml
+           requests:
+             cpu: 100m
+             memory: 20Mi
++      serviceAccountName: controller-manager
+       terminationGracePeriodSeconds: 10
+# config/rbac/auth_proxy_role_binding.yaml
+   name: proxy-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default 
++  name: controller-manager
+   namespace: system
+# config/rbac/kustomization.yaml
+ resources:
++- service_account.yaml
+ - role.yaml
+ - role_binding.yaml
+ - leader_election_role.yaml
+# config/rbac/leader_election_role_binding.yaml
+   name: leader-election-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default
++  name: controller-manager
+   namespace: system
+# config/rbac/role_binding.yaml
+   name: manager-role
+ subjects:
+ - kind: ServiceAccount
+-  name: default 
++  name: controller-manager
+   namespace: system
+# config/rbac/service_account.yaml 
++apiVersion: v1 
++kind: ServiceAccount 
++metadata: 
++  name: controller-manager 
++  namespace: system
+```
+
+_See [#4653](https://github.com/operator-framework/operator-sdk/pull/4653) for more details._
\ No newline at end of file
diff --git a/website/content/en/docs/upgrading-sdk-version/version-upgrade-guide.md b/website/content/en/docs/upgrading-sdk-version/version-upgrade-guide.md
index dbba1715..2a9393ce 100644
--- a/website/content/en/docs/upgrading-sdk-version/version-upgrade-guide.md
+++ b/website/content/en/docs/upgrading-sdk-version/version-upgrade-guide.md
@@ -10,7 +10,6 @@ For some versions it might also be necessary to update the upstream Kubernetes a
 
 The full list of dependencies and their versions required by a particular version of the SDK can be viewed by using the [`operator-sdk print-deps`][print-deps-cli] command. Use this command to update the project `Gopkg.toml`/`go.mod` file accordingly as you upgrade to a new SDK version.
 
-
 For some SDK versions after `v0.1.0` there might be minor breaking changes in the controller-runtime APIs, `operator-sdk` CLI or the expected project layout and file names. These breaking changes will usually be outlined in the [CHANGELOG][changelog]/[release-notes][release-notes] for each release version.
 
 For releases that have a large number of breaking changes or involve a significant refactoring of the APIs and project layout there will be a migration guide similar to the [v0.1.0 migration guide][v0.1.0-migration-guide].
@@ -32,27 +31,27 @@ The following sections outline the upgrade steps for each SDK version along with
   ```TOML
   [[override]]
     name = "k8s.io/code-generator"
-    **revision for tag "kubernetes-1.12.3"**
+    # **revision for tag "kubernetes-1.12.3"**
     revision = "3dcf91f64f638563e5106f21f50c31fa361c918d"
 
   [[override]]
     name = "k8s.io/api"
-    **revision for tag "kubernetes-1.12.3"**
+    # **revision for tag "kubernetes-1.12.3"**
     revision = "b503174bad5991eb66f18247f52e41c3258f6348"
 
   [[override]]
     name = "k8s.io/apiextensions-apiserver"
-    **revision for tag "kubernetes-1.12.3"**
+    # **revision for tag "kubernetes-1.12.3"**
     revision = "0cd23ebeb6882bd1cdc2cb15fc7b2d72e8a86a5b"
 
   [[override]]
     name = "k8s.io/apimachinery"
-    **revision for tag "kubernetes-1.12.3"**
+    # **revision for tag "kubernetes-1.12.3"**
     revision = "eddba98df674a16931d2d4ba75edc3a389bf633a"
 
   [[override]]
     name = "k8s.io/client-go"
-    **revision for tag "kubernetes-1.12.3"**
+    # **revision for tag "kubernetes-1.12.3"**
     revision = "d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8"
 
   [[override]]
@@ -79,27 +78,27 @@ The following sections outline the upgrade steps for each SDK version along with
   ```TOML
   [[override]]
     name = "k8s.io/code-generator"
-    **revision for tag "kubernetes-1.13.1"**
+    # **revision for tag "kubernetes-1.13.1"**
     revision = "c2090bec4d9b1fb25de3812f868accc2bc9ecbae"
 
   [[override]]
     name = "k8s.io/api"
-    **revision for tag "kubernetes-1.13.1"**
+    # **revision for tag "kubernetes-1.13.1"**
     revision = "05914d821849570fba9eacfb29466f2d8d3cd229"
 
   [[override]]
     name = "k8s.io/apiextensions-apiserver"
-    **revision for tag "kubernetes-1.13.1"**
+    # **revision for tag "kubernetes-1.13.1"**
     revision = "0fe22c71c47604641d9aa352c785b7912c200562"
 
   [[override]]
     name = "k8s.io/apimachinery"
-    **revision for tag "kubernetes-1.13.1"**
+    # **revision for tag "kubernetes-1.13.1"**
     revision = "2b1284ed4c93a43499e781493253e2ac5959c4fd"
 
   [[override]]
     name = "k8s.io/client-go"
-    **revision for tag "kubernetes-1.13.1"**
+    # **revision for tag "kubernetes-1.13.1"**
     revision = "8d9ed539ba3134352c586810e749e58df4e94e4f"
 
   [[override]]
@@ -286,19 +285,19 @@ Upon updating the project to `v0.8.2` the following breaking changes apply:
   ```TOML
   [[override]]
     name = "k8s.io/api"
-    **revision for tag "kubernetes-1.13.4"**
+    # **revision for tag "kubernetes-1.13.4"**
     revision = "5cb15d34447165a97c76ed5a60e4e99c8a01ecfe"
   [[override]]
     name = "k8s.io/apiextensions-apiserver"
-    **revision for tag "kubernetes-1.13.4"**
+    # **revision for tag "kubernetes-1.13.4"**
     revision = "d002e88f6236312f0289d9d1deab106751718ff0"
   [[override]]
     name = "k8s.io/apimachinery"
-    **revision for tag "kubernetes-1.13.4"**
+    # **revision for tag "kubernetes-1.13.4"**
     revision = "86fb29eff6288413d76bd8506874fddd9fccdff0"
   [[override]]
     name = "k8s.io/client-go"
-    **revision for tag "kubernetes-1.13.4"**
+    # **revision for tag "kubernetes-1.13.4"**
     revision = "b40b2a5939e43f7ffe0028ad67586b7ce50bb675"
   [[override]]
     name = "github.com/coreos/prometheus-operator"
@@ -380,19 +379,19 @@ Upon updating the project to `v0.8.2` the following breaking changes apply:
     ```TOML
     [[override]]
       name = "k8s.io/api"
-      **revision for tag "kubernetes-1.14.1"**
+      # **revision for tag "kubernetes-1.14.1"**
       revision = "6e4e0e4f393bf5e8bbff570acd13217aa5a770cd"
     [[override]]
       name = "k8s.io/apiextensions-apiserver"
-      **revision for tag "kubernetes-1.14.1"**
+      # **revision for tag "kubernetes-1.14.1"**
       revision = "727a075fdec8319bf095330e344b3ccc668abc73"
     [[override]]
       name = "k8s.io/apimachinery"
-      **revision for tag "kubernetes-1.14.1"**
+      # **revision for tag "kubernetes-1.14.1"**
       revision = "6a84e37a896db9780c75367af8d2ed2bb944022e"
     [[override]]
       name = "k8s.io/client-go"
-      **revision for tag "kubernetes-1.14.1"**
+      # **revision for tag "kubernetes-1.14.1"**
       revision = "1a26190bd76a9017e289958b9fba936430aa3704"
     [[override]]
       name = "github.com/coreos/prometheus-operator"
@@ -465,7 +464,7 @@ All method signatures for [`sigs.k8s.io/controller-runtime/pkg/client.Client`](h
     with:
     ```go
     listOpts := []client.ListOption{
-      client.InNamespace("namespace"),        
+      client.InNamespace("namespace"),
     }
     err = r.client.List(context.TODO(), podList, listOpts...)
     ```
@@ -634,7 +633,7 @@ Replace `*` per verbs in order to solve the issue [671](https://github.com/opera
 
 - **Deprecated:** Deprecated the `operator-sdk generate openapi` command. CRD generation is still supported with `operator-sdk generate crds`. It is now recommended to use [openapi-gen](https://github.com/kubernetes/kube-openapi/tree/master/cmd/openapi-gen) directly for OpenAPI code generation. The `generate openapi` subcommand will be removed in a future release.
 - **Breaking change:** An existing CSV's `spec.customresourcedefinitions.owned` is now always overwritten except for each name, version, and kind on invoking olm-catalog gen-csv when Go API code annotations are present.
-- **Potentially Breaking change:** Be aware that there are potentially other breaking changes due to the controller-runtime and Kubernetes version be upgraded from `v0.4.0` to `v1.16.2, respectively. There may be breaking changes to Go client code due to both of those changes.
+- **Potentially Breaking change:** Be aware that there are potentially other breaking changes due to the controller-runtime and Kubernetes version be upgraded from `v0.4.0` to `v1.16.2`, respectively. There may be breaking changes to Go client code due to both of those changes.
 
 For further detailed information see [CHANGELOG](https://github.com/operator-framework/operator-sdk/blob/master/CHANGELOG.md#v0130)
 
@@ -1341,7 +1340,7 @@ install:
   - pip3 install docker molecule ansible-lint yamllint flake8 openshift jmespath
 ```
 
-**NOTE** To know more about how to upgrade your project to use the V3 Molecule version see [here](https://github.com/ansible-community/molecule/issues/2560).  
+**NOTE** To know more about how to upgrade your project to use the V3 Molecule version see [here](https://github.com/ansible-community/molecule/issues/2560).
 
 **Deprecations**
 


Test patch:
diff --git a/hack/generate/samples/generate_testdata.go b/hack/generate/samples/generate_testdata.go
index 69125cdc..b5fd758c 100644
--- a/hack/generate/samples/generate_testdata.go
+++ b/hack/generate/samples/generate_testdata.go
@@ -28,31 +28,37 @@ import (
 )
 
 func main() {
-	// testdata is the path where all samples should be generate
-	const testdata = "/testdata/"
-
-	// binaryName allow inform the binary that should be used.
+	// binaryPath allow inform the binary that should be used.
 	// By default it is operator-sdk
-	var binaryName string
+	var binaryPath string
 
-	flag.StringVar(&binaryName, "bin", testutils.BinaryName, "Binary path that should be used")
+	flag.StringVar(&binaryPath, "bin", testutils.BinaryName, "Binary path that should be used")
 	flag.Parse()
 
-	currentPath, err := os.Getwd()
+	// Make the binary path absolute if pathed, for reproducibility and debugging purposes.
+	if dir, _ := filepath.Split(binaryPath); dir != "" {
+		tmp, err := filepath.Abs(binaryPath)
+		if err != nil {
+			log.Fatalf("Failed to make binary path %q absolute: %v", binaryPath, err)
+		}
+		binaryPath = tmp
+	}
+
+	wd, err := os.Getwd()
 	if err != nil {
-		log.Error(err)
-		os.Exit(1)
+		log.Fatal(err)
 	}
 
-	samplesPath := filepath.Join(currentPath, testdata)
-	log.Infof("using the path: (%v)", samplesPath)
+	// samplesPath is the path where all samples should be generated
+	samplesPath := filepath.Join(wd, "testdata")
+	log.Infof("writing sample directories under %s", samplesPath)
 
 	log.Infof("creating Helm Memcached Sample")
-	helm.GenerateMemcachedHelmSample(samplesPath)
+	helm.GenerateMemcachedSamples(binaryPath, samplesPath)
 
 	log.Infof("creating Ansible Memcached Sample")
-	ansible.GenerateMemcachedAnsibleSample(samplesPath)
+	ansible.GenerateMemcachedSamples(binaryPath, samplesPath)
 
 	log.Infof("creating Go Memcached Sample with Webhooks")
-	golang.GenerateMemcachedGoWithWebhooksSample(samplesPath)
+	golang.GenerateMemcachedSamples(binaryPath, samplesPath)
 }
diff --git a/images/custom-scorecard-tests/Dockerfile b/images/custom-scorecard-tests/Dockerfile
index 07f1a411..deb1ff98 100644
--- a/images/custom-scorecard-tests/Dockerfile
+++ b/images/custom-scorecard-tests/Dockerfile
@@ -17,7 +17,7 @@ COPY . .
 RUN GOOS=linux GOARCH=$TARGETARCH make build/custom-scorecard-tests
 
 # Final image.
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-298
 
 ENV HOME=/opt/custom-scorecard-tests \
     USER_NAME=custom-scorecard-tests \
diff --git a/images/scorecard-test/Dockerfile b/images/scorecard-test/Dockerfile
index 996970c5..ec014a2b 100644
--- a/images/scorecard-test/Dockerfile
+++ b/images/scorecard-test/Dockerfile
@@ -17,7 +17,7 @@ COPY . .
 RUN GOOS=linux GOARCH=$TARGETARCH make build/scorecard-test
 
 # Final image.
-FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-230
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-298
 
 ENV HOME=/opt/scorecard-test \
     USER_NAME=scorecard-test \
diff --git a/internal/ansible/flags/flag_test.go b/internal/ansible/flags/flag_test.go
new file mode 100644
index 00000000..095918ea
--- /dev/null
+++ b/internal/ansible/flags/flag_test.go
@@ -0,0 +1,72 @@
+// Copyright 2021 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 flags_test
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"github.com/spf13/pflag"
+	"sigs.k8s.io/controller-runtime/pkg/manager"
+
+	"github.com/operator-framework/operator-sdk/internal/ansible/flags"
+)
+
+var _ = Describe("Flags", func() {
+	Describe("ToManagerOptions", func() {
+		var (
+			f       *flags.Flags
+			flagSet *pflag.FlagSet
+			options manager.Options
+		)
+		BeforeEach(func() {
+			f = &flags.Flags{}
+			flagSet = pflag.NewFlagSet("test", pflag.ExitOnError)
+			f.AddTo(flagSet)
+		})
+
+		When("the flag is set", func() {
+			It("uses the flag value when corresponding option value is empty", func() {
+				expOptionValue := ":5678"
+				options.MetricsBindAddress = ""
+				parseArgs(flagSet, "--metrics-bind-address", expOptionValue)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+			It("uses the flag value when corresponding option value is not empty", func() {
+				expOptionValue := ":5678"
+				options.MetricsBindAddress = ":1234"
+				parseArgs(flagSet, "--metrics-bind-address", expOptionValue)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+		})
+		When("the flag is not set", func() {
+			It("uses the default flag value when corresponding option value is empty", func() {
+				expOptionValue := ":8080"
+				options.MetricsBindAddress = ""
+				parseArgs(flagSet)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+			It("uses the option value when corresponding option value is not empty", func() {
+				expOptionValue := ":1234"
+				options.MetricsBindAddress = expOptionValue
+				parseArgs(flagSet)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+		})
+	})
+})
+
+func parseArgs(fs *pflag.FlagSet, extraArgs ...string) {
+	Expect(fs.Parse(extraArgs)).To(Succeed())
+}
diff --git a/internal/ansible/flags/suite_test.go b/internal/ansible/flags/suite_test.go
new file mode 100644
index 00000000..09916d7f
--- /dev/null
+++ b/internal/ansible/flags/suite_test.go
@@ -0,0 +1,27 @@
+// Copyright 2021 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 flags_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestFlags(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Flags Suite")
+}
diff --git a/internal/helm/flags/flag_test.go b/internal/helm/flags/flag_test.go
new file mode 100644
index 00000000..5b9fdd9c
--- /dev/null
+++ b/internal/helm/flags/flag_test.go
@@ -0,0 +1,72 @@
+// Copyright 2021 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 flags_test
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"github.com/spf13/pflag"
+	"sigs.k8s.io/controller-runtime/pkg/manager"
+
+	"github.com/operator-framework/operator-sdk/internal/helm/flags"
+)
+
+var _ = Describe("Flags", func() {
+	Describe("ToManagerOptions", func() {
+		var (
+			f       *flags.Flags
+			flagSet *pflag.FlagSet
+			options manager.Options
+		)
+		BeforeEach(func() {
+			f = &flags.Flags{}
+			flagSet = pflag.NewFlagSet("test", pflag.ExitOnError)
+			f.AddTo(flagSet)
+		})
+
+		When("the flag is set", func() {
+			It("uses the flag value when corresponding option value is empty", func() {
+				expOptionValue := ":5678"
+				options.MetricsBindAddress = ""
+				parseArgs(flagSet, "--metrics-bind-address", expOptionValue)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+			It("uses the flag value when corresponding option value is not empty", func() {
+				expOptionValue := ":5678"
+				options.MetricsBindAddress = ":1234"
+				parseArgs(flagSet, "--metrics-bind-address", expOptionValue)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+		})
+		When("the flag is not set", func() {
+			It("uses the default flag value when corresponding option value is empty", func() {
+				expOptionValue := ":8080"
+				options.MetricsBindAddress = ""
+				parseArgs(flagSet)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+			It("uses the option value when corresponding option value is not empty", func() {
+				expOptionValue := ":1234"
+				options.MetricsBindAddress = expOptionValue
+				parseArgs(flagSet)
+				Expect(f.ToManagerOptions(options).MetricsBindAddress).To(Equal(expOptionValue))
+			})
+		})
+	})
+})
+
+func parseArgs(fs *pflag.FlagSet, extraArgs ...string) {
+	Expect(fs.Parse(extraArgs)).To(Succeed())
+}
diff --git a/internal/helm/flags/suite_test.go b/internal/helm/flags/suite_test.go
new file mode 100644
index 00000000..09916d7f
--- /dev/null
+++ b/internal/helm/flags/suite_test.go
@@ -0,0 +1,27 @@
+// Copyright 2021 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 flags_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestFlags(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Flags Suite")
+}
diff --git a/internal/scorecard/testdata/pod.yaml b/internal/scorecard/testdata/pod.yaml
index 3b36f466..b55f50fb 100644
--- a/internal/scorecard/testdata/pod.yaml
+++ b/internal/scorecard/testdata/pod.yaml
@@ -12,7 +12,7 @@ spec:
           apiVersion: v1
           fieldPath: metadata.namespace
     image: quay.io/operator-framework/scorecard-test:dev 
-    imagePullPolicy: IfNotPresent
+    imagePullPolicy: Always
     name: scorecard-test
     command: ["/usr/local/bin/scorecard-test"]
     args: ["basic-check-spec"]
diff --git a/testdata/ansible/memcached-operator/Dockerfile b/testdata/ansible/memcached-operator/Dockerfile
index 464a197d..4c52ea0f 100644
--- a/testdata/ansible/memcached-operator/Dockerfile
+++ b/testdata/ansible/memcached-operator/Dockerfile
@@ -1,4 +1,4 @@
-FROM quay.io/operator-framework/ansible-operator:v1.5.0
+FROM quay.io/operator-framework/ansible-operator:v1.6.1
 
 COPY requirements.yml ${HOME}/requirements.yml
 RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
diff --git a/testdata/ansible/memcached-operator/Makefile b/testdata/ansible/memcached-operator/Makefile
index 7c4c38c7..54feb3cb 100644
--- a/testdata/ansible/memcached-operator/Makefile
+++ b/testdata/ansible/memcached-operator/Makefile
@@ -109,7 +109,7 @@ ifeq (,$(shell which ansible-operator 2>/dev/null))
 	@{ \
 	set -e ;\
 	mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\
-	curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.5.0/ansible-operator_$(OS)_$(ARCH) ;\
+	curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.6.1/ansible-operator_$(OS)_$(ARCH) ;\
 	chmod +x $(ANSIBLE_OPERATOR) ;\
 	}
 else
diff --git a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml
index fa798691..6cd486d5 100644
--- a/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml
+++ b/testdata/ansible/memcached-operator/bundle/tests/scorecard/config.yaml
@@ -8,42 +8,42 @@ stages:
   - entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
   - entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
   - entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
   - entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/ansible/memcached-operator/config/default/kustomization.yaml b/testdata/ansible/memcached-operator/config/default/kustomization.yaml
index a7a68300..7a8160b5 100644
--- a/testdata/ansible/memcached-operator/config/default/kustomization.yaml
+++ b/testdata/ansible/memcached-operator/config/default/kustomization.yaml
@@ -24,3 +24,7 @@ patchesStrategicMerge:
 # If you want your controller-manager to expose the /metrics
 # endpoint w/o any authn/z, please comment the following line.
 - manager_auth_proxy_patch.yaml
+
+# Mount the controller config file for loading manager configurations
+# through a ComponentConfig type
+#- manager_config_patch.yaml
diff --git a/testdata/ansible/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml b/testdata/ansible/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml
index aa7a58d5..9e263db9 100644
--- a/testdata/ansible/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml
+++ b/testdata/ansible/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml
@@ -3,4 +3,5 @@ kind: Memcached
 metadata:
   name: memcached-sample
 spec:
+  # Add fields here
   size: 1
diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml
index 9a2562c8..ec3f34a7 100644
--- a/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml
+++ b/testdata/ansible/memcached-operator/config/scorecard/patches/basic.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
diff --git a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml
index f2284ce8..9e095537 100644
--- a/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml
+++ b/testdata/ansible/memcached-operator/config/scorecard/patches/olm.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
@@ -14,7 +14,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
@@ -24,7 +24,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
@@ -34,7 +34,7 @@
     entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
@@ -44,7 +44,7 @@
     entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml
index fa798691..6cd486d5 100644
--- a/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml
+++ b/testdata/go/v2/memcached-operator/bundle/tests/scorecard/config.yaml
@@ -8,42 +8,42 @@ stages:
   - entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
   - entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
   - entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
   - entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml
index 9a2562c8..ec3f34a7 100644
--- a/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml
+++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/basic.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
diff --git a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml
index f2284ce8..9e095537 100644
--- a/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml
+++ b/testdata/go/v2/memcached-operator/config/scorecard/patches/olm.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
@@ -14,7 +14,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
@@ -24,7 +24,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
@@ -34,7 +34,7 @@
     entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
@@ -44,7 +44,7 @@
     entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml
index fa798691..6cd486d5 100644
--- a/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml
+++ b/testdata/go/v3/memcached-operator/bundle/tests/scorecard/config.yaml
@@ -8,42 +8,42 @@ stages:
   - entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
   - entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
   - entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
   - entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml
index 9a2562c8..ec3f34a7 100644
--- a/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml
+++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/basic.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
diff --git a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml
index f2284ce8..9e095537 100644
--- a/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml
+++ b/testdata/go/v3/memcached-operator/config/scorecard/patches/olm.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
@@ -14,7 +14,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
@@ -24,7 +24,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
@@ -34,7 +34,7 @@
     entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
@@ -44,7 +44,7 @@
     entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/helm/memcached-operator/Dockerfile b/testdata/helm/memcached-operator/Dockerfile
index f4fea722..5f4dce1e 100644
--- a/testdata/helm/memcached-operator/Dockerfile
+++ b/testdata/helm/memcached-operator/Dockerfile
@@ -1,5 +1,5 @@
 # Build the manager binary
-FROM quay.io/operator-framework/helm-operator:v1.5.0
+FROM quay.io/operator-framework/helm-operator:v1.6.1
 
 ENV HOME=/opt/helm
 COPY watches.yaml ${HOME}/watches.yaml
diff --git a/testdata/helm/memcached-operator/Makefile b/testdata/helm/memcached-operator/Makefile
index 693d5d8c..2b618ad3 100644
--- a/testdata/helm/memcached-operator/Makefile
+++ b/testdata/helm/memcached-operator/Makefile
@@ -109,7 +109,7 @@ ifeq (,$(shell which helm-operator 2>/dev/null))
 	@{ \
 	set -e ;\
 	mkdir -p $(dir $(HELM_OPERATOR)) ;\
-	curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.5.0/helm-operator_$(OS)_$(ARCH) ;\
+	curl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.6.1/helm-operator_$(OS)_$(ARCH) ;\
 	chmod +x $(HELM_OPERATOR) ;\
 	}
 else
diff --git a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml
index fa798691..6cd486d5 100644
--- a/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml
+++ b/testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml
@@ -8,42 +8,42 @@ stages:
   - entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
   - entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
   - entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
   - entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
   - entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/testdata/helm/memcached-operator/config/default/kustomization.yaml b/testdata/helm/memcached-operator/config/default/kustomization.yaml
index a7a68300..7a8160b5 100644
--- a/testdata/helm/memcached-operator/config/default/kustomization.yaml
+++ b/testdata/helm/memcached-operator/config/default/kustomization.yaml
@@ -24,3 +24,7 @@ patchesStrategicMerge:
 # If you want your controller-manager to expose the /metrics
 # endpoint w/o any authn/z, please comment the following line.
 - manager_auth_proxy_patch.yaml
+
+# Mount the controller config file for loading manager configurations
+# through a ComponentConfig type
+#- manager_config_patch.yaml
diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml
index 9a2562c8..ec3f34a7 100644
--- a/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml
+++ b/testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - basic-check-spec
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: basic
       test: basic-check-spec-test
diff --git a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml
index f2284ce8..9e095537 100644
--- a/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml
+++ b/testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml
@@ -4,7 +4,7 @@
     entrypoint:
     - scorecard-test
     - olm-bundle-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-bundle-validation-test
@@ -14,7 +14,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-validation
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-validation-test
@@ -24,7 +24,7 @@
     entrypoint:
     - scorecard-test
     - olm-crds-have-resources
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-crds-have-resources-test
@@ -34,7 +34,7 @@
     entrypoint:
     - scorecard-test
     - olm-spec-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-spec-descriptors-test
@@ -44,7 +44,7 @@
     entrypoint:
     - scorecard-test
     - olm-status-descriptors
-    image: quay.io/operator-framework/scorecard-test:v1.5.0
+    image: quay.io/operator-framework/scorecard-test:v1.6.1
     labels:
       suite: olm
       test: olm-status-descriptors-test
diff --git a/website/content/en/docs/contribution-guidelines/testing.md b/website/content/en/docs/contribution-guidelines/testing.md
index 5064d892..af011955 100644
--- a/website/content/en/docs/contribution-guidelines/testing.md
+++ b/website/content/en/docs/contribution-guidelines/testing.md
@@ -1,7 +1,7 @@
 ---
 title: Testing
 linkTitle: Testing
-weight: 10
+weight: 6
 ---
 
 On all PRs, a suite of static and cluster tests is run against your changes in a CI environment.