Repository: operator-framework/operator-lifecycle-manager
Pull request #1316 (2020-02-21 18:05:39)

Bug 1784024: Use generations to prevent duplicate InstallPlans
Supersedes #1203 

openshift-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/operator-framework/operator-lifecycle-manager/pull/1316#" title="Author self-approved">njhale</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=operator-framework%2Foperator-lifecycle-manager).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/OWNERS)~~ [njhale]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
openshift-ci-robot: @njhale: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/unit | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-unit/3247) | `/test unit`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @njhale: This pull request references [Bugzilla bug 1784024](https://bugzilla.redhat.com/show_bug.cgi?id=1784024), which is invalid:
 - expected the bug to target the "4.5.0" release, but it targets "4.4.0" instead

Comment <code>/bugzilla refresh</code> to re-evaluate validity if changes to the Bugzilla bug are made, or edit the title of this pull request to link to a different bug.

<details>

In response to [this](https://github.com/operator-framework/operator-lifecycle-manager/pull/1316):

>Bug 1784024: Use generations to prevent duplicate InstallPlans


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
njhale: /bugzilla refresh
openshift-ci-robot: @njhale: This pull request references [Bugzilla bug 1784024](https://bugzilla.redhat.com/show_bug.cgi?id=1784024), which is valid. The bug has been moved to the POST state. The bug has been updated to refer to the pull request using the external bug tracker.

<details>

In response to [this](https://github.com/operator-framework/operator-lifecycle-manager/pull/1316#issuecomment-589782359):

>/bugzilla refresh


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
openshift-ci-robot: @njhale: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/unit | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-unit/3247) | `/test unit`
ci/prow/e2e-aws-console-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-console-olm/2111) | `/test e2e-aws-console-olm`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @njhale: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/unit | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-unit/3247) | `/test unit`
ci/prow/e2e-aws-console-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-console-olm/2111) | `/test e2e-aws-console-olm`
ci/prow/e2e-aws-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-olm/4116) | `/test e2e-aws-olm`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @njhale: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/unit | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-unit/3247) | `/test unit`
ci/prow/e2e-aws-console-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-console-olm/2111) | `/test e2e-aws-console-olm`
ci/prow/e2e-aws-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-olm/4116) | `/test e2e-aws-olm`
ci/prow/e2e-gcp | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-gcp/750) | `/test e2e-gcp`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @njhale: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e-aws-olm | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-olm/4116) | `/test e2e-aws-olm`
ci/prow/e2e-gcp | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-gcp/750) | `/test e2e-gcp`
ci/prow/e2e-aws-console-olm | 289303712d99f60ca26919eede2f2681a3c764fa | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-console-olm/2112) | `/test e2e-aws-console-olm`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
openshift-ci-robot: @njhale: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
ci/prow/e2e-gcp | ad889eda97c9f2c994bd50ac1a3230f01b38aa2b | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-gcp/750) | `/test e2e-gcp`
ci/prow/e2e-aws-console-olm | 289303712d99f60ca26919eede2f2681a3c764fa | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-console-olm/2112) | `/test e2e-aws-console-olm`
ci/prow/e2e-aws-olm | 289303712d99f60ca26919eede2f2681a3c764fa | [link](https://prow.svc.ci.openshift.org/view/gcs/origin-ci-test/pr-logs/pull/operator-framework_operator-lifecycle-manager/1316/pull-ci-operator-framework-operator-lifecycle-manager-master-e2e-aws-olm/4120) | `/test e2e-aws-olm`

[Full PR test history](https://prow.svc.ci.openshift.org/pr-history?org=operator-framework&repo=operator-lifecycle-manager&pr=1316). [Your PR dashboard](https://prow.svc.ci.openshift.org/pr?query=is:pr+state:open+author:njhale). Please help us cut down on flakes by [linking to](https://github.com/kubernetes/community/blob/master/contributors/devel/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/operator-framework/operator-lifecycle-manager/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
njhale: /retest

Patch:
diff --git a/.github/stale.yml b/.github/stale.yml
deleted file mode 100644
index dc90e5a1c..000000000
--- a/.github/stale.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-# Number of days of inactivity before an issue becomes stale
-daysUntilStale: 60
-# Number of days of inactivity before a stale issue is closed
-daysUntilClose: 7
-# Issues with these labels will never be considered stale
-exemptLabels:
-  - pinned
-  - security
-# Label to use when marking an issue as stale
-staleLabel: wontfix
-# Comment to post when marking an issue as stale. Set to `false` to disable
-markComment: >
-  This issue has been automatically marked as stale because it has not had
-  recent activity. It will be closed if no further activity occurs. Thank you
-  for your contributions.
-# Comment to post when closing a stale issue. Set to `false` to disable
-closeComment: false
diff --git a/Makefile b/Makefile
index d1d23e3c8..51cc0065a 100644
--- a/Makefile
+++ b/Makefile
@@ -156,8 +156,8 @@ clean:
 
 # Generate manifests for CRDs
 manifests: vendor
-	$(CONTROLLER_GEN) schemapatch:manifests=./deploy/chart/templates paths=./pkg/api/apis/operators/v1alpha1/... output:dir=./deploy/chart/templates
-	$(CONTROLLER_GEN) schemapatch:manifests=./deploy/chart/templates paths=./pkg/api/apis/operators/v1/... output:dir=./deploy/chart/templates
+	$(CONTROLLER_GEN) schemapatch:manifests=./deploy/chart/templates paths=./pkg/api/apis/operators/... output:dir=./deploy/chart/templates
+
 	$(YQ_INTERNAL) w --inplace deploy/chart/templates/0000_50_olm_03-clusterserviceversion.crd.yaml spec.validation.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.metadata.x-kubernetes-preserve-unknown-fields true
 
 # Generate clients, listers, and informers
diff --git a/README.md b/README.md
index e4e019beb..117c55ac2 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 
 ## Overview
 
-This project is a component of the [Operator Framework](https://github.com/operator-framework), an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post](https://operatorhub.io/what-is-an-operator) and learn about practical use cases at [OLM-Book](https://github.com/operator-framework/olm-book/).
+This project is a component of the [Operator Framework](https://github.com/operator-framework), an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post](https://operatorhub.io/what-is-an-operator).
 
 OLM extends Kubernetes to provide a declarative way to install, manage, and upgrade Operators and their dependencies in a cluster. It provides the following features:
 
diff --git a/deploy/chart/templates/0000_50_olm_00-namespace.yaml b/deploy/chart/templates/0000_50_olm_00-namespace.yaml
index 17f36da66..ffc148584 100644
--- a/deploy/chart/templates/0000_50_olm_00-namespace.yaml
+++ b/deploy/chart/templates/0000_50_olm_00-namespace.yaml
@@ -6,7 +6,7 @@ metadata:
   annotations:
     openshift.io/node-selector: ""
   labels:
-    openshift.io/scc: "anyuid"
+    openshift.io/run-level: "1"
     openshift.io/cluster-monitoring: "true"
   {{ end }}
 ---
@@ -18,5 +18,5 @@ metadata:
   annotations:
     openshift.io/node-selector: ""
   labels:
-    openshift.io/scc: "anyuid"
+    openshift.io/run-level: "1"
   {{ end }}
diff --git a/deploy/chart/templates/0000_50_olm_04-installplan.crd.yaml b/deploy/chart/templates/0000_50_olm_04-installplan.crd.yaml
index 5e1747fdb..8839f288c 100644
--- a/deploy/chart/templates/0000_50_olm_04-installplan.crd.yaml
+++ b/deploy/chart/templates/0000_50_olm_04-installplan.crd.yaml
@@ -67,6 +67,7 @@ spec:
           - approval
           - approved
           - clusterServiceVersionNames
+          - generation
           properties:
             approval:
               description: Approval is the user approval policy for an InstallPlan.
@@ -77,6 +78,8 @@ spec:
               type: array
               items:
                 type: string
+            generation:
+              type: integer
             source:
               type: string
             sourceNamespace:
@@ -128,8 +131,12 @@ spec:
                   description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                   type: string
             bundleLookups:
+              description: BundleLookups is the set of in-progress requests to pull
+                and unpackage bundle content to the cluster.
               type: array
               items:
+                description: BundleLookup is a request to pull and unpackage the content
+                  of a bundle to the cluster.
                 type: object
                 required:
                 - catalogSourceRef
@@ -137,8 +144,8 @@ spec:
                 - replaces
                 properties:
                   catalogSourceRef:
-                    description: ObjectReference contains enough information to let
-                      you inspect or modify the referred object.
+                    description: CatalogSourceRef is a reference to the CatalogSource
+                      the bundle path was resolved from.
                     type: object
                     properties:
                       apiVersion:
@@ -174,6 +181,7 @@ spec:
                         description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
                         type: string
                   conditions:
+                    description: Conditions represents the overall state of a BundleLookup.
                     type: array
                     items:
                       type: object
@@ -187,7 +195,7 @@ spec:
                           type: string
                           format: date-time
                         lastUpdateTime:
-                          description: Last time the condition was probed
+                          description: Last time the condition was probed.
                           type: string
                           format: date-time
                         message:
@@ -205,8 +213,12 @@ spec:
                           description: Type of condition.
                           type: string
                   path:
+                    description: Path refers to the location of a bundle to pull.
+                      It's typically an image reference.
                     type: string
                   replaces:
+                    description: Replaces is the name of the bundle to replace with
+                      the one found at Path.
                     type: string
             catalogSources:
               type: array
diff --git a/deploy/chart/templates/0000_50_olm_05-subscription.crd.yaml b/deploy/chart/templates/0000_50_olm_05-subscription.crd.yaml
index 90d55ff1d..0598db10a 100644
--- a/deploy/chart/templates/0000_50_olm_05-subscription.crd.yaml
+++ b/deploy/chart/templates/0000_50_olm_05-subscription.crd.yaml
@@ -1702,6 +1702,10 @@ spec:
             currentCSV:
               description: CurrentCSV is the CSV the Subscription is progressing to.
               type: string
+            installPlanGeneration:
+              description: InstallPlanGeneration is the current generation of the
+                installplan
+              type: integer
             installPlanRef:
               description: InstallPlanRef is a reference to the latest InstallPlan
                 that contains the Subscription's current CSV.
diff --git a/manifests/0000_50_olm_00-namespace.yaml b/manifests/0000_50_olm_00-namespace.yaml
index 4093986bb..1627154ec 100644
--- a/manifests/0000_50_olm_00-namespace.yaml
+++ b/manifests/0000_50_olm_00-namespace.yaml
@@ -2,17 +2,19 @@ apiVersion: v1
 kind: Namespace
 metadata:
   name: openshift-operator-lifecycle-manager
+  
   annotations:
     openshift.io/node-selector: ""
   labels:
-    openshift.io/scc: "anyuid"
+    openshift.io/run-level: "1"
     openshift.io/cluster-monitoring: "true"
 ---
 apiVersion: v1
 kind: Namespace
 metadata:
   name: openshift-operators
+  
   annotations:
     openshift.io/node-selector: ""
   labels:
-    openshift.io/scc: "anyuid"
+    openshift.io/run-level: "1"
diff --git a/pkg/api/apis/operators/installplan_types.go b/pkg/api/apis/operators/installplan_types.go
index fcd7764e8..2a51f5725 100644
--- a/pkg/api/apis/operators/installplan_types.go
+++ b/pkg/api/apis/operators/installplan_types.go
@@ -26,6 +26,7 @@ type InstallPlanSpec struct {
 	ClusterServiceVersionNames []string
 	Approval                   Approval
 	Approved                   bool
+	Generation                 int
 }
 
 // InstallPlanPhase is the current status of a InstallPlan as a whole.
diff --git a/pkg/api/apis/operators/subscription_types.go b/pkg/api/apis/operators/subscription_types.go
index 931207681..92a2b6f0f 100644
--- a/pkg/api/apis/operators/subscription_types.go
+++ b/pkg/api/apis/operators/subscription_types.go
@@ -183,6 +183,10 @@ type SubscriptionStatus struct {
 	// +optional
 	Reason ConditionReason
 
+	// InstallPlanGeneration is the current generation of the installplan
+	// +optional
+	InstallPlanGeneration int `json:"installPlanGeneration,omitempty"`
+
 	// InstallPlanRef is a reference to the latest InstallPlan that contains the Subscription's current CSV.
 	// +optional
 	InstallPlanRef *corev1.ObjectReference
diff --git a/pkg/api/apis/operators/v1alpha1/installplan_types.go b/pkg/api/apis/operators/v1alpha1/installplan_types.go
index 05522337d..fb8ad81a0 100644
--- a/pkg/api/apis/operators/v1alpha1/installplan_types.go
+++ b/pkg/api/apis/operators/v1alpha1/installplan_types.go
@@ -28,6 +28,7 @@ type InstallPlanSpec struct {
 	ClusterServiceVersionNames []string `json:"clusterServiceVersionNames"`
 	Approval                   Approval `json:"approval"`
 	Approved                   bool     `json:"approved"`
+	Generation                 int      `json:"generation"`
 }
 
 // InstallPlanPhase is the current status of a InstallPlan as a whole.
@@ -305,39 +306,6 @@ func (b *BundleLookup) SetCondition(cond BundleLookupCondition) BundleLookupCond
 	return cond
 }
 
-// ManifestsMatch returns true if the CSV manifests in the StepResources of the given list of steps
-// matches those in the InstallPlanStatus.
-func (s *InstallPlanStatus) CSVManifestsMatch(steps []*Step) bool {
-	if s.Plan == nil && steps == nil {
-		return true
-	}
-	if s.Plan == nil || steps == nil {
-		return false
-	}
-
-	manifests := make(map[string]struct{})
-	for _, step := range s.Plan {
-		resource := step.Resource
-		if resource.Kind != ClusterServiceVersionKind {
-			continue
-		}
-		manifests[resource.Manifest] = struct{}{}
-	}
-
-	for _, step := range steps {
-		resource := step.Resource
-		if resource.Kind != ClusterServiceVersionKind {
-			continue
-		}
-		if _, ok := manifests[resource.Manifest]; !ok {
-			return false
-		}
-		delete(manifests, resource.Manifest)
-	}
-
-	return len(manifests) == 0
-}
-
 func (s *Step) String() string {
 	return fmt.Sprintf("%s: %s (%s)", s.Resolving, s.Resource, s.Status)
 }
diff --git a/pkg/api/apis/operators/v1alpha1/subscription_types.go b/pkg/api/apis/operators/v1alpha1/subscription_types.go
index 9e997bb61..b80334e17 100644
--- a/pkg/api/apis/operators/v1alpha1/subscription_types.go
+++ b/pkg/api/apis/operators/v1alpha1/subscription_types.go
@@ -186,6 +186,10 @@ type SubscriptionStatus struct {
 	// +optional
 	Reason ConditionReason `json:"reason,omitempty"`
 
+	// InstallPlanGeneration is the current generation of the installplan
+	// +optional
+	InstallPlanGeneration int `json:"installPlanGeneration,omitempty"`
+
 	// InstallPlanRef is a reference to the latest InstallPlan that contains the Subscription's current CSV.
 	// +optional
 	InstallPlanRef *corev1.ObjectReference `json:"installPlanRef,omitempty"`
diff --git a/pkg/api/apis/operators/v1alpha1/zz_generated.conversion.go b/pkg/api/apis/operators/v1alpha1/zz_generated.conversion.go
index efd707efd..1ab14411c 100644
--- a/pkg/api/apis/operators/v1alpha1/zz_generated.conversion.go
+++ b/pkg/api/apis/operators/v1alpha1/zz_generated.conversion.go
@@ -1363,6 +1363,7 @@ func autoConvert_v1alpha1_InstallPlanSpec_To_operators_InstallPlanSpec(in *Insta
 	out.ClusterServiceVersionNames = *(*[]string)(unsafe.Pointer(&in.ClusterServiceVersionNames))
 	out.Approval = operators.Approval(in.Approval)
 	out.Approved = in.Approved
+	out.Generation = in.Generation
 	return nil
 }
 
@@ -1377,6 +1378,7 @@ func autoConvert_operators_InstallPlanSpec_To_v1alpha1_InstallPlanSpec(in *opera
 	out.ClusterServiceVersionNames = *(*[]string)(unsafe.Pointer(&in.ClusterServiceVersionNames))
 	out.Approval = Approval(in.Approval)
 	out.Approved = in.Approved
+	out.Generation = in.Generation
 	return nil
 }
 
@@ -1909,6 +1911,7 @@ func autoConvert_v1alpha1_SubscriptionStatus_To_operators_SubscriptionStatus(in
 	out.Install = (*operators.InstallPlanReference)(unsafe.Pointer(in.Install))
 	out.State = operators.SubscriptionState(in.State)
 	out.Reason = operators.ConditionReason(in.Reason)
+	out.InstallPlanGeneration = in.InstallPlanGeneration
 	out.InstallPlanRef = (*v1.ObjectReference)(unsafe.Pointer(in.InstallPlanRef))
 	out.CatalogHealth = *(*[]operators.SubscriptionCatalogHealth)(unsafe.Pointer(&in.CatalogHealth))
 	out.Conditions = *(*[]operators.SubscriptionCondition)(unsafe.Pointer(&in.Conditions))
@@ -1927,6 +1930,7 @@ func autoConvert_operators_SubscriptionStatus_To_v1alpha1_SubscriptionStatus(in
 	out.Install = (*InstallPlanReference)(unsafe.Pointer(in.Install))
 	out.State = SubscriptionState(in.State)
 	out.Reason = ConditionReason(in.Reason)
+	out.InstallPlanGeneration = in.InstallPlanGeneration
 	out.InstallPlanRef = (*v1.ObjectReference)(unsafe.Pointer(in.InstallPlanRef))
 	out.CatalogHealth = *(*[]SubscriptionCatalogHealth)(unsafe.Pointer(&in.CatalogHealth))
 	out.Conditions = *(*[]SubscriptionCondition)(unsafe.Pointer(&in.Conditions))
diff --git a/pkg/api/apis/operators/v1alpha2/doc.go b/pkg/api/apis/operators/v1alpha2/doc.go
new file mode 100644
index 000000000..29ac1b147
--- /dev/null
+++ b/pkg/api/apis/operators/v1alpha2/doc.go
@@ -0,0 +1,6 @@
+// +k8s:deepcopy-gen=package
+// +k8s:conversion-gen=github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators
+// +groupName=operators.coreos.com
+
+// Package v1alpha2 contains resources types for version v1alpha2 of the operators.coreos.com API group.
+package v1alpha2
diff --git a/pkg/api/apis/operators/v1alpha2/operatorgroup_types.go b/pkg/api/apis/operators/v1alpha2/operatorgroup_types.go
new file mode 100644
index 000000000..5779c3519
--- /dev/null
+++ b/pkg/api/apis/operators/v1alpha2/operatorgroup_types.go
@@ -0,0 +1,97 @@
+package v1alpha2
+
+import (
+	"sort"
+	"strings"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+const (
+	OperatorGroupAnnotationKey             = "olm.operatorGroup"
+	OperatorGroupNamespaceAnnotationKey    = "olm.operatorNamespace"
+	OperatorGroupTargetsAnnotationKey      = "olm.targetNamespaces"
+	OperatorGroupProvidedAPIsAnnotationKey = "olm.providedAPIs"
+
+	OperatorGroupKind = "OperatorGroup"
+)
+
+// OperatorGroupSpec is the spec for an OperatorGroup resource.
+type OperatorGroupSpec struct {
+	// Selector selects the OperatorGroup's target namespaces.
+	// +optional
+	Selector *metav1.LabelSelector `json:"selector,omitempty"`
+
+	// TargetNamespaces is an explicit set of namespaces to target.
+	// If it is set, Selector is ignored.
+	// +optional
+	TargetNamespaces []string `json:"targetNamespaces,omitempty"`
+
+	// ServiceAccountName is the admin specified service account which will be
+	// used to deploy operator(s) in this operator group.
+	ServiceAccountName string `json:"serviceAccountName,omitempty"`
+
+	// Static tells OLM not to update the OperatorGroup's providedAPIs annotation
+	// +optional
+	StaticProvidedAPIs bool `json:"staticProvidedAPIs,omitempty"`
+}
+
+// OperatorGroupStatus is the status for an OperatorGroupResource.
+type OperatorGroupStatus struct {
+	// Namespaces is the set of target namespaces for the OperatorGroup.
+	Namespaces []string `json:"namespaces,omitempty"`
+
+	// ServiceAccountRef references the service account object specified.
+	ServiceAccountRef *corev1.ObjectReference `json:"serviceAccountRef,omitempty"`
+
+	// LastUpdated is a timestamp of the last time the OperatorGroup's status was Updated.
+	LastUpdated *metav1.Time `json:"lastUpdated"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +genclient
+
+// OperatorGroup is the unit of multitenancy for OLM managed operators.
+// It constrains the installation of operators in its namespace to a specified set of target namespaces.
+type OperatorGroup struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata"`
+
+	// +optional
+	Spec   OperatorGroupSpec   `json:"spec"`
+	Status OperatorGroupStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// OperatorGroupList is a list of OperatorGroup resources.
+type OperatorGroupList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata"`
+
+	Items []OperatorGroup `json:"items"`
+}
+
+func (o *OperatorGroup) BuildTargetNamespaces() string {
+	sort.Strings(o.Status.Namespaces)
+	return strings.Join(o.Status.Namespaces, ",")
+}
+
+// IsServiceAccountSpecified returns true if the spec has a service account name specified.
+func (o *OperatorGroup) IsServiceAccountSpecified() bool {
+	if o.Spec.ServiceAccountName == "" {
+		return false
+	}
+
+	return true
+}
+
+// HasServiceAccountSynced returns true if the service account specified has been synced.
+func (o *OperatorGroup) HasServiceAccountSynced() bool {
+	if o.IsServiceAccountSpecified() && o.Status.ServiceAccountRef != nil {
+		return true
+	}
+
+	return false
+}
diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go
index ae9599149..95b3e1aa4 100644
--- a/pkg/controller/operators/catalog/operator.go
+++ b/pkg/controller/operators/catalog/operator.go
@@ -7,11 +7,9 @@ import (
 	"fmt"
 	"reflect"
 	"strings"
+	"sync"
 	"time"
 
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/util/yaml"
-
 	errorwrap "github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"google.golang.org/grpc/connectivity"
@@ -23,15 +21,18 @@ import (
 	extinf "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	utilclock "k8s.io/apimachinery/pkg/util/clock"
 	utilerrors "k8s.io/apimachinery/pkg/util/errors"
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 	"k8s.io/apimachinery/pkg/util/validation/field"
+	"k8s.io/apimachinery/pkg/util/yaml"
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/tools/clientcmd"
+	"k8s.io/client-go/util/retry"
 	"k8s.io/client-go/util/workqueue"
 
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/reference"
@@ -753,6 +754,7 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
 	}
 
 	// TODO: parallel
+	maxGeneration := 0
 	subscriptionUpdated := false
 	for i, sub := range subs {
 		logger := logger.WithFields(logrus.Fields{
@@ -762,6 +764,10 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
 			"channel": sub.Spec.Channel,
 		})
 
+		if sub.Status.InstallPlanGeneration > maxGeneration {
+			maxGeneration = sub.Status.InstallPlanGeneration
+		}
+
 		// ensure the installplan reference is correct
 		sub, changedIP, err := o.ensureSubscriptionInstallPlanState(logger, sub)
 		if err != nil {
@@ -813,12 +819,12 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
 			}
 		}
 
-		installPlanReference, err := o.ensureInstallPlan(logger, namespace, subs, installPlanApproval, steps, bundleLookups)
+		installPlanReference, err := o.ensureInstallPlan(logger, namespace, maxGeneration+1, subs, installPlanApproval, steps, bundleLookups)
 		if err != nil {
 			logger.WithError(err).Debug("error ensuring installplan")
 			return err
 		}
-		if err := o.updateSubscriptionStatus(namespace, updatedSubs, installPlanReference); err != nil {
+		if err := o.updateSubscriptionStatus(namespace, maxGeneration+1, updatedSubs, installPlanReference); err != nil {
 			logger.WithError(err).Debug("error ensuring subscription installplan state")
 			return err
 		}
@@ -866,7 +872,7 @@ func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub
 		return sub, false, nil
 	}
 
-	ip, err := o.lister.OperatorsV1alpha1().InstallPlanLister().InstallPlans(sub.GetNamespace()).Get(ipName)
+	ip, err := o.client.OperatorsV1alpha1().InstallPlans(sub.GetNamespace()).Get(ipName, metav1.GetOptions{})
 	if err != nil {
 		logger.WithField("installplan", ipName).Warn("unable to get installplan from cache")
 		return nil, false, err
@@ -936,24 +942,52 @@ func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha
 	return updatedSub, true, nil
 }
 
-func (o *Operator) updateSubscriptionStatus(namespace string, subs []*v1alpha1.Subscription, installPlanRef *corev1.ObjectReference) error {
-	// TODO: parallel, sync waitgroup
-	var err error
+func (o *Operator) updateSubscriptionStatus(namespace string, gen int, subs []*v1alpha1.Subscription, installPlanRef *corev1.ObjectReference) error {
+	var (
+		errs        []error
+		mu          sync.Mutex
+		wg          sync.WaitGroup
+		getOpts     = metav1.GetOptions{}
+		lastUpdated = o.now()
+	)
 	for _, sub := range subs {
-		sub.Status.LastUpdated = o.now()
+		sub.Status.LastUpdated = lastUpdated
 		if installPlanRef != nil {
 			sub.Status.InstallPlanRef = installPlanRef
 			sub.Status.Install = v1alpha1.NewInstallPlanReference(installPlanRef)
 			sub.Status.State = v1alpha1.SubscriptionStateUpgradePending
+			sub.Status.InstallPlanGeneration = gen
 		}
-		if _, subErr := o.client.OperatorsV1alpha1().Subscriptions(namespace).UpdateStatus(sub); subErr != nil {
-			err = subErr
-		}
+
+		wg.Add(1)
+		go func(s v1alpha1.Subscription) {
+			defer wg.Done()
+
+			update := func() error {
+				// Update the status of the latest revision
+				latest, err := o.client.OperatorsV1alpha1().Subscriptions(s.GetNamespace()).Get(s.GetName(), getOpts)
+				if err != nil {
+					return err
+				}
+
+				latest.Status = s.Status
+				_, err = o.client.OperatorsV1alpha1().Subscriptions(namespace).UpdateStatus(latest)
+
+				return err
+			}
+			if err := retry.RetryOnConflict(retry.DefaultRetry, update); err != nil {
+				mu.Lock()
+				defer mu.Unlock()
+				errs = append(errs, err)
+			}
+		}(*sub)
 	}
-	return err
+	wg.Wait()
+
+	return utilerrors.NewAggregate(errs)
 }
 
-func (o *Operator) ensureInstallPlan(logger *logrus.Entry, namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup) (*corev1.ObjectReference, error) {
+func (o *Operator) ensureInstallPlan(logger *logrus.Entry, namespace string, gen int, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup) (*corev1.ObjectReference, error) {
 	if len(steps) == 0 && len(bundleLookups) == 0 {
 		return nil, nil
 	}
@@ -965,44 +999,16 @@ func (o *Operator) ensureInstallPlan(logger *logrus.Entry, namespace string, sub
 	}
 
 	for _, installPlan := range installPlans {
-		if installPlan.Status.CSVManifestsMatch(steps) {
-			logger.Infof("found InstallPlan with matching manifests: %s", installPlan.GetName())
-
-			ownerWasAdded := false
-			for _, sub := range subs {
-				ownerWasAdded = ownerWasAdded || !ownerutil.EnsureOwner(installPlan, sub)
-			}
-
-			out := installPlan.DeepCopy()
-			if ownerWasAdded {
-				out, err = o.client.OperatorsV1alpha1().InstallPlans(installPlan.GetNamespace()).Update(installPlan)
-				if err != nil {
-					return nil, err
-				}
-			}
-
-			// Use provided `installPlanApproval` to determine the appropriate phase
-			if installPlanApproval == v1alpha1.ApprovalAutomatic {
-				out.Status.Phase = v1alpha1.InstallPlanPhaseInstalling
-			} else {
-				out.Status.Phase = v1alpha1.InstallPlanPhaseRequiresApproval
-			}
-			for _, step := range out.Status.Plan {
-				step.Status = v1alpha1.StepStatusUnknown
-			}
-			res, err := o.client.OperatorsV1alpha1().InstallPlans(namespace).UpdateStatus(out)
-			if err != nil {
-				return nil, err
-			}
-			return reference.GetReference(res)
+		if installPlan.Spec.Generation == gen {
+			return reference.GetReference(installPlan)
 		}
 	}
-	logger.Warn("no installplan found with matching manifests, creating new one")
+	logger.Warn("no installplan found with matching generation, creating new one")
 
-	return o.createInstallPlan(namespace, subs, installPlanApproval, steps, bundleLookups)
+	return o.createInstallPlan(namespace, gen, subs, installPlanApproval, steps, bundleLookups)
 }
 
-func (o *Operator) createInstallPlan(namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup) (*corev1.ObjectReference, error) {
+func (o *Operator) createInstallPlan(namespace string, gen int, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup) (*corev1.ObjectReference, error) {
 	if len(steps) == 0 && len(bundleLookups) == 0 {
 		return nil, nil
 	}
@@ -1033,6 +1039,7 @@ func (o *Operator) createInstallPlan(namespace string, subs []*v1alpha1.Subscrip
 			ClusterServiceVersionNames: csvNames,
 			Approval:                   installPlanApproval,
 			Approved:                   installPlanApproval == v1alpha1.ApprovalAutomatic,
+			Generation:                 gen,
 		},
 	}
 	for _, sub := range subs {
diff --git a/pkg/lib/queueinformer/queueinformer_operator.go b/pkg/lib/queueinformer/queueinformer_operator.go
index e009fe221..147da0896 100644
--- a/pkg/lib/queueinformer/queueinformer_operator.go
+++ b/pkg/lib/queueinformer/queueinformer_operator.go
@@ -169,16 +169,13 @@ func (o *operator) Run(ctx context.Context) {
 				close(o.atLevel)
 				close(o.done)
 			}()
-			if err := o.start(ctx); err != nil {
-				o.logger.WithError(err).Error("error encountered during startup")
-				return
-			}
+			o.start(ctx)
 			<-ctx.Done()
 		}()
 	})
 }
 
-func (o *operator) start(ctx context.Context) error {
+func (o *operator) start(ctx context.Context) {
 	defer close(o.ready)
 
 	// goroutine will be unnecessary after https://github.com/kubernetes/enhancements/pull/1503
@@ -200,11 +197,12 @@ func (o *operator) start(ctx context.Context) error {
 	select {
 	case err := <-errs:
 		if err != nil {
-			return fmt.Errorf("operator not ready: %s", err.Error())
+			o.logger.Infof("operator not ready: %s", err.Error())
+			return
 		}
 		o.logger.Info("operator ready")
 	case <-ctx.Done():
-		return nil
+		return
 	}
 
 	o.logger.Info("starting informers...")
@@ -212,7 +210,8 @@ func (o *operator) start(ctx context.Context) error {
 
 	o.logger.Info("waiting for caches to sync...")
 	if ok := cache.WaitForCacheSync(ctx.Done(), o.hasSynced); !ok {
-		return fmt.Errorf("failed to wait for caches to sync")
+		o.logger.Info("failed to wait for caches to sync")
+		return
 	}
 
 	o.logger.Info("starting workers...")
@@ -221,8 +220,6 @@ func (o *operator) start(ctx context.Context) error {
 			go o.worker(ctx, queueInformer)
 		}
 	}
-
-	return nil
 }
 
 // worker runs a worker thread that just dequeues items, processes them, and marks them done.
diff --git a/pkg/package-server/provider/registry.go b/pkg/package-server/provider/registry.go
index ff0b1075a..456546e4e 100644
--- a/pkg/package-server/provider/registry.go
+++ b/pkg/package-server/provider/registry.go
@@ -412,7 +412,7 @@ func (p *RegistryProvider) Get(namespace, name string) (*operators.PackageManife
 func (p *RegistryProvider) List(namespace string, selector labels.Selector) (*operators.PackageManifestList, error) {
 	var pkgs []*operators.PackageManifest
 	if namespace == metav1.NamespaceAll {
-		all, err := p.pkgLister.List(selector)
+		all, err := p.pkgLister.List(labels.Everything())
 		if err != nil {
 			return nil, err
 		}
diff --git a/scripts/build_local.sh b/scripts/build_local.sh
index 6b72d7d34..03d02d1ff 100755
--- a/scripts/build_local.sh
+++ b/scripts/build_local.sh
@@ -5,18 +5,16 @@
 
 set -e
 
+if [ -z "$NO_MINIKUBE" ]; then
+  pgrep -f "[m]inikube" >/dev/null || minikube start --kubernetes-version="v1.16.2" --extra-config=apiserver.v=4 || { echo 'Cannot start minikube.'; exit 1; }
+  eval "$(minikube docker-env)" || { echo 'Cannot switch to minikube docker'; exit 1; }
+  kubectl config use-context minikube
+fi
+
 docker build -f local.Dockerfile -t quay.io/operator-framework/olm:local -t quay.io/operator-framework/olm-e2e:local ./bin
 docker build -f test/e2e/hang.Dockerfile -t hang:10 ./bin
 
-if [ -x "$(command -v kind)" ] && [[ "$(kubectl config current-context)" =~ ^kind-? ]]; then
+if [ -x "$(command -v kind)" ] && [ "$(kubectl config current-context)" = "kind" ]; then
   kind load docker-image quay.io/operator-framework/olm:local
   kind load docker-image quay.io/operator-framework/olm-e2e:local
-  kind load docker-image hang:10
-  exit 0 # don't bother with minikube if kind is active
-fi
-
-if [ -z "$NO_MINIKUBE" ]; then
-  pgrep -f "[m]inikube" >/dev/null || minikube start --kubernetes-version="v1.16.2" --extra-config=apiserver.v=4 || { echo 'Cannot start minikube.'; exit 1; }
-  eval "$(minikube docker-env)" || { echo 'Cannot switch to minikube docker'; exit 1; }
-  kubectl config use-context minikube
 fi


Test patch:
diff --git a/pkg/controller/operators/catalog/subscriptions_test.go b/pkg/controller/operators/catalog/subscriptions_test.go
index fc6125a26..e79930b93 100644
--- a/pkg/controller/operators/catalog/subscriptions_test.go
+++ b/pkg/controller/operators/catalog/subscriptions_test.go
@@ -18,7 +18,6 @@ import (
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/fakes"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clientfake"
-	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
 )
 
 func TestSyncSubscriptions(t *testing.T) {
@@ -60,6 +59,10 @@ func TestSyncSubscriptions(t *testing.T) {
 				clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)},
 				existingOLMObjs: []runtime.Object{
 					&v1alpha1.Subscription{
+						TypeMeta: metav1.TypeMeta{
+							Kind:       v1alpha1.SubscriptionKind,
+							APIVersion: v1alpha1.SchemeGroupVersion.String(),
+						},
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      "sub",
 							Namespace: testNamespace,
@@ -109,6 +112,10 @@ func TestSyncSubscriptions(t *testing.T) {
 			},
 			args: args{
 				obj: &v1alpha1.Subscription{
+					TypeMeta: metav1.TypeMeta{
+						Kind:       v1alpha1.SubscriptionKind,
+						APIVersion: v1alpha1.SchemeGroupVersion.String(),
+					},
 					ObjectMeta: metav1.ObjectMeta{
 						Name:      "sub",
 						Namespace: testNamespace,
@@ -147,7 +154,8 @@ func TestSyncSubscriptions(t *testing.T) {
 							Kind:       v1alpha1.InstallPlanKind,
 							APIVersion: v1alpha1.InstallPlanAPIVersion,
 						},
-						LastUpdated: now,
+						LastUpdated:           now,
+						InstallPlanGeneration: 1,
 					},
 				},
 			},
@@ -156,8 +164,9 @@ func TestSyncSubscriptions(t *testing.T) {
 					ClusterServiceVersionNames: []string{
 						"csv.v.1",
 					},
-					Approval: v1alpha1.ApprovalAutomatic,
-					Approved: true,
+					Approval:   v1alpha1.ApprovalAutomatic,
+					Approved:   true,
+					Generation: 1,
 				},
 				Status: v1alpha1.InstallPlanStatus{
 					Phase: v1alpha1.InstallPlanPhaseInstalling,
@@ -187,6 +196,10 @@ func TestSyncSubscriptions(t *testing.T) {
 				clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)},
 				existingOLMObjs: []runtime.Object{
 					&v1alpha1.Subscription{
+						TypeMeta: metav1.TypeMeta{
+							Kind:       v1alpha1.SubscriptionKind,
+							APIVersion: v1alpha1.SchemeGroupVersion.String(),
+						},
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      "sub",
 							Namespace: testNamespace,
@@ -238,6 +251,10 @@ func TestSyncSubscriptions(t *testing.T) {
 			},
 			args: args{
 				obj: &v1alpha1.Subscription{
+					TypeMeta: metav1.TypeMeta{
+						Kind:       v1alpha1.SubscriptionKind,
+						APIVersion: v1alpha1.SchemeGroupVersion.String(),
+					},
 					ObjectMeta: metav1.ObjectMeta{
 						Name:      "sub",
 						Namespace: testNamespace,
@@ -278,7 +295,8 @@ func TestSyncSubscriptions(t *testing.T) {
 							Kind:       v1alpha1.InstallPlanKind,
 							APIVersion: v1alpha1.InstallPlanAPIVersion,
 						},
-						LastUpdated: now,
+						LastUpdated:           now,
+						InstallPlanGeneration: 1,
 					},
 				},
 			},
@@ -287,8 +305,9 @@ func TestSyncSubscriptions(t *testing.T) {
 					ClusterServiceVersionNames: []string{
 						"csv.v.1",
 					},
-					Approval: v1alpha1.ApprovalAutomatic,
-					Approved: true,
+					Approval:   v1alpha1.ApprovalAutomatic,
+					Approved:   true,
+					Generation: 1,
 				},
 				Status: v1alpha1.InstallPlanStatus{
 					Phase: v1alpha1.InstallPlanPhaseInstalling,
@@ -318,6 +337,10 @@ func TestSyncSubscriptions(t *testing.T) {
 				clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)},
 				existingOLMObjs: []runtime.Object{
 					&v1alpha1.Subscription{
+						TypeMeta: metav1.TypeMeta{
+							Kind:       v1alpha1.SubscriptionKind,
+							APIVersion: v1alpha1.SchemeGroupVersion.String(),
+						},
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      "sub",
 							Namespace: testNamespace,
@@ -373,6 +396,10 @@ func TestSyncSubscriptions(t *testing.T) {
 			},
 			args: args{
 				obj: &v1alpha1.Subscription{
+					TypeMeta: metav1.TypeMeta{
+						Kind:       v1alpha1.SubscriptionKind,
+						APIVersion: v1alpha1.SchemeGroupVersion.String(),
+					},
 					ObjectMeta: metav1.ObjectMeta{
 						Name:      "sub",
 						Namespace: testNamespace,
@@ -413,7 +440,8 @@ func TestSyncSubscriptions(t *testing.T) {
 							Kind:       v1alpha1.InstallPlanKind,
 							APIVersion: v1alpha1.InstallPlanAPIVersion,
 						},
-						LastUpdated: now,
+						InstallPlanGeneration: 1,
+						LastUpdated:           now,
 					},
 				},
 			},
@@ -422,6 +450,7 @@ func TestSyncSubscriptions(t *testing.T) {
 					ClusterServiceVersionNames: []string{},
 					Approval:                   v1alpha1.ApprovalAutomatic,
 					Approved:                   true,
+					Generation:                 1,
 				},
 				Status: v1alpha1.InstallPlanStatus{
 					Phase:          v1alpha1.InstallPlanPhaseInstalling,
@@ -462,6 +491,10 @@ func TestSyncSubscriptions(t *testing.T) {
 						},
 					},
 					&v1alpha1.Subscription{
+						TypeMeta: metav1.TypeMeta{
+							Kind:       v1alpha1.SubscriptionKind,
+							APIVersion: v1alpha1.SchemeGroupVersion.String(),
+						},
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      "sub",
 							Namespace: testNamespace,
@@ -513,6 +546,10 @@ func TestSyncSubscriptions(t *testing.T) {
 			},
 			args: args{
 				obj: &v1alpha1.Subscription{
+					TypeMeta: metav1.TypeMeta{
+						Kind:       v1alpha1.SubscriptionKind,
+						APIVersion: v1alpha1.SchemeGroupVersion.String(),
+					},
 					ObjectMeta: metav1.ObjectMeta{
 						Name:      "sub",
 						Namespace: testNamespace,
@@ -553,7 +590,8 @@ func TestSyncSubscriptions(t *testing.T) {
 							Kind:       v1alpha1.InstallPlanKind,
 							APIVersion: v1alpha1.InstallPlanAPIVersion,
 						},
-						LastUpdated: now,
+						LastUpdated:           now,
+						InstallPlanGeneration: 1,
 					},
 				},
 			},
@@ -562,8 +600,9 @@ func TestSyncSubscriptions(t *testing.T) {
 					ClusterServiceVersionNames: []string{
 						"csv.v.2",
 					},
-					Approval: v1alpha1.ApprovalAutomatic,
-					Approved: true,
+					Approval:   v1alpha1.ApprovalAutomatic,
+					Approved:   true,
+					Generation: 1,
 				},
 				Status: v1alpha1.InstallPlanStatus{
 					Phase: v1alpha1.InstallPlanPhaseInstalling,
@@ -602,6 +641,10 @@ func TestSyncSubscriptions(t *testing.T) {
 						},
 					},
 					&v1alpha1.Subscription{
+						TypeMeta: metav1.TypeMeta{
+							Kind:       v1alpha1.SubscriptionKind,
+							APIVersion: v1alpha1.SchemeGroupVersion.String(),
+						},
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      "sub",
 							Namespace: testNamespace,
@@ -677,6 +720,10 @@ func TestSyncSubscriptions(t *testing.T) {
 			},
 			args: args{
 				obj: &v1alpha1.Subscription{
+					TypeMeta: metav1.TypeMeta{
+						Kind:       v1alpha1.SubscriptionKind,
+						APIVersion: v1alpha1.SchemeGroupVersion.String(),
+					},
 					ObjectMeta: metav1.ObjectMeta{
 						Name:      "sub",
 						Namespace: testNamespace,
@@ -717,7 +764,8 @@ func TestSyncSubscriptions(t *testing.T) {
 							Kind:       v1alpha1.InstallPlanKind,
 							APIVersion: v1alpha1.InstallPlanAPIVersion,
 						},
-						LastUpdated: now,
+						LastUpdated:           now,
+						InstallPlanGeneration: 1,
 					},
 				},
 			},
@@ -727,8 +775,9 @@ func TestSyncSubscriptions(t *testing.T) {
 						"csv.v.2",
 						"dep.v.1",
 					},
-					Approval: v1alpha1.ApprovalAutomatic,
-					Approved: true,
+					Approval:   v1alpha1.ApprovalAutomatic,
+					Approved:   true,
+					Generation: 1,
 				},
 				Status: v1alpha1.InstallPlanStatus{
 					Phase: v1alpha1.InstallPlanPhaseInstalling,
@@ -776,163 +825,6 @@ func TestSyncSubscriptions(t *testing.T) {
 				},
 			},
 		},
-		{
-			name: "Status/HaveCurrentCSV/SameManifests",
-			fields: fields{
-				clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)},
-				existingOLMObjs: []runtime.Object{
-					&v1alpha1.ClusterServiceVersion{
-						ObjectMeta: metav1.ObjectMeta{
-							Name:      "csv.v.1",
-							Namespace: testNamespace,
-						},
-						Status: v1alpha1.ClusterServiceVersionStatus{
-							Phase: v1alpha1.CSVPhaseSucceeded,
-						},
-					},
-					&v1alpha1.Subscription{
-						ObjectMeta: metav1.ObjectMeta{
-							Name:      "sub",
-							Namespace: testNamespace,
-						},
-						Spec: &v1alpha1.SubscriptionSpec{
-							CatalogSource:          "src",
-							CatalogSourceNamespace: testNamespace,
-						},
-						Status: v1alpha1.SubscriptionStatus{
-							CurrentCSV: "",
-							State:      "",
-						},
-					},
-					&v1alpha1.InstallPlan{
-						ObjectMeta: metav1.ObjectMeta{
-							Name:      "install-ip123",
-							Namespace: testNamespace,
-							SelfLink:  fmt.Sprintf("/apis/%s/namespaces/%s/%s/%s", v1alpha1.SchemeGroupVersion.String(), "installplans", testNamespace, "install-ip123"),
-						},
-						Spec: v1alpha1.InstallPlanSpec{
-							ClusterServiceVersionNames: []string{
-								"csv.v.1",
-							},
-							Approval: v1alpha1.ApprovalAutomatic,
-							Approved: true,
-						},
-						Status: v1alpha1.InstallPlanStatus{
-							Phase: v1alpha1.InstallPlanPhaseComplete,
-							CatalogSources: []string{
-								"src",
-							},
-							Plan: []*v1alpha1.Step{
-								{
-									Resolving: "csv.v.1",
-									Resource: v1alpha1.StepResource{
-										CatalogSource:          "src",
-										CatalogSourceNamespace: testNamespace,
-										Group:                  v1alpha1.GroupName,
-										Version:                v1alpha1.GroupVersion,
-										Kind:                   v1alpha1.ClusterServiceVersionKind,
-										Name:                   "csv.v.1",
-										Manifest:               "{}",
-									},
-								},
-							},
-						},
-					},
-				},
-				resolveSteps: []*v1alpha1.Step{
-					{
-						Resolving: "csv.v.1",
-						Resource: v1alpha1.StepResource{
-							CatalogSource:          "src",
-							CatalogSourceNamespace: testNamespace,
-							Group:                  v1alpha1.GroupName,
-							Version:                v1alpha1.GroupVersion,
-							Kind:                   v1alpha1.ClusterServiceVersionKind,
-							Name:                   "csv.v.1",
-							Manifest:               "{}",
-						},
-					},
-				},
-				resolveSubs: []*v1alpha1.Subscription{
-					{
-						TypeMeta: metav1.TypeMeta{
-							Kind:       v1alpha1.SubscriptionKind,
-							APIVersion: v1alpha1.SubscriptionCRDAPIVersion,
-						},
-						ObjectMeta: metav1.ObjectMeta{
-							Name:      "sub",
-							Namespace: testNamespace,
-						},
-						Spec: &v1alpha1.SubscriptionSpec{
-							CatalogSource:          "src",
-							CatalogSourceNamespace: testNamespace,
-						},
-						Status: v1alpha1.SubscriptionStatus{
-							CurrentCSV: "csv.v.1",
-							State:      "SubscriptionStateAtLatest",
-						},
-					},
-				},
-			},
-			args: args{
-				obj: &v1alpha1.Subscription{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "sub",
-						Namespace: testNamespace,
-					},
-					Spec: &v1alpha1.SubscriptionSpec{
-						CatalogSource:          "src",
-						CatalogSourceNamespace: testNamespace,
-					},
-					Status: v1alpha1.SubscriptionStatus{
-						CurrentCSV: "",
-						State:      "",
-					},
-				},
-			},
-			wantInstallPlan: &v1alpha1.InstallPlan{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:      "install-ip123",
-					Namespace: testNamespace,
-					SelfLink:  fmt.Sprintf("/apis/%s/namespaces/%s/%s/%s", v1alpha1.SchemeGroupVersion.String(), "installplans", testNamespace, "install-ip123"),
-					OwnerReferences: []metav1.OwnerReference{{
-						APIVersion:         v1alpha1.SubscriptionCRDAPIVersion,
-						Kind:               v1alpha1.SubscriptionKind,
-						Name:               "sub",
-						Controller:         &ownerutil.NotController,
-						BlockOwnerDeletion: &ownerutil.DontBlockOwnerDeletion,
-					}},
-				},
-				Spec: v1alpha1.InstallPlanSpec{
-					ClusterServiceVersionNames: []string{
-						"csv.v.1",
-					},
-					Approval: v1alpha1.ApprovalAutomatic,
-					Approved: true,
-				},
-				Status: v1alpha1.InstallPlanStatus{
-					Phase: v1alpha1.InstallPlanPhaseInstalling,
-					CatalogSources: []string{
-						"src",
-					},
-					Plan: []*v1alpha1.Step{
-						{
-							Resolving: "csv.v.1",
-							Resource: v1alpha1.StepResource{
-								CatalogSource:          "src",
-								CatalogSourceNamespace: testNamespace,
-								Group:                  v1alpha1.GroupName,
-								Version:                v1alpha1.GroupVersion,
-								Kind:                   v1alpha1.ClusterServiceVersionKind,
-								Name:                   "csv.v.1",
-								Manifest:               "{}",
-							},
-							Status: v1alpha1.StepStatusUnknown,
-						},
-					},
-				},
-			},
-		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/lib/queueinformer/queueinformer_operator_test.go b/pkg/lib/queueinformer/queueinformer_operator_test.go
index be3881bb6..560387364 100644
--- a/pkg/lib/queueinformer/queueinformer_operator_test.go
+++ b/pkg/lib/queueinformer/queueinformer_operator_test.go
@@ -18,7 +18,7 @@ func (f versionFunc) ServerVersion() (*version.Info, error) {
 	return (func() (*version.Info, error))(f)()
 }
 
-func TestOperatorRunChannelClosure(t *testing.T) {
+func TestOperatorRunReadyChannelClosed(t *testing.T) {
 	for _, tc := range []struct {
 		name string
 		// set up the operator under test and return a cleanup func to be invoked when the test completes
@@ -78,16 +78,10 @@ func TestOperatorRunChannelClosure(t *testing.T) {
 
 			o.Run(ctx)
 
-			timeout := time.After(time.Second)
-			for n, ch := range map[string]<-chan struct{}{
-				"ready": o.Ready(),
-				"done":  o.Done(),
-			} {
-				select {
-				case <-ch:
-				case <-timeout:
-					t.Errorf("timed out before %s channel closed", n)
-				}
+			select {
+			case <-o.Ready():
+			case <-time.After(time.Second):
+				t.Error("timed out before ready channel closed")
 			}
 		})
 	}
diff --git a/pkg/package-server/provider/registry_test.go b/pkg/package-server/provider/registry_test.go
index c5a38ef51..00528633f 100644
--- a/pkg/package-server/provider/registry_test.go
+++ b/pkg/package-server/provider/registry_test.go
@@ -8,7 +8,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"k8s.io/apimachinery/pkg/selection"
 	"net"
 	"os"
 	"path/filepath"
@@ -1077,316 +1076,6 @@ func TestRegistryProviderList(t *testing.T) {
 	}
 }
 
-type LabelReq struct {
-	key       string
-	op        selection.Operator
-	strValues []string
-}
-
-func TestRegistryProviderListLabels(t *testing.T) {
-	tests := []struct {
-		name             string
-		globalNS         string
-		labelReq         *LabelReq
-		registryClients  []*registryClient
-		requestNamespace string
-		expectedErr      string
-		expected         *operators.PackageManifestList
-	}{
-		{
-			name:     "PackagesFound/LabelsSupported/SingleNS",
-			globalNS: "ns",
-			labelReq: &LabelReq{
-				key: "catalog",
-				op:  selection.Exists,
-			},
-			registryClients: []*registryClient{
-				newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))),
-			},
-			requestNamespace: "ns",
-			expectedErr:      "",
-			expected: &operators.PackageManifestList{Items: []operators.PackageManifest{
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "prometheus",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "Red Hat",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "prometheus",
-						Provider: operators.AppLink{
-							Name: "Red Hat",
-						},
-						DefaultChannel: "preview",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "preview",
-								CurrentCSV: "prometheusoperator.0.22.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "etcd",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "CoreOS, Inc",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "etcd",
-						Provider: operators.AppLink{
-							Name: "CoreOS, Inc",
-						},
-						DefaultChannel: "alpha",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "alpha",
-								CurrentCSV: "etcdoperator.v0.9.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-			}},
-		},
-		{
-			name:     "PackagesFound/LabelsSupported/GlobalNS",
-			globalNS: "ns",
-			labelReq: &LabelReq{
-				key: "catalog",
-				op:  selection.Exists,
-			},
-			registryClients: []*registryClient{
-				newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))),
-			},
-			requestNamespace: "",
-			expectedErr:      "",
-			expected: &operators.PackageManifestList{Items: []operators.PackageManifest{
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "prometheus",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "Red Hat",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "prometheus",
-						Provider: operators.AppLink{
-							Name: "Red Hat",
-						},
-						DefaultChannel: "preview",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "preview",
-								CurrentCSV: "prometheusoperator.0.22.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "etcd",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "CoreOS, Inc",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "etcd",
-						Provider: operators.AppLink{
-							Name: "CoreOS, Inc",
-						},
-						DefaultChannel: "alpha",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "alpha",
-								CurrentCSV: "etcdoperator.v0.9.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-			}},
-		},
-		{
-			name:     "PackagesNotFound/LabelsNotSupported/GlobalNS",
-			globalNS: "",
-			labelReq: &LabelReq{
-				key: "catalog",
-				op:  selection.DoesNotExist,
-			},
-			registryClients: []*registryClient{
-				newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", ""), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))),
-			},
-			requestNamespace: "",
-			expectedErr:      "",
-			expected:         &operators.PackageManifestList{Items: []operators.PackageManifest{}},
-		},
-		{
-			name:     "PackagesFound/LabelsNotProvided/GlobalNS",
-			globalNS: "",
-			registryClients: []*registryClient{
-				newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))),
-			},
-			requestNamespace: "",
-			expectedErr:      "",
-			expected: &operators.PackageManifestList{Items: []operators.PackageManifest{
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "prometheus",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "Red Hat",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "prometheus",
-						Provider: operators.AppLink{
-							Name: "Red Hat",
-						},
-						DefaultChannel: "preview",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "preview",
-								CurrentCSV: "prometheusoperator.0.22.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-				{
-					ObjectMeta: metav1.ObjectMeta{
-						Name:      "etcd",
-						Namespace: "ns",
-						Labels: labels.Set{
-							"catalog":                         "cool-operators",
-							"catalog-namespace":               "ns",
-							"provider":                        "CoreOS, Inc",
-							"provider-url":                    "",
-							"operatorframework.io/arch.amd64": "supported",
-							"operatorframework.io/os.linux":   "supported",
-						},
-					},
-					Status: operators.PackageManifestStatus{
-						CatalogSource:          "cool-operators",
-						CatalogSourceNamespace: "ns",
-						PackageName:            "etcd",
-						Provider: operators.AppLink{
-							Name: "CoreOS, Inc",
-						},
-						DefaultChannel: "alpha",
-						Channels: []operators.PackageChannel{
-							{
-								Name:       "alpha",
-								CurrentCSV: "etcdoperator.v0.9.2",
-								CurrentCSVDesc: func() operators.CSVDescription {
-									csv := operatorsv1alpha1.ClusterServiceVersion{}
-									require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv))
-									return operators.CreateCSVDescription(&csv)
-								}(),
-							},
-						},
-					},
-				},
-			}},
-		},
-	}
-
-	for _, test := range tests {
-		t.Run(test.name, func(t *testing.T) {
-			ctx, cancel := context.WithCancel(context.TODO())
-			defer cancel()
-
-			lab := labels.NewSelector()
-			if test.labelReq != nil {
-				req, err := labels.NewRequirement(test.labelReq.key, test.labelReq.op, test.labelReq.strValues)
-				require.NoError(t, err)
-				lab = lab.Add(*req)
-			}
-
-			provider, err := NewFakeRegistryProvider(ctx, nil, nil, test.globalNS)
-			require.NoError(t, err)
-
-			for _, c := range test.registryClients {
-				require.NoError(t, provider.refreshCache(ctx, c))
-			}
-
-			packageManifestList, err := provider.List(test.requestNamespace, lab)
-			if test.expectedErr != "" {
-				require.NotNil(t, err)
-				require.Equal(t, test.expectedErr, err.Error())
-			} else {
-				require.Nil(t, err)
-			}
-
-			require.Equal(t, len(test.expected.Items), len(packageManifestList.Items))
-			require.ElementsMatch(t, test.expected.Items, packageManifestList.Items)
-		})
-	}
-}
-
 func newTestRegistryClient(t *testing.T, catsrc *operatorsv1alpha1.CatalogSource) *registryClient {
 	conn, err := grpc.Dial(address+catsrc.Status.RegistryServiceStatus.Port, grpc.WithInsecure())
 	require.NoError(t, err, "could not set up test grpc connection")
diff --git a/test/e2e/csv_e2e_test.go b/test/e2e/csv_e2e_test.go
index 4213d1b5e..c1050f877 100644
--- a/test/e2e/csv_e2e_test.go
+++ b/test/e2e/csv_e2e_test.go
@@ -2489,15 +2489,26 @@ func TestUpdateCSVInPlace(t *testing.T) {
 	require.NoError(t, err)
 	require.NotNil(t, dep)
 
-	// Create "updated" CSV
+	// Create "updated" CSV with a different image
 	strategyNew := strategy
 	strategyNew.DeploymentSpecs[0].Spec.Template.Spec.Containers = []corev1.Container{
 		{
-			Name:  genName("nginx-"),
-			Image: *dummyImage,
+			Name:    genName("hat"),
+			Image:   "quay.io/coreos/mock-extension-apiserver:master",
+			Command: []string{"/bin/mock-extension-apiserver"},
+			Args: []string{
+				"-v=4",
+				"--mock-kinds",
+				"fedora",
+				"--mock-group-version",
+				"group.version",
+				"--secure-port",
+				"5443",
+				"--debug",
+			},
 			Ports: []corev1.ContainerPort{
 				{
-					ContainerPort: 80,
+					ContainerPort: 5443,
 				},
 			},
 			ImagePullPolicy: corev1.PullIfNotPresent,
diff --git a/test/e2e/installplan_e2e_test.go b/test/e2e/installplan_e2e_test.go
index 378fdc01c..9aedd8ac5 100644
--- a/test/e2e/installplan_e2e_test.go
+++ b/test/e2e/installplan_e2e_test.go
@@ -4,6 +4,7 @@ import (
 	"errors"
 	"fmt"
 	"strings"
+	"sync"
 	"testing"
 	"time"
 
@@ -23,7 +24,8 @@ import (
 	"k8s.io/client-go/util/retry"
 	"k8s.io/kubernetes/pkg/apis/rbac"
 
-	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
+	operatorsv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
+	operatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
@@ -31,7 +33,7 @@ import (
 	opver "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/version"
 )
 
-type checkInstallPlanFunc func(fip *v1alpha1.InstallPlan) bool
+type checkInstallPlanFunc func(fip *operatorsv1alpha1.InstallPlan) bool
 
 func validateCRDVersions(t *testing.T, c operatorclient.ClientInterface, name string, expectedVersions map[string]struct{}) {
 	// Retrieve CRD information
@@ -52,8 +54,8 @@ func validateCRDVersions(t *testing.T, c operatorclient.ClientInterface, name st
 	require.Equal(t, 0, len(expectedVersions), "Actual CRD versions do not match expected")
 }
 
-func buildInstallPlanPhaseCheckFunc(phases ...v1alpha1.InstallPlanPhase) checkInstallPlanFunc {
-	return func(fip *v1alpha1.InstallPlan) bool {
+func buildInstallPlanPhaseCheckFunc(phases ...operatorsv1alpha1.InstallPlanPhase) checkInstallPlanFunc {
+	return func(fip *operatorsv1alpha1.InstallPlan) bool {
 		satisfiesAny := false
 		for _, phase := range phases {
 			satisfiesAny = satisfiesAny || fip.Status.Phase == phase
@@ -62,11 +64,11 @@ func buildInstallPlanPhaseCheckFunc(phases ...v1alpha1.InstallPlanPhase) checkIn
 	}
 }
 
-func buildInstallPlanCleanupFunc(crc versioned.Interface, namespace string, installPlan *v1alpha1.InstallPlan) cleanupFunc {
+func buildInstallPlanCleanupFunc(crc versioned.Interface, namespace string, installPlan *operatorsv1alpha1.InstallPlan) cleanupFunc {
 	return func() {
 		deleteOptions := &metav1.DeleteOptions{}
 		for _, step := range installPlan.Status.Plan {
-			if step.Resource.Kind == v1alpha1.ClusterServiceVersionKind {
+			if step.Resource.Kind == operatorsv1alpha1.ClusterServiceVersionKind {
 				if err := crc.OperatorsV1alpha1().ClusterServiceVersions(namespace).Delete(step.Resource.Name, deleteOptions); err != nil {
 					fmt.Println(err)
 				}
@@ -88,12 +90,12 @@ func buildInstallPlanCleanupFunc(crc versioned.Interface, namespace string, inst
 	}
 }
 
-func fetchInstallPlan(t *testing.T, c versioned.Interface, name string, checkPhase checkInstallPlanFunc) (*v1alpha1.InstallPlan, error) {
+func fetchInstallPlan(t *testing.T, c versioned.Interface, name string, checkPhase checkInstallPlanFunc) (*operatorsv1alpha1.InstallPlan, error) {
 	return fetchInstallPlanWithNamespace(t, c, name, testNamespace, checkPhase)
 }
 
-func fetchInstallPlanWithNamespace(t *testing.T, c versioned.Interface, name string, namespace string, checkPhase checkInstallPlanFunc) (*v1alpha1.InstallPlan, error) {
-	var fetchedInstallPlan *v1alpha1.InstallPlan
+func fetchInstallPlanWithNamespace(t *testing.T, c versioned.Interface, name string, namespace string, checkPhase checkInstallPlanFunc) (*operatorsv1alpha1.InstallPlan, error) {
+	var fetchedInstallPlan *operatorsv1alpha1.InstallPlan
 	var err error
 
 	err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
@@ -108,8 +110,8 @@ func fetchInstallPlanWithNamespace(t *testing.T, c versioned.Interface, name str
 }
 
 // do not return an error if the installplan has not been created yet
-func waitForInstallPlan(t *testing.T, c versioned.Interface, name string, namespace string, checkPhase checkInstallPlanFunc) (*v1alpha1.InstallPlan, error) {
-	var fetchedInstallPlan *v1alpha1.InstallPlan
+func waitForInstallPlan(t *testing.T, c versioned.Interface, name string, namespace string, checkPhase checkInstallPlanFunc) (*operatorsv1alpha1.InstallPlan, error) {
+	var fetchedInstallPlan *operatorsv1alpha1.InstallPlan
 	var err error
 
 	err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
@@ -123,10 +125,10 @@ func waitForInstallPlan(t *testing.T, c versioned.Interface, name string, namesp
 	return fetchedInstallPlan, err
 }
 
-func newNginxInstallStrategy(name string, permissions []v1alpha1.StrategyDeploymentPermissions, clusterPermissions []v1alpha1.StrategyDeploymentPermissions) v1alpha1.NamedInstallStrategy {
+func newNginxInstallStrategy(name string, permissions []operatorsv1alpha1.StrategyDeploymentPermissions, clusterPermissions []operatorsv1alpha1.StrategyDeploymentPermissions) operatorsv1alpha1.NamedInstallStrategy {
 	// Create an nginx details deployment
-	details := v1alpha1.StrategyDetailsDeployment{
-		DeploymentSpecs: []v1alpha1.StrategyDeploymentSpec{
+	details := operatorsv1alpha1.StrategyDetailsDeployment{
+		DeploymentSpecs: []operatorsv1alpha1.StrategyDeploymentSpec{
 			{
 				Name: name,
 				Spec: appsv1.DeploymentSpec{
@@ -153,8 +155,8 @@ func newNginxInstallStrategy(name string, permissions []v1alpha1.StrategyDeploym
 		Permissions:        permissions,
 		ClusterPermissions: clusterPermissions,
 	}
-	namedStrategy := v1alpha1.NamedInstallStrategy{
-		StrategyName: v1alpha1.InstallStrategyNameDeployment,
+	namedStrategy := operatorsv1alpha1.NamedInstallStrategy{
+		StrategyName: operatorsv1alpha1.InstallStrategyNameDeployment,
 		StrategySpec: details,
 	}
 
@@ -182,42 +184,42 @@ func newCRD(plural string) apiextensions.CustomResourceDefinition {
 	return crd
 }
 
-func newCSV(name, namespace, replaces string, version semver.Version, owned []apiextensions.CustomResourceDefinition, required []apiextensions.CustomResourceDefinition, namedStrategy v1alpha1.NamedInstallStrategy) v1alpha1.ClusterServiceVersion {
+func newCSV(name, namespace, replaces string, version semver.Version, owned []apiextensions.CustomResourceDefinition, required []apiextensions.CustomResourceDefinition, namedStrategy operatorsv1alpha1.NamedInstallStrategy) operatorsv1alpha1.ClusterServiceVersion {
 	csvType = metav1.TypeMeta{
-		Kind:       v1alpha1.ClusterServiceVersionKind,
-		APIVersion: v1alpha1.GroupVersion,
+		Kind:       operatorsv1alpha1.ClusterServiceVersionKind,
+		APIVersion: operatorsv1alpha1.GroupVersion,
 	}
 
-	csv := v1alpha1.ClusterServiceVersion{
+	csv := operatorsv1alpha1.ClusterServiceVersion{
 		TypeMeta: csvType,
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      name,
 			Namespace: namespace,
 		},
-		Spec: v1alpha1.ClusterServiceVersionSpec{
+		Spec: operatorsv1alpha1.ClusterServiceVersionSpec{
 			Replaces:       replaces,
 			Version:        opver.OperatorVersion{version},
 			MinKubeVersion: "0.0.0",
-			InstallModes: []v1alpha1.InstallMode{
+			InstallModes: []operatorsv1alpha1.InstallMode{
 				{
-					Type:      v1alpha1.InstallModeTypeOwnNamespace,
+					Type:      operatorsv1alpha1.InstallModeTypeOwnNamespace,
 					Supported: true,
 				},
 				{
-					Type:      v1alpha1.InstallModeTypeSingleNamespace,
+					Type:      operatorsv1alpha1.InstallModeTypeSingleNamespace,
 					Supported: true,
 				},
 				{
-					Type:      v1alpha1.InstallModeTypeMultiNamespace,
+					Type:      operatorsv1alpha1.InstallModeTypeMultiNamespace,
 					Supported: true,
 				},
 				{
-					Type:      v1alpha1.InstallModeTypeAllNamespaces,
+					Type:      operatorsv1alpha1.InstallModeTypeAllNamespaces,
 					Supported: true,
 				},
 			},
 			InstallStrategy: namedStrategy,
-			CustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{
+			CustomResourceDefinitions: operatorsv1alpha1.CustomResourceDefinitions{
 				Owned:    nil,
 				Required: nil,
 			},
@@ -237,7 +239,7 @@ func newCSV(name, namespace, replaces string, version semver.Version, owned []ap
 				}
 			}
 		}
-		desc := v1alpha1.CRDDescription{
+		desc := operatorsv1alpha1.CRDDescription{
 			Name:        crd.GetName(),
 			Version:     crdVersion,
 			Kind:        crd.Spec.Names.Plural,
@@ -259,7 +261,7 @@ func newCSV(name, namespace, replaces string, version semver.Version, owned []ap
 				}
 			}
 		}
-		desc := v1alpha1.CRDDescription{
+		desc := operatorsv1alpha1.CRDDescription{
 			Name:        crd.GetName(),
 			Version:     crdVersion,
 			Kind:        crd.Spec.Names.Plural,
@@ -328,13 +330,13 @@ func TestInstallPlanWithCSVsAcrossMultipleCatalogSources(t *testing.T) {
 
 	// Create the catalog sources
 	require.NotEqual(t, "", testNamespace)
-	_, cleanupDependentCatalogSource := createInternalCatalogSource(t, c, crc, dependentCatalogName, testNamespace, dependentManifests, []apiextensions.CustomResourceDefinition{dependentCRD}, []v1alpha1.ClusterServiceVersion{dependentCSV})
+	_, cleanupDependentCatalogSource := createInternalCatalogSource(t, c, crc, dependentCatalogName, testNamespace, dependentManifests, []apiextensions.CustomResourceDefinition{dependentCRD}, []operatorsv1alpha1.ClusterServiceVersion{dependentCSV})
 	defer cleanupDependentCatalogSource()
 	// Attempt to get the catalog source before creating install plan
 	_, err := fetchCatalogSource(t, crc, dependentCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 	require.NoError(t, err)
 
-	_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, nil, []v1alpha1.ClusterServiceVersion{mainCSV})
+	_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, nil, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 	defer cleanupMainCatalogSource()
 	// Attempt to get the catalog source before creating install plan
 	_, err = fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
@@ -342,14 +344,14 @@ func TestInstallPlanWithCSVsAcrossMultipleCatalogSources(t *testing.T) {
 
 	// Create expected install plan step sources
 	expectedStepSources := map[registry.ResourceKey]registry.ResourceKey{
-		registry.ResourceKey{Name: dependentCRD.Name, Kind: "CustomResourceDefinition"}:                                                                       {Name: dependentCatalogName, Namespace: testNamespace},
-		registry.ResourceKey{Name: dependentPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}:                                                          {Name: dependentCatalogName, Namespace: testNamespace},
-		registry.ResourceKey{Name: mainPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}:                                                               {Name: mainCatalogName, Namespace: testNamespace},
-		registry.ResourceKey{Name: strings.Join([]string{dependentPackageStable, dependentCatalogName, testNamespace}, "-"), Kind: v1alpha1.SubscriptionKind}: {Name: dependentCatalogName, Namespace: testNamespace},
+		registry.ResourceKey{Name: dependentCRD.Name, Kind: "CustomResourceDefinition"}:                                                                                {Name: dependentCatalogName, Namespace: testNamespace},
+		registry.ResourceKey{Name: dependentPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}:                                                          {Name: dependentCatalogName, Namespace: testNamespace},
+		registry.ResourceKey{Name: mainPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}:                                                               {Name: mainCatalogName, Namespace: testNamespace},
+		registry.ResourceKey{Name: strings.Join([]string{dependentPackageStable, dependentCatalogName, testNamespace}, "-"), Kind: operatorsv1alpha1.SubscriptionKind}: {Name: dependentCatalogName, Namespace: testNamespace},
 	}
 
 	subscriptionName := genName("sub-nginx-")
-	subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+	subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 	defer subscriptionCleanup()
 
 	subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -359,14 +361,14 @@ func TestInstallPlanWithCSVsAcrossMultipleCatalogSources(t *testing.T) {
 	installPlanName := subscription.Status.InstallPlanRef.Name
 
 	// Wait for InstallPlan to be status: Complete before checking resource presence
-	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 	require.NoError(t, err)
 	log(fmt.Sprintf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase))
 
-	require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+	require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 	// Fetch installplan again to check for unnecessary control loops
-	fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *v1alpha1.InstallPlan) bool {
+	fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *operatorsv1alpha1.InstallPlan) bool {
 		compareResources(t, fetchedInstallPlan, fip)
 		return true
 	})
@@ -421,14 +423,14 @@ EXPECTED:
 		},
 	}
 
-	updateInternalCatalog(t, c, crc, dependentCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{dependentCRD}, []v1alpha1.ClusterServiceVersion{dependentCSV, updatedDependentCSV}, dependentManifests)
+	updateInternalCatalog(t, c, crc, dependentCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{dependentCRD}, []operatorsv1alpha1.ClusterServiceVersion{dependentCSV, updatedDependentCSV}, dependentManifests)
 
 	// Wait for subscription to update
 	updatedDepSubscription, err := fetchSubscription(t, crc, testNamespace, strings.Join([]string{dependentPackageStable, dependentCatalogName, testNamespace}, "-"), subscriptionHasCurrentCSV(updatedDependentCSV.GetName()))
 	require.NoError(t, err)
 
 	// Verify installplan created and installed
-	fetchedUpdatedDepInstallPlan, err := fetchInstallPlan(t, crc, updatedDepSubscription.Status.InstallPlanRef.Name, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+	fetchedUpdatedDepInstallPlan, err := fetchInstallPlan(t, crc, updatedDepSubscription.Status.InstallPlanRef.Name, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 	require.NoError(t, err)
 	log(fmt.Sprintf("Install plan %s fetched with status %s", fetchedUpdatedDepInstallPlan.GetName(), fetchedUpdatedDepInstallPlan.Status.Phase))
 	require.NotEqual(t, fetchedInstallPlan.GetName(), fetchedUpdatedDepInstallPlan.GetName())
@@ -498,15 +500,15 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 
 		// Create the catalog source
 		mainCatalogSourceName := genName("mock-ocs-main-" + strings.ToLower(t.Name()) + "-")
-		_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{dependentCRD, mainCRD}, []v1alpha1.ClusterServiceVersion{dependentBetaCSV, dependentStableCSV, mainStableCSV, mainBetaCSV})
+		_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{dependentCRD, mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{dependentBetaCSV, dependentStableCSV, mainStableCSV, mainBetaCSV})
 		defer cleanupCatalogSource()
 		// Attempt to get the catalog source before creating install plan(s)
 		_, err := fetchCatalogSource(t, crc, mainCatalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		expectedSteps := map[registry.ResourceKey]struct{}{
-			registry.ResourceKey{Name: mainCRD.Name, Kind: "CustomResourceDefinition"}:              {},
-			registry.ResourceKey{Name: mainPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}: {},
+			registry.ResourceKey{Name: mainCRD.Name, Kind: "CustomResourceDefinition"}:                       {},
+			registry.ResourceKey{Name: mainPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}: {},
 		}
 
 		// Create the preexisting CRD and CSV
@@ -519,7 +521,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 		t.Log("Dependent CRD and preexisting CSV created")
 
 		subscriptionName := genName("sub-nginx-")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -529,14 +531,14 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 		installPlanName := subscription.Status.Install.Name
 
 		// Wait for InstallPlan to be status: Complete or Failed before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 		require.NoError(t, err)
 		t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Fetch installplan again to check for unnecessary control loops
-		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *v1alpha1.InstallPlan) bool {
+		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *operatorsv1alpha1.InstallPlan) bool {
 			compareResources(t, fetchedInstallPlan, fip)
 			return true
 		})
@@ -623,14 +625,14 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 
 		// Create the catalog source
 		mainCatalogSourceName := genName("mock-ocs-main-" + strings.ToLower(t.Name()) + "-")
-		_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{dependentCRD, mainCRD}, []v1alpha1.ClusterServiceVersion{dependentBetaCSV, dependentStableCSV, mainStableCSV, mainBetaCSV})
+		_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{dependentCRD, mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{dependentBetaCSV, dependentStableCSV, mainStableCSV, mainBetaCSV})
 		defer cleanupCatalogSource()
 		// Attempt to get the catalog source before creating install plan(s)
 		_, err := fetchCatalogSource(t, crc, mainCatalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -640,19 +642,19 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 		installPlanName := subscription.Status.Install.Name
 
 		// Wait for InstallPlan to be status: Complete or failed before checking resource presence
-		completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed)
+		completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed)
 		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, completeOrFailedFunc)
 		require.NoError(t, err)
 		t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Ensure that the desired resources have been created
 		expectedSteps := map[registry.ResourceKey]struct{}{
-			registry.ResourceKey{Name: mainCRD.Name, Kind: "CustomResourceDefinition"}:                                                                             {},
-			registry.ResourceKey{Name: dependentCRD.Name, Kind: "CustomResourceDefinition"}:                                                                        {},
-			registry.ResourceKey{Name: dependentPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}:                                                           {},
-			registry.ResourceKey{Name: mainPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}:                                                                {},
-			registry.ResourceKey{Name: strings.Join([]string{dependentPackageStable, mainCatalogSourceName, testNamespace}, "-"), Kind: v1alpha1.SubscriptionKind}: {},
+			registry.ResourceKey{Name: mainCRD.Name, Kind: "CustomResourceDefinition"}:                                                                                      {},
+			registry.ResourceKey{Name: dependentCRD.Name, Kind: "CustomResourceDefinition"}:                                                                                 {},
+			registry.ResourceKey{Name: dependentPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}:                                                           {},
+			registry.ResourceKey{Name: mainPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}:                                                                {},
+			registry.ResourceKey{Name: strings.Join([]string{dependentPackageStable, mainCatalogSourceName, testNamespace}, "-"), Kind: operatorsv1alpha1.SubscriptionKind}: {},
 		}
 
 		require.Equal(t, len(expectedSteps), len(fetchedInstallPlan.Status.Plan), "number of expected steps does not match installed")
@@ -679,7 +681,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 		require.NoError(t, crc.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(mainStableCSV.GetName(), &metav1.DeleteOptions{}))
 
 		// existing cleanup should remove this
-		createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, "", v1alpha1.ApprovalAutomatic)
+		createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 		subscription, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
 		require.NoError(t, err)
@@ -688,14 +690,14 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
 		installPlanName = subscription.Status.Install.Name
 
 		// Wait for InstallPlan to be status: Complete or Failed before checking resource presence
-		fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+		fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 		require.NoError(t, err)
 		t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Fetch installplan again to check for unnecessary control loops
-		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *v1alpha1.InstallPlan) bool {
+		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *operatorsv1alpha1.InstallPlan) bool {
 			compareResources(t, fetchedInstallPlan, fip)
 			return true
 		})
@@ -721,13 +723,13 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 	// excluded: new CRD, same version, same schema - won't trigger a CRD update
 	tests := []struct {
 		name          string
-		expectedPhase v1alpha1.InstallPlanPhase
+		expectedPhase operatorsv1alpha1.InstallPlanPhase
 		oldCRD        *apiextensions.CustomResourceDefinition
 		newCRD        *apiextensions.CustomResourceDefinition
 	}{
 		{
 			name:          "all existing versions are present, different (backwards compatible) schema",
-			expectedPhase: v1alpha1.InstallPlanPhaseComplete,
+			expectedPhase: operatorsv1alpha1.InstallPlanPhaseComplete,
 			oldCRD: func() *apiextensions.CustomResourceDefinition {
 				oldCRD := newCRD(mainCRDPlural + "a")
 				oldCRD.Spec.Version = ""
@@ -779,7 +781,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 		},
 		{
 			name:          "all existing versions are present, different (backwards incompatible) schema",
-			expectedPhase: v1alpha1.InstallPlanPhaseFailed,
+			expectedPhase: operatorsv1alpha1.InstallPlanPhaseFailed,
 			oldCRD: func() *apiextensions.CustomResourceDefinition {
 				oldCRD := newCRD(mainCRDPlural + "b")
 				oldCRD.Spec.Version = ""
@@ -831,7 +833,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 		},
 		{
 			name:          "missing existing versions in new CRD",
-			expectedPhase: v1alpha1.InstallPlanPhaseFailed,
+			expectedPhase: operatorsv1alpha1.InstallPlanPhaseFailed,
 			oldCRD: func() *apiextensions.CustomResourceDefinition {
 				oldCRD := newCRD(mainCRDPlural + "c")
 				oldCRD.Spec.Version = ""
@@ -888,7 +890,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 		},
 		{
 			name:          "existing version is present in new CRD (deprecated field)",
-			expectedPhase: v1alpha1.InstallPlanPhaseComplete,
+			expectedPhase: operatorsv1alpha1.InstallPlanPhaseComplete,
 			oldCRD: func() *apiextensions.CustomResourceDefinition {
 				oldCRD := newCRD(mainCRDPlural + "d")
 				oldCRD.Spec.Version = "v1alpha1"
@@ -971,7 +973,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 
 			// Create the catalog source
 			mainCatalogSourceName := genName("mock-ocs-main-")
-			_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{*tt.oldCRD}, []v1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV})
+			_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{*tt.oldCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV})
 			defer cleanupCatalogSource()
 
 			// Attempt to get the catalog source before creating install plan(s)
@@ -979,7 +981,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 			require.NoError(t, err)
 
 			subscriptionName := genName("sub-nginx-alpha-")
-			cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+			cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 			defer cleanupSubscription()
 
 			subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -989,16 +991,16 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 			installPlanName := subscription.Status.InstallPlanRef.Name
 
 			// Wait for InstallPlan to be status: Complete or failed before checking resource presence
-			completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed)
+			completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed)
 			fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, completeOrFailedFunc)
 			require.NoError(t, err)
 			t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
-			require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+			require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 			// Ensure that the desired resources have been created
 			expectedSteps := map[registry.ResourceKey]struct{}{
-				registry.ResourceKey{Name: tt.oldCRD.Name, Kind: "CustomResourceDefinition"}:            {},
-				registry.ResourceKey{Name: mainPackageStable, Kind: v1alpha1.ClusterServiceVersionKind}: {},
+				registry.ResourceKey{Name: tt.oldCRD.Name, Kind: "CustomResourceDefinition"}:                     {},
+				registry.ResourceKey{Name: mainPackageStable, Kind: operatorsv1alpha1.ClusterServiceVersionKind}: {},
 			}
 
 			require.Equal(t, len(expectedSteps), len(fetchedInstallPlan.Status.Plan), "number of expected steps does not match installed")
@@ -1023,7 +1025,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 			require.NoError(t, err)
 			defer cleanupCR()
 
-			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.newCRD}, []v1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV}, mainManifests)
+			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.newCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV}, mainManifests)
 			// Attempt to get the catalog source before creating install plan(s)
 			_, err = fetchCatalogSource(t, crc, mainCatalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
 			require.NoError(t, err)
@@ -1048,7 +1050,7 @@ func TestInstallPlanWithCRDSchemaChange(t *testing.T) {
 			installPlanName = subscription.Status.InstallPlanRef.Name
 
 			// Wait for InstallPlan to be status: Complete or Failed before checking resource presence
-			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 			require.NoError(t, err)
 			t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
@@ -1072,14 +1074,14 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 	// excluded: new CRD, same version, same schema - won't trigger a CRD update
 	tests := []struct {
 		name            string
-		expectedPhase   v1alpha1.InstallPlanPhase
+		expectedPhase   operatorsv1alpha1.InstallPlanPhase
 		oldCRD          *apiextensions.CustomResourceDefinition
 		intermediateCRD *apiextensions.CustomResourceDefinition
 		newCRD          *apiextensions.CustomResourceDefinition
 	}{
 		{
 			name:          "upgrade CRD with deprecated version",
-			expectedPhase: v1alpha1.InstallPlanPhaseComplete,
+			expectedPhase: operatorsv1alpha1.InstallPlanPhaseComplete,
 			oldCRD: func() *apiextensions.CustomResourceDefinition {
 				oldCRD := newCRD(mainCRDPlural)
 				oldCRD.Spec.Version = "v1alpha1"
@@ -1166,7 +1168,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 
 			// Create the catalog source
 			mainCatalogSourceName := genName("mock-ocs-main-")
-			_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{*tt.oldCRD}, []v1alpha1.ClusterServiceVersion{mainStableCSV})
+			_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{*tt.oldCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainStableCSV})
 			defer cleanupCatalogSource()
 
 			// Attempt to get the catalog source before creating install plan(s)
@@ -1175,7 +1177,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 
 			subscriptionName := genName("sub-nginx-")
 			// this subscription will be cleaned up below without the clean up function
-			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 			subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
 			require.NoError(t, err)
@@ -1184,11 +1186,11 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 			installPlanName := subscription.Status.Install.Name
 
 			// Wait for InstallPlan to be status: Complete or failed before checking resource presence
-			completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed)
+			completeOrFailedFunc := buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed)
 			fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, completeOrFailedFunc)
 			require.NoError(t, err)
 			t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
-			require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+			require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 			// Ensure CRD versions are accurate
 			expectedVersions := map[string]struct{}{
@@ -1209,7 +1211,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 				},
 			}
 
-			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.intermediateCRD}, []v1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV}, mainManifests)
+			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.intermediateCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainStableCSV, mainBetaCSV}, mainManifests)
 			// Attempt to get the catalog source before creating install plan(s)
 			_, err = fetchCatalogSource(t, crc, mainCatalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
 			require.NoError(t, err)
@@ -1220,7 +1222,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 			require.NoError(t, crc.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(mainStableCSV.GetName(), &metav1.DeleteOptions{}))
 
 			// existing cleanup should remove this
-			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, "", v1alpha1.ApprovalAutomatic)
+			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, betaChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 			subscription, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
 			require.NoError(t, err)
@@ -1229,7 +1231,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 			installPlanName = subscription.Status.Install.Name
 
 			// Wait for InstallPlan to be status: Complete or Failed before checking resource presence
-			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 			require.NoError(t, err)
 			t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
@@ -1260,7 +1262,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 				},
 			}
 
-			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.newCRD}, []v1alpha1.ClusterServiceVersion{mainBetaCSV, mainDeltaCSV}, mainManifests)
+			updateInternalCatalog(t, c, crc, mainCatalogSourceName, testNamespace, []apiextensions.CustomResourceDefinition{*tt.newCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainBetaCSV, mainDeltaCSV}, mainManifests)
 			// Attempt to get the catalog source before creating install plan(s)
 			_, err = fetchCatalogSource(t, crc, mainCatalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
 			require.NoError(t, err)
@@ -1271,7 +1273,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 			require.NoError(t, crc.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(mainBetaCSV.GetName(), &metav1.DeleteOptions{}))
 
 			// existing cleanup should remove this
-			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, deltaChannel, "", v1alpha1.ApprovalAutomatic)
+			createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, mainPackageName, deltaChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 			subscription, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
 			require.NoError(t, err)
@@ -1280,7 +1282,7 @@ func TestInstallPlanWithDeprecatedVersionCRD(t *testing.T) {
 			installPlanName = subscription.Status.Install.Name
 
 			// Wait for InstallPlan to be status: Complete or Failed before checking resource presence
-			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+			fetchedInstallPlan, err = fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 			require.NoError(t, err)
 			t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
@@ -1353,7 +1355,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 
 		// Generate permissions
 		serviceAccountName := genName("nginx-sa")
-		permissions := []v1alpha1.StrategyDeploymentPermissions{
+		permissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1366,7 +1368,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Generate permissions
-		clusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		clusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1392,14 +1394,14 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 				DefaultChannelName: stableChannel,
 			},
 		}
-		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV})
+		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 		defer cleanupMainCatalogSource()
 		// Attempt to get the catalog source before creating install plan
 		_, err := fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-update-perms1")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -1411,17 +1413,17 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		installPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Verify CSV is created
 		_, err = awaitCSV(t, crc, testNamespace, mainCSV.GetName(), csvSucceededChecker)
 		require.NoError(t, err)
 
 		// Update CatalogSource with a new CSV with more permissions
-		updatedPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		updatedPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1438,7 +1440,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 				},
 			},
 		}
-		updatedClusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		updatedClusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1469,7 +1471,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Update catalog with updated CSV with more permissions
-		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
+		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
 
 		_, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanDifferentChecker(fetchedInstallPlan.GetName()))
 		require.NoError(t, err)
@@ -1477,9 +1479,9 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		updatedInstallPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
 
 		// Wait for csv to update
 		_, err = awaitCSV(t, crc, testNamespace, updatedCSV.GetName(), csvSucceededChecker)
@@ -1528,7 +1530,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 
 		// Generate permissions
 		serviceAccountName := genName("nginx-sa")
-		permissions := []v1alpha1.StrategyDeploymentPermissions{
+		permissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1546,7 +1548,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Generate permissions
-		clusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		clusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1577,14 +1579,14 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 				DefaultChannelName: stableChannel,
 			},
 		}
-		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV})
+		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 		defer cleanupMainCatalogSource()
 		// Attempt to get the catalog source before creating install plan
 		_, err := fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-update-perms1")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -1596,17 +1598,17 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		installPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Verify CSV is created
 		_, err = awaitCSV(t, crc, testNamespace, mainCSV.GetName(), csvSucceededChecker)
 		require.NoError(t, err)
 
 		// Update CatalogSource with a new CSV with more permissions
-		updatedPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		updatedPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1618,7 +1620,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 				},
 			},
 		}
-		updatedClusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		updatedClusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1647,7 +1649,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Update catalog with updated CSV with more permissions
-		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
+		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
 
 		// Wait for subscription to update its status
 		_, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanDifferentChecker(fetchedInstallPlan.GetName()))
@@ -1656,9 +1658,9 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		updatedInstallPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
 
 		// Wait for csv to update
 		_, err = awaitCSV(t, crc, testNamespace, updatedCSV.GetName(), csvSucceededChecker)
@@ -1738,7 +1740,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 
 		// Generate permissions
 		serviceAccountName := genName("nginx-sa")
-		permissions := []v1alpha1.StrategyDeploymentPermissions{
+		permissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1751,7 +1753,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Generate permissions
-		clusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+		clusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 			{
 				ServiceAccountName: serviceAccountName,
 				Rules: []rbacv1.PolicyRule{
@@ -1778,14 +1780,14 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 				DefaultChannelName: stableChannel,
 			},
 		}
-		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV})
+		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 		defer cleanupMainCatalogSource()
 		// Attempt to get the catalog source before creating install plan
 		_, err := fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-stompy-")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -1797,18 +1799,18 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		installPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Verify CSV is created
 		csv, err := awaitCSV(t, crc, testNamespace, mainCSV.GetName(), csvSucceededChecker)
 		require.NoError(t, err)
 
 		modifiedEnv := []corev1.EnvVar{{Name: "EXAMPLE", Value: "value"}}
-		modifiedDetails := v1alpha1.StrategyDetailsDeployment{
-			DeploymentSpecs: []v1alpha1.StrategyDeploymentSpec{
+		modifiedDetails := operatorsv1alpha1.StrategyDetailsDeployment{
+			DeploymentSpecs: []operatorsv1alpha1.StrategyDeploymentSpec{
 				{
 					Name: deploymentName,
 					Spec: appsv1.DeploymentSpec{
@@ -1836,8 +1838,8 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			Permissions:        permissions,
 			ClusterPermissions: clusterPermissions,
 		}
-		csv.Spec.InstallStrategy = v1alpha1.NamedInstallStrategy{
-			StrategyName: v1alpha1.InstallStrategyNameDeployment,
+		csv.Spec.InstallStrategy = operatorsv1alpha1.NamedInstallStrategy{
+			StrategyName: operatorsv1alpha1.InstallStrategyNameDeployment,
 			StrategySpec: modifiedDetails,
 		}
 		_, err = crc.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Update(csv)
@@ -1873,7 +1875,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 			},
 		}
 		// Update catalog with updated CSV with more permissions
-		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
+		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV, updatedCSV}, updatedManifests)
 
 		_, err = fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanDifferentChecker(fetchedInstallPlan.GetName()))
 		require.NoError(t, err)
@@ -1881,9 +1883,9 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		updatedInstallPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedInstallPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedUpdatedInstallPlan.Status.Phase)
 
 		// Wait for csv to update
 		_, err = awaitCSV(t, crc, testNamespace, updatedCSV.GetName(), csvSucceededChecker)
@@ -1985,14 +1987,14 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		}
 
 		// Create the catalog sources
-		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []v1alpha1.ClusterServiceVersion{mainCSV})
+		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{mainCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 		defer cleanupMainCatalogSource()
 		// Attempt to get the catalog source before creating install plan
 		_, err := fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-update-before-")
-		createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
 		require.NoError(t, err)
@@ -2003,13 +2005,13 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		installPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Fetch installplan again to check for unnecessary control loops
-		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *v1alpha1.InstallPlan) bool {
+		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *operatorsv1alpha1.InstallPlan) bool {
 			compareResources(t, fetchedInstallPlan, fip)
 			return true
 		})
@@ -2019,7 +2021,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		_, err = awaitCSV(t, crc, testNamespace, mainCSV.GetName(), csvAnyChecker)
 		require.NoError(t, err)
 
-		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{updatedCRD}, []v1alpha1.ClusterServiceVersion{mainCSV}, mainManifests)
+		updateInternalCatalog(t, c, crc, mainCatalogName, testNamespace, []apiextensions.CustomResourceDefinition{updatedCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV}, mainManifests)
 
 		// Update the subscription resource
 		err = crc.OperatorsV1alpha1().Subscriptions(testNamespace).DeleteCollection(metav1.NewDeleteOptions(0), metav1.ListOptions{})
@@ -2027,7 +2029,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 
 		// existing cleanup should remove this
 		subscriptionName = genName("sub-nginx-update-after-")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		// Wait for subscription to update
@@ -2035,7 +2037,7 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		require.NoError(t, err)
 
 		// Verify installplan created and installed
-		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedSubscription.Status.InstallPlanRef.Name, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedUpdatedInstallPlan, err := fetchInstallPlan(t, crc, updatedSubscription.Status.InstallPlanRef.Name, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 		require.NotEqual(t, fetchedInstallPlan.GetName(), fetchedUpdatedInstallPlan.GetName())
 
@@ -2170,14 +2172,14 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		}
 
 		// Create the catalog sources
-		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{updatedCRD}, []v1alpha1.ClusterServiceVersion{mainCSV})
+		_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, testNamespace, mainManifests, []apiextensions.CustomResourceDefinition{updatedCRD}, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
 		defer cleanupMainCatalogSource()
 		// Attempt to get the catalog source before creating install plan
 		_, err = fetchCatalogSource(t, crc, mainCatalogName, testNamespace, catalogSourceRegistryPodSynced)
 		require.NoError(t, err)
 
 		subscriptionName := genName("sub-nginx-update2-")
-		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+		subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 		defer subscriptionCleanup()
 
 		subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -2189,13 +2191,13 @@ func TestUpdateCatalogForSubscription(t *testing.T) {
 		installPlanName := subscription.Status.InstallPlanRef.Name
 
 		// Wait for InstallPlan to be status: Complete before checking resource presence
-		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete))
+		fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
 		require.NoError(t, err)
 
-		require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+		require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 
 		// Fetch installplan again to check for unnecessary control loops
-		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *v1alpha1.InstallPlan) bool {
+		fetchedInstallPlan, err = fetchInstallPlan(t, crc, fetchedInstallPlan.GetName(), func(fip *operatorsv1alpha1.InstallPlan) bool {
 			compareResources(t, fetchedInstallPlan, fip)
 			return true
 		})
@@ -2260,7 +2262,7 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
 
 	// Generate permissions
 	serviceAccountName := genName("nginx-sa")
-	permissions := []v1alpha1.StrategyDeploymentPermissions{
+	permissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 		{
 			ServiceAccountName: serviceAccountName,
 			Rules: []rbacv1.PolicyRule{
@@ -2273,7 +2275,7 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
 		},
 	}
 	// Generate permissions
-	clusterPermissions := []v1alpha1.StrategyDeploymentPermissions{
+	clusterPermissions := []operatorsv1alpha1.StrategyDeploymentPermissions{
 		{
 			ServiceAccountName: serviceAccountName,
 			Rules: []rbacv1.PolicyRule{
@@ -2300,7 +2302,7 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
 
 	// Create CatalogSource
 	mainCatalogSourceName := genName("nginx-catalog")
-	_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{stableCSV})
+	_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []operatorsv1alpha1.ClusterServiceVersion{stableCSV})
 	defer cleanupCatalogSource()
 
 	// Attempt to get CatalogSource
@@ -2308,7 +2310,7 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
 	require.NoError(t, err)
 
 	subscriptionName := genName("sub-nginx-")
-	subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, packageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+	subscriptionCleanup := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, mainCatalogSourceName, packageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 	defer subscriptionCleanup()
 
 	subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -2318,9 +2320,9 @@ func TestCreateInstallPlanWithPermissions(t *testing.T) {
 	installPlanName := subscription.Status.Install.Name
 
 	// Attempt to get InstallPlan
-	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseFailed, v1alpha1.InstallPlanPhaseComplete))
+	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed, operatorsv1alpha1.InstallPlanPhaseComplete))
 	require.NoError(t, err)
-	require.NotEqual(t, v1alpha1.InstallPlanPhaseFailed, fetchedInstallPlan.Status.Phase, "InstallPlan failed")
+	require.NotEqual(t, operatorsv1alpha1.InstallPlanPhaseFailed, fetchedInstallPlan.Status.Phase, "InstallPlan failed")
 
 	// Expect correct RBAC resources to be resolved and created
 	expectedSteps := map[registry.ResourceKey]struct{}{
@@ -2548,7 +2550,7 @@ func TestInstallPlanCRDValidation(t *testing.T) {
 	c := newKubeClient(t)
 	crc := newCRClient(t)
 	catalogSourceName := genName("mock-nginx-")
-	_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, catalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csv})
+	_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, catalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []operatorsv1alpha1.ClusterServiceVersion{csv})
 	defer cleanupCatalogSource()
 
 	// Attempt to get the catalog source before creating install plan
@@ -2556,7 +2558,7 @@ func TestInstallPlanCRDValidation(t *testing.T) {
 	require.NoError(t, err)
 
 	subscriptionName := genName("sub-nginx-")
-	cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogSourceName, packageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
+	cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogSourceName, packageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 	defer cleanupSubscription()
 
 	subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionHasInstallPlanChecker)
@@ -2566,11 +2568,11 @@ func TestInstallPlanCRDValidation(t *testing.T) {
 	installPlanName := subscription.Status.InstallPlanRef.Name
 
 	// Wait for InstallPlan to be status: Complete before checking resource presence
-	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseComplete, v1alpha1.InstallPlanPhaseFailed))
+	fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete, operatorsv1alpha1.InstallPlanPhaseFailed))
 	require.NoError(t, err)
 	t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
 
-	require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+	require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
 }
 
 func TestInstallPlanUnpacksBundleImage(t *testing.T) {
@@ -2589,15 +2591,15 @@ func TestInstallPlanUnpacksBundleImage(t *testing.T) {
 		require.NoError(t, c.KubernetesInterface().CoreV1().Namespaces().Delete(ns.GetName(), deleteOpts))
 	}()
 
-	catsrc := &v1alpha1.CatalogSource{
+	catsrc := &operatorsv1alpha1.CatalogSource{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      genName("kiali-"),
 			Namespace: ns.GetName(),
 			Labels:    map[string]string{"olm.catalogSource": "kaili-catalog"},
 		},
-		Spec: v1alpha1.CatalogSourceSpec{
+		Spec: operatorsv1alpha1.CatalogSourceSpec{
 			Image:      "quay.io/olmtest/single-bundle-index:1.0.0",
-			SourceType: v1alpha1.SourceTypeGrpc,
+			SourceType: operatorsv1alpha1.SourceTypeGrpc,
 		},
 	}
 	catsrc, err = crc.OperatorsV1alpha1().CatalogSources(catsrc.GetNamespace()).Create(catsrc)
@@ -2609,16 +2611,16 @@ func TestInstallPlanUnpacksBundleImage(t *testing.T) {
 
 	// Generate a Subscription
 	subName := genName("kiali-")
-	createSubscriptionForCatalog(t, crc, catsrc.GetNamespace(), subName, catsrc.GetName(), "kiali", stableChannel, "", v1alpha1.ApprovalAutomatic)
+	createSubscriptionForCatalog(t, crc, catsrc.GetNamespace(), subName, catsrc.GetName(), "kiali", stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
 
 	sub, err := fetchSubscription(t, crc, catsrc.GetNamespace(), subName, subscriptionHasInstallPlanChecker)
 	require.NoError(t, err)
 
 	// Wait for the expected InstallPlan's execution to either fail or succeed
 	ipName := sub.Status.InstallPlanRef.Name
-	ip, err := waitForInstallPlan(t, crc, ipName, sub.GetNamespace(), buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseFailed, v1alpha1.InstallPlanPhaseComplete))
+	ip, err := waitForInstallPlan(t, crc, ipName, sub.GetNamespace(), buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed, operatorsv1alpha1.InstallPlanPhaseComplete))
 	require.NoError(t, err)
-	require.Equal(t, v1alpha1.InstallPlanPhaseComplete, ip.Status.Phase, "InstallPlan not complete")
+	require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, ip.Status.Phase, "InstallPlan not complete")
 
 	// Ensure the InstallPlan contains the steps resolved from the bundle image
 	operatorName := "kiali-operator"
@@ -2645,3 +2647,161 @@ func TestInstallPlanUnpacksBundleImage(t *testing.T) {
 	}
 	require.Lenf(t, expectedSteps, 0, "Actual resource steps do not match expected: %#v", expectedSteps)
 }
+
+// TestInstallPlanConsistentGeneration verifies that, in cases where there are multiple options to fulfil a dependency
+// across multiple catalogs, we only generate one installplan with one set of resolved resources.
+func TestInstallPlanConsistentGeneration(t *testing.T) {
+
+	// Configure catalogs:
+	//  - one catalog with a package that has a dependency
+	//  - several duplicate catalog with a package that satisfies the dependency
+	// Install the package from the main catalog
+	// Should see only 1 installplan created
+	// Should see the main CSV installed
+
+	defer cleaner.NotifyTestComplete(t, true)
+
+	log := func(s string) {
+		t.Logf("%s: %s", time.Now().Format("15:04:05.9999"), s)
+	}
+
+	ns := &corev1.Namespace{}
+	ns.SetName(genName("ns-"))
+
+	c := newKubeClient(t)
+	crc := newCRClient(t)
+
+	// Create a namespace an OperatorGroup
+	ns, err := c.KubernetesInterface().CoreV1().Namespaces().Create(ns)
+	require.NoError(t, err)
+	deleteOpts := &metav1.DeleteOptions{}
+	defer func() {
+		require.NoError(t, c.KubernetesInterface().CoreV1().Namespaces().Delete(ns.GetName(), deleteOpts))
+	}()
+
+	og := &operatorsv1.OperatorGroup{}
+	og.SetName("og")
+	_, err = crc.OperatorsV1().OperatorGroups(ns.GetName()).Create(og)
+	require.NoError(t, err)
+
+	mainPackageName := genName("nginx-")
+	dependentPackageName := genName("nginxdep-")
+
+	mainPackageStable := fmt.Sprintf("%s-stable", mainPackageName)
+	dependentPackageStable := fmt.Sprintf("%s-stable", dependentPackageName)
+
+	stableChannel := "stable"
+
+	mainNamedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil)
+	dependentNamedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil)
+
+	crdPlural := genName("ins-")
+
+	dependentCRD := newCRD(crdPlural)
+	mainCSV := newCSV(mainPackageStable, ns.GetName(), "", semver.MustParse("0.1.0"), nil, []apiextensions.CustomResourceDefinition{dependentCRD}, mainNamedStrategy)
+	dependentCSV := newCSV(dependentPackageStable, ns.GetName(), "", semver.MustParse("0.1.0"), []apiextensions.CustomResourceDefinition{dependentCRD}, nil, dependentNamedStrategy)
+
+	defer func() {
+		require.NoError(t, crc.OperatorsV1alpha1().Subscriptions(ns.GetName()).DeleteCollection(&metav1.DeleteOptions{}, metav1.ListOptions{}))
+	}()
+
+	dependentCatalogName := genName("mock-ocs-dependent-")
+	mainCatalogName := genName("mock-ocs-main-")
+
+	// Create separate manifests for each CatalogSource
+	mainManifests := []registry.PackageManifest{
+		{
+			PackageName: mainPackageName,
+			Channels: []registry.PackageChannel{
+				{Name: stableChannel, CurrentCSVName: mainPackageStable},
+			},
+			DefaultChannelName: stableChannel,
+		},
+	}
+
+	dependentManifests := []registry.PackageManifest{
+		{
+			PackageName: dependentPackageName,
+			Channels: []registry.PackageChannel{
+				{Name: stableChannel, CurrentCSVName: dependentPackageStable},
+			},
+			DefaultChannelName: stableChannel,
+		},
+	}
+
+	// Create the dependent catalog source
+	_, cleanupDependentCatalogSource := createInternalCatalogSource(t, c, crc, dependentCatalogName, ns.GetName(), dependentManifests, []apiextensions.CustomResourceDefinition{dependentCRD}, []operatorsv1alpha1.ClusterServiceVersion{dependentCSV})
+	defer cleanupDependentCatalogSource()
+
+	// Attempt to get the catalog source before creating install plan
+	dependentCatalogSource, err := fetchCatalogSource(t, crc, dependentCatalogName, ns.GetName(), catalogSourceRegistryPodSynced)
+	require.NoError(t, err)
+
+	// Create the alt dependent catalog sources
+	var wg sync.WaitGroup
+	for i := 0; i < 4; i++ { // Creating more increases the odds that the race condition will be triggered
+		wg.Add(1)
+		go func(i int) {
+			// Create a CatalogSource pointing to the grpc pod
+			addressSource := &operatorsv1alpha1.CatalogSource{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       operatorsv1alpha1.CatalogSourceKind,
+					APIVersion: operatorsv1alpha1.CatalogSourceCRDAPIVersion,
+				},
+				Spec: operatorsv1alpha1.CatalogSourceSpec{
+					SourceType: operatorsv1alpha1.SourceTypeGrpc,
+					Address:    dependentCatalogSource.Status.RegistryServiceStatus.Address(),
+				},
+			}
+			addressSource.SetName(genName("alt-dep-"))
+
+			_, err := crc.OperatorsV1alpha1().CatalogSources(ns.GetName()).Create(addressSource)
+			require.NoError(t, err)
+
+			// Attempt to get the catalog source before creating install plan
+			_, err = fetchCatalogSource(t, crc, addressSource.GetName(), ns.GetName(), catalogSourceRegistryPodSynced)
+			require.NoError(t, err)
+			wg.Done()
+		}(i)
+	}
+	wg.Wait()
+
+	// Create the main catalog source
+	_, cleanupMainCatalogSource := createInternalCatalogSource(t, c, crc, mainCatalogName, ns.GetName(), mainManifests, nil, []operatorsv1alpha1.ClusterServiceVersion{mainCSV})
+	defer cleanupMainCatalogSource()
+
+	// Attempt to get the catalog source before creating install plan
+	_, err = fetchCatalogSource(t, crc, mainCatalogName, ns.GetName(), catalogSourceRegistryPodSynced)
+	require.NoError(t, err)
+
+	subscriptionName := genName("sub-nginx-")
+	subscriptionCleanup := createSubscriptionForCatalog(t, crc, ns.GetName(), subscriptionName, mainCatalogName, mainPackageName, stableChannel, "", operatorsv1alpha1.ApprovalAutomatic)
+	defer subscriptionCleanup()
+
+	subscription, err := fetchSubscription(t, crc, ns.GetName(), subscriptionName, subscriptionHasInstallPlanChecker)
+	require.NoError(t, err)
+	require.NotNil(t, subscription)
+
+	installPlanName := subscription.Status.InstallPlanRef.Name
+
+	// Wait for InstallPlan to be status: Complete before checking resource presence
+	fetchedInstallPlan, err := fetchInstallPlanWithNamespace(t, crc, installPlanName, ns.GetName(), buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete))
+	require.NoError(t, err)
+	log(fmt.Sprintf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase))
+
+	require.Equal(t, operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)
+
+	// Verify CSV is created
+	_, err = awaitCSV(t, crc, ns.GetName(), mainCSV.GetName(), csvSucceededChecker)
+	require.NoError(t, err)
+
+	// Make sure to clean up the installed CRD
+	defer func() {
+		require.NoError(t, c.ApiextensionsV1beta1Interface().ApiextensionsV1beta1().CustomResourceDefinitions().Delete(dependentCRD.GetName(), deleteOpts))
+	}()
+
+	// ensure there is only one installplan
+	ips, err := crc.OperatorsV1alpha1().InstallPlans(ns.GetName()).List(metav1.ListOptions{})
+	require.NoError(t, err)
+	require.Equal(t, 1, len(ips.Items), "If this test fails it should be taken seriously and not treated as a flake. \n%v", ips.Items)
+}