Repository: operator-framework/operator-sdk
Pull request #4766 (2021-04-14 21:45:40)

deps: enable Dependabot to upgrade base images
<!--

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:**

This configures Dependabot (Github feature) to automatically create PRs whenever a newer base image is available.

**Motivation for the change:**

This simplifies the process of switching to a new base image after security patches are released.

Relates to #4763


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 e33d8698..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.6.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/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/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/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/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/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 8d0db628..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.6.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.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..733cdabb 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
@@ -465,7 +465,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 +634,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 +1341,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/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 7fe8d337..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.6.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 0625ecd8..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.6.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 102f82a7..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.6.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.6.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.6.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.6.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.6.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.6.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 82c03ac2..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.6.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 61942fa2..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.6.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.6.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.6.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.6.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.6.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 102f82a7..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.6.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.6.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.6.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.6.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.6.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.6.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 82c03ac2..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.6.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 61942fa2..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.6.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.6.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.6.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.6.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.6.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 102f82a7..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.6.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.6.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.6.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.6.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.6.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.6.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 82c03ac2..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.6.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 61942fa2..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.6.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.6.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.6.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.6.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.6.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 067a66fa..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.6.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 11928a2b..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.6.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 102f82a7..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.6.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.6.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.6.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.6.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.6.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.6.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 82c03ac2..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.6.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 61942fa2..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.6.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.6.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.6.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.6.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.6.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.