Repository: Azure/ARO-RP
Pull request #2152 (2022-06-03 06:43:15)

Panic on AdminUpdate with MaintenanceTaskEverything
### Which issue this PR addresses:

<!--
Please include a link to the ADO work item as well as any GitHub issues.

Usage: `Fixes #<GitHub issue number>`, or `Fixes (paste link of issue)`.
-->
Fixes: https://msazure.visualstudio.com/AzureRedHatOpenShift/_workitems/edit/14361162

### What this PR does / why we need it: 
Admin put or patch fails with runtime error: index out of range [0] with length 0 when API server is unavailable (due to VMs being powered off)

<!--
Include a brief summary of what the PR is intended to accomplish and how the PR
does it. (2-3 sentences)
-->

### Test plan for issue:
Power off the VMs and run admin put or patch: update task starts, it will now skip the process, if there is no VMs with a Warn message

<!--
How did you test that this PR works?

- Are there unit tests?
- Are there integration/e2e tests?
- If it is not possible to write automated tests, explain why and document how
  to manually test and verify the feature.
-->

### Is there any documentation that needs to be updated for this PR?

<!--
- If yes and the docs are in GitHub, include doc updates in the PR.
- If yes and the docs are not in GitHub (i.e. ADO wiki), include a link to the
  docs.
- If no, explain why (e.g. "tech debt cleanup, N/A").
-->



Patch:
diff --git a/docs/deploy-development-rp.md b/docs/deploy-development-rp.md
index 2251b02da..7b1809330 100644
--- a/docs/deploy-development-rp.md
+++ b/docs/deploy-development-rp.md
@@ -176,14 +176,6 @@
   curl -X POST -k "https://localhost:8443/admin/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$RESOURCEGROUP/providers/Microsoft.RedHatOpenShift/openShiftClusters/$CLUSTER/upgrade"
   ```
 
-* Get container logs from an OpenShift pod in a cluster
-  ```bash
-  NAMESPACE=<namespace-name>
-  POD=<pod-name>
-  CONTAINER=<container-name>
-  curl -X GET -k "https://localhost:8443/admin/subscriptions/$AZURE_SUBSCRIPTION_ID/resourceGroups/$RESOURCEGROUP/providers/Microsoft.RedHatOpenShift/openShiftClusters/$CLUSTER/kubernetespodlogs?podname=$POD&namespace=$NAMESPACE&container=$CONTAINER"
-  ```
-
 ## Debugging
 
 * SSH to the bootstrap node:
diff --git a/hack/validate-imports/allowed-import-names.yaml b/hack/validate-imports/allowed-import-names.yaml
deleted file mode 100644
index 7f3ffa503..000000000
--- a/hack/validate-imports/allowed-import-names.yaml
+++ /dev/null
@@ -1,102 +0,0 @@
-allowedImportNames:
-  github.com/Azure/ARO-RP/pkg/frontend/middleware:
-    - ""
-    - frontendmiddleware
-  github.com/Azure/ARO-RP/pkg/metrics/statsd/cosmosdb:
-    - dbmetrics
-  github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1:
-    - arov1alpha1
-  github.com/Azure/ARO-RP/pkg/operator/apis/preview.aro.openshift.io/v1alpha1:
-    - aropreviewv1alpha1
-  github.com/Azure/ARO-RP/pkg/operator/clientset/versioned:
-    - aroclient
-  github.com/Azure/ARO-RP/pkg/operator/clientset/versioned/fake:
-    - arofake
-  github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/keyvault:
-    - keyvaultclient
-    - ""
-  github.com/Azure/ARO-RP/pkg/util/dynamichelper/discovery:
-    - utildiscovery
-  github.com/Azure/ARO-RP/pkg/util/embed:
-    - utilembed
-  github.com/Azure/ARO-RP/pkg/util/namespace:
-    - utilnamespace
-    - ""
-  github.com/Azure/ARO-RP/pkg/util/recover:
-    - utilrecover
-    - ""
-  github.com/Azure/ARO-RP/test/database:
-    - testdatabase
-  github.com/Azure/ARO-RP/test/util/dynamichelper:
-    - testdynamichelper
-  github.com/Azure/ARO-RP/test/util/log:
-    - testlog
-  github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac:
-    - azgraphrbac
-  github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault:
-    - azkeyvault
-  github.com/Azure/azure-sdk-for-go/storage:
-    - azstorage
-  github.com/coreos/stream-metadata-go/arch:
-    - coreosarch
-  github.com/googleapis/gnostic/openapiv2:
-    - openapi_v2
-  github.com/openshift/console-operator/pkg/api:
-    - consoleapi
-  github.com/openshift/installer/pkg/asset/installconfig/azure:
-    - icazure
-  github.com/openshift/installer/pkg/rhcos:
-    - rhcospkg
-  github.com/openshift/installer/pkg/types/azure:
-    - azuretypes
-  github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1:
-    - machinev1beta1
-  github.com/openshift/machine-api-operator/pkg/generated/clientset/versioned:
-    - maoclient
-  github.com/openshift/machine-api-operator/pkg/generated/clientset/versioned/fake:
-    - maofake
-  github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1:
-    - mcv1
-  github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned:
-    - mcoclient
-  github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/fake:
-    - mcofake
-  github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/typed/machineconfiguration.openshift.io/v1:
-    - mcoclientv1
-  github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1:
-    - monitoringv1
-  golang.org/x/crypto/ssh:
-    - ""
-    - cryptossh
-  k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:
-    - extensionsv1
-  k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:
-    - extensionsv1beta1
-  k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:
-    - extensionsclient
-  k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake:
-    - extensionsfake
-  k8s.io/apimachinery/pkg/api/errors:
-    - kerrors
-  k8s.io/apimachinery/pkg/apis/meta/v1:
-    - metav1
-  k8s.io/apimachinery/pkg/runtime:
-    - kruntime
-  k8s.io/apimachinery/pkg/runtime/serializer/json:
-    - kjson
-  k8s.io/apimachinery/pkg/util/rand:
-    - utilrand
-  k8s.io/apimachinery/pkg/util/runtime:
-    - utilruntime
-  k8s.io/apimachinery/pkg/version:
-    - kversion
-  k8s.io/client-go/testing:
-    - ktesting
-  k8s.io/client-go/tools/clientcmd/api/v1:
-    - clientcmdv1
-  k8s.io/client-go/tools/metrics:
-    - kmetrics
-  sigs.k8s.io/cluster-api-provider-azure/pkg/apis/azureprovider/v1beta1:
-    - azureproviderv1beta1
-  sigs.k8s.io/controller-runtime:
-    - ctrl
diff --git a/hack/validate-imports/validate-imports.go b/hack/validate-imports/validate-imports.go
index fdab631af..731ccd76e 100644
--- a/hack/validate-imports/validate-imports.go
+++ b/hack/validate-imports/validate-imports.go
@@ -4,20 +4,13 @@ package main
 // Licensed under the Apache License 2.0.
 
 import (
-	_ "embed"
 	"fmt"
 	"go/ast"
 	"go/token"
-	"log"
 	"regexp"
 	"strings"
-
-	"github.com/ghodss/yaml"
 )
 
-//go:embed allowed-import-names.yaml
-var allowedNamesYaml []byte
-
 func isStandardLibrary(path string) bool {
 	return !strings.ContainsRune(strings.SplitN(path, "/", 2)[0], '.')
 }
@@ -29,68 +22,16 @@ func validateUnderscoreImport(path string) error {
 
 	switch path {
 	case "net/http/pprof",
-		"github.com/Azure/ARO-RP/pkg/util/scheme",
-		"embed":
+		"github.com/Azure/ARO-RP/pkg/util/scheme":
 		return nil
 	}
 
 	return fmt.Errorf("invalid _ import %s", path)
 }
 
-type importValidator struct {
-	AllowedNames map[string][]string `json:"allowedImportNames"`
-}
-
-func initValidator() importValidator {
-	allowed := importValidator{}
-	err := yaml.Unmarshal(allowedNamesYaml, &allowed)
-	if err != nil {
-		log.Fatalf("error while unmarshalling allowed import names. err: %s", err)
-	}
-	return allowed
-}
-
-func (validator importValidator) isOkFromYaml(name, importedAs string) (bool, []string) {
-	for _, v := range validator.AllowedNames[name] {
-		if importedAs == v {
-			return true, nil
-		}
-	}
-	return false, validator.AllowedNames[name]
-}
-
-func (validator importValidator) validateImportName(name, importedAs string) error {
-	isAllowed, names := validator.isOkFromYaml(name, importedAs)
-
-	if isAllowed {
-		return nil
-	}
-
-	isAllowedFromRegex, namesRegex := isOkFromRegex(name, importedAs)
-
-	if isAllowedFromRegex {
-		return nil
-	}
-
-	names = append(names, namesRegex...)
-
-	return fmt.Errorf("%s is imported as %q, should be %q", name, importedAs, names)
-}
-
-func isOkFromRegex(name, importedAs string) (bool, []string) {
-	acceptableNames := acceptableNamesRegex(name)
-
-	for _, v := range acceptableNames {
-		if v == importedAs {
-			return true, nil
-		}
-	}
-	return false, acceptableNames
-}
-
-// acceptableNamesRegex returns a list of acceptable names for an import; empty
+// acceptableNames returns a list of acceptable names for an import; empty
 // string = no import override; nil list = don't care
-func acceptableNamesRegex(path string) []string {
+func acceptableNames(path string) []string {
 	m := regexp.MustCompile(`^github\.com/Azure/ARO-RP/pkg/api/(v[^/]*[0-9])$`).FindStringSubmatch(path)
 	if m != nil {
 		return []string{m[1]}
@@ -161,22 +102,101 @@ func acceptableNamesRegex(path string) []string {
 		return []string{m[1] + m[2] + "client"}
 	}
 
-	return []string{""}
-}
-
-func importedAs(spec *ast.ImportSpec) string {
-	if spec == nil {
-		return ""
-	}
-
-	if spec.Name == nil {
-		return ""
+	switch path {
+	case "github.com/Azure/ARO-RP/pkg/frontend/middleware":
+		return []string{"", "frontendmiddleware"}
+	case "github.com/Azure/ARO-RP/pkg/metrics/statsd/cosmosdb":
+		return []string{"dbmetrics"}
+	case "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1":
+		return []string{"arov1alpha1"}
+	case "github.com/Azure/ARO-RP/pkg/operator/apis/preview.aro.openshift.io/v1alpha1":
+		return []string{"aropreviewv1alpha1"}
+	case "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned":
+		return []string{"aroclient"}
+	case "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned/fake":
+		return []string{"arofake"}
+	case "github.com/Azure/ARO-RP/pkg/util/dynamichelper/discovery":
+		return []string{"utildiscovery"}
+	case "github.com/Azure/ARO-RP/pkg/util/namespace":
+		return []string{"", "utilnamespace"}
+	case "github.com/Azure/ARO-RP/pkg/util/recover":
+		return []string{"", "utilrecover"}
+	case "github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/keyvault":
+		return []string{"", "keyvaultclient"}
+	case "github.com/Azure/ARO-RP/test/database":
+		return []string{"testdatabase"}
+	case "github.com/Azure/ARO-RP/test/util/dynamichelper":
+		return []string{"testdynamichelper"}
+	case "github.com/Azure/ARO-RP/test/util/log":
+		return []string{"testlog"}
+	case "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac":
+		return []string{"azgraphrbac"}
+	case "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault":
+		return []string{"azkeyvault"}
+	case "github.com/Azure/azure-sdk-for-go/storage":
+		return []string{"azstorage"}
+	case "github.com/googleapis/gnostic/openapiv2":
+		return []string{"openapi_v2"}
+	case "github.com/openshift/console-operator/pkg/api":
+		return []string{"consoleapi"}
+	case "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1":
+		return []string{"mcv1"}
+	case "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned":
+		return []string{"mcoclient"}
+	case "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/fake":
+		return []string{"mcofake"}
+	case "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/typed/machineconfiguration.openshift.io/v1":
+		return []string{"mcoclientv1"}
+	case "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake":
+		return []string{"extensionsfake"}
+	case "github.com/openshift/installer/pkg/asset/installconfig/azure":
+		return []string{"icazure"}
+	case "github.com/openshift/installer/pkg/types/azure":
+		return []string{"azuretypes"}
+	case "github.com/coreos/stream-metadata-go/arch":
+		return []string{"coreosarch"}
+	case "github.com/openshift/installer/pkg/rhcos":
+		return []string{"rhcospkg"}
+	case "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1":
+		return []string{"monitoringv1"}
+	case "golang.org/x/crypto/ssh":
+		return []string{"", "cryptossh"}
+	case "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1":
+		return []string{"extensionsv1beta1"}
+	case "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1":
+		return []string{"extensionsv1"}
+	case "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset":
+		return []string{"extensionsclient"}
+	case "k8s.io/apimachinery/pkg/api/errors":
+		return []string{"kerrors"}
+	case "k8s.io/apimachinery/pkg/runtime":
+		return []string{"kruntime"}
+	case "k8s.io/apimachinery/pkg/apis/meta/v1":
+		return []string{"metav1"}
+	case "k8s.io/apimachinery/pkg/runtime/serializer/json":
+		return []string{"kjson"}
+	case "k8s.io/apimachinery/pkg/util/runtime":
+		return []string{"utilruntime"}
+	case "k8s.io/apimachinery/pkg/util/rand":
+		return []string{"utilrand"}
+	case "k8s.io/apimachinery/pkg/version":
+		return []string{"kversion"}
+	case "k8s.io/client-go/testing":
+		return []string{"ktesting"}
+	case "k8s.io/client-go/tools/clientcmd/api/v1":
+		return []string{"clientcmdv1"}
+	case "k8s.io/client-go/tools/metrics":
+		return []string{"kmetrics"}
+	case "sigs.k8s.io/cluster-api-provider-azure/pkg/apis/azureprovider/v1beta1":
+		return []string{"azureproviderv1beta1"}
+	case "sigs.k8s.io/controller-runtime":
+		return []string{"ctrl"}
 	}
 
-	return spec.Name.Name
+	return []string{""}
 }
 
-func validateImports(path string, fset *token.FileSet, f *ast.File) []error {
+func validateImports(path string, fset *token.FileSet, f *ast.File) (errs []error) {
 	for _, prefix := range []string{
 		"pkg/client/",
 		"pkg/database/cosmosdb/zz_generated_",
@@ -190,67 +210,62 @@ func validateImports(path string, fset *token.FileSet, f *ast.File) []error {
 		}
 	}
 
-	errs := make([]error, 0)
-	validator := initValidator()
+nextImport:
 	for _, imp := range f.Imports {
-		if err := validator.validateImport(imp); err != nil {
-			errs = append(errs, err)
-		}
-	}
+		value := strings.Trim(imp.Path.Value, `"`)
 
-	return errs
-}
-
-func (validator importValidator) validateImport(imp *ast.ImportSpec) error {
-	packageName := strings.Trim(imp.Path.Value, `"`)
-
-	if imp.Name != nil && imp.Name.Name == "." {
-		//accept dotimports because we check them with golangci-lint
-		return nil
-	}
-
-	if imp.Name != nil && imp.Name.Name == "_" {
-		err := validateUnderscoreImport(packageName)
-		if err != nil {
-			return err
+		if imp.Name != nil && imp.Name.Name == "." {
+			//accept dotimports because we check them with golangci-lint
+			continue
 		}
-		return nil
-	}
 
-	switch packageName {
-	case "sigs.k8s.io/yaml", "gopkg.in/yaml.v2":
-		return fmt.Errorf("%s is imported; use github.com/ghodss/yaml", packageName)
-	case "github.com/google/uuid", "github.com/satori/go.uuid":
-		return fmt.Errorf("%s is imported; use github.com/gofrs/uuid", packageName)
-	}
-
-	if strings.HasPrefix(packageName, "github.com/Azure/azure-sdk-for-go/profiles") {
-		return fmt.Errorf("%s is imported; use github.com/Azure/azure-sdk-for-go/services/*", packageName)
-	}
+		if imp.Name != nil && imp.Name.Name == "_" {
+			err := validateUnderscoreImport(value)
+			if err != nil {
+				errs = append(errs, err)
+			}
+			continue
+		}
 
-	if strings.HasSuffix(packageName, "/scheme") &&
-		packageName != "k8s.io/client-go/kubernetes/scheme" {
-		return fmt.Errorf("%s is imported; should probably use k8s.io/client-go/kubernetes/scheme", packageName)
-	}
+		switch value {
+		case "sigs.k8s.io/yaml", "gopkg.in/yaml.v2":
+			errs = append(errs, fmt.Errorf("%s is imported; use github.com/ghodss/yaml", value))
+			continue nextImport
+		case "github.com/google/uuid", "github.com/satori/go.uuid":
+			errs = append(errs, fmt.Errorf("%s is imported; use github.com/gofrs/uuid", value))
+			continue nextImport
+		}
 
-	if isStandardLibrary(packageName) {
-		if imp.Name != nil {
-			return fmt.Errorf("overridden import %s", packageName)
+		if strings.HasPrefix(value, "github.com/Azure/azure-sdk-for-go/profiles") {
+			errs = append(errs, fmt.Errorf("%s is imported; use github.com/Azure/azure-sdk-for-go/services/*", value))
+			continue
 		}
-		return nil
-	}
 
-	names := acceptableNamesRegex(packageName)
+		if strings.HasSuffix(value, "/scheme") &&
+			value != "k8s.io/client-go/kubernetes/scheme" {
+			errs = append(errs, fmt.Errorf("%s is imported; should probably use k8s.io/client-go/kubernetes/scheme", value))
+			continue
+		}
 
-	if names == nil {
-		return nil
-	}
+		if isStandardLibrary(value) {
+			if imp.Name != nil {
+				errs = append(errs, fmt.Errorf("overridden import %s", value))
+			}
+			continue
+		}
 
-	importedAs := importedAs(imp)
-	err := validator.validateImportName(packageName, importedAs)
-	if err != nil {
-		return err
+		names := acceptableNames(value)
+		if names == nil {
+			continue
+		}
+		for _, name := range names {
+			if name == "" && imp.Name == nil ||
+				name != "" && imp.Name != nil && imp.Name.Name == name {
+				continue nextImport
+			}
+		}
+		errs = append(errs, fmt.Errorf("%s is imported as %q, should be %q", value, imp.Name, names))
 	}
 
-	return nil
+	return
 }
diff --git a/pkg/cluster/storageaccounts.go b/pkg/cluster/storageaccounts.go
index d16658afd..8aa983054 100644
--- a/pkg/cluster/storageaccounts.go
+++ b/pkg/cluster/storageaccounts.go
@@ -74,6 +74,10 @@ func (m *manager) enableServiceEndpoints(ctx context.Context) error {
 // The encryption flag is set to false/disabled for legacy storage accounts.
 func (m *manager) migrateStorageAccounts(ctx context.Context) error {
 	resourceGroup := stringutils.LastTokenByte(m.doc.OpenShiftCluster.Properties.ClusterProfile.ResourceGroupID, '/')
+	if len(m.doc.OpenShiftCluster.Properties.WorkerProfiles) == 0 {
+		m.log.Error("skipping migrateStorageAccounts due to missing WorkerProfiles.")
+		return nil
+	}
 	clusterStorageAccountName := "cluster" + m.doc.OpenShiftCluster.Properties.StorageSuffix
 	registryStorageAccountName := m.doc.OpenShiftCluster.Properties.ImageRegistryStorageAccountName
 
diff --git a/pkg/frontend/admin_openshiftcluster_kubernetespods_logs.go b/pkg/frontend/admin_openshiftcluster_kubernetespods_logs.go
deleted file mode 100644
index ec2bd8802..000000000
--- a/pkg/frontend/admin_openshiftcluster_kubernetespods_logs.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package frontend
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"context"
-	"net/http"
-	"path/filepath"
-	"strings"
-
-	"github.com/gorilla/mux"
-	"github.com/sirupsen/logrus"
-
-	"github.com/Azure/ARO-RP/pkg/api"
-	"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
-	"github.com/Azure/ARO-RP/pkg/frontend/middleware"
-)
-
-func (f *frontend) getAdminKubernetesPodLogs(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
-	log := ctx.Value(middleware.ContextKeyLog).(*logrus.Entry)
-	r.URL.Path = filepath.Dir(r.URL.Path)
-	b, err := f._getAdminKubernetesPodLogs(ctx, r, log)
-
-	if err == nil {
-		w.Header().Set("Content-Type", "text/plain")
-	}
-
-	adminReply(log, w, nil, b, err)
-}
-
-func (f *frontend) _getAdminKubernetesPodLogs(ctx context.Context, r *http.Request, log *logrus.Entry) ([]byte, error) {
-	vars := mux.Vars(r)
-
-	namespace, containerName, podName := r.URL.Query().Get("namespace"), r.URL.Query().Get("container"), r.URL.Query().Get("podname")
-
-	err := validateAdminKubernetesPodLogs(namespace, podName, containerName)
-	if err != nil {
-		return nil, err
-	}
-
-	resourceID := strings.TrimPrefix(r.URL.Path, "/admin")
-
-	doc, err := f.dbOpenShiftClusters.Get(ctx, resourceID)
-	switch {
-	case cosmosdb.IsErrorStatusCode(err, http.StatusNotFound):
-		return nil, api.NewCloudError(http.StatusNotFound, api.CloudErrorCodeResourceNotFound, "", "The Resource '%s/%s' under resource group '%s' was not found.", vars["resourceType"], vars["resourceName"], vars["resourceGroupName"])
-	case err != nil:
-		return nil, err
-	}
-
-	k, err := f.kubeActionsFactory(log, f.env, doc.OpenShiftCluster)
-	if err != nil {
-		return nil, err
-	}
-
-	return k.KubeGetPodLogs(ctx, namespace, podName, containerName)
-}
diff --git a/pkg/frontend/adminactions/kubeactions.go b/pkg/frontend/adminactions/kubeactions.go
index 8113e416f..b0f51bc7c 100644
--- a/pkg/frontend/adminactions/kubeactions.go
+++ b/pkg/frontend/adminactions/kubeactions.go
@@ -9,12 +9,10 @@ import (
 
 	configclient "github.com/openshift/client-go/config/clientset/versioned"
 	"github.com/sirupsen/logrus"
-	corev1 "k8s.io/api/core/v1"
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/client-go/dynamic"
-	"k8s.io/client-go/kubernetes"
 
 	"github.com/Azure/ARO-RP/pkg/api"
 	"github.com/Azure/ARO-RP/pkg/env"
@@ -29,7 +27,6 @@ type KubeActions interface {
 	KubeCreateOrUpdate(ctx context.Context, obj *unstructured.Unstructured) error
 	KubeDelete(ctx context.Context, groupKind, namespace, name string) error
 	Upgrade(ctx context.Context, upgradeY bool) error
-	KubeGetPodLogs(ctx context.Context, namespace, name, containerName string) ([]byte, error)
 }
 
 type kubeActions struct {
@@ -40,7 +37,6 @@ type kubeActions struct {
 
 	dyn       dynamic.Interface
 	configcli configclient.Interface
-	kubecli   kubernetes.Interface
 }
 
 // NewKubeActions returns a kubeActions
@@ -65,11 +61,6 @@ func NewKubeActions(log *logrus.Entry, env env.Interface, oc *api.OpenShiftClust
 		return nil, err
 	}
 
-	kubecli, err := kubernetes.NewForConfig(restConfig)
-	if err != nil {
-		return nil, err
-	}
-
 	return &kubeActions{
 		log: log,
 		oc:  oc,
@@ -78,16 +69,9 @@ func NewKubeActions(log *logrus.Entry, env env.Interface, oc *api.OpenShiftClust
 
 		dyn:       dyn,
 		configcli: configcli,
-		kubecli:   kubecli,
 	}, nil
 }
 
-func (k *kubeActions) KubeGetPodLogs(ctx context.Context, namespace, podName, containerName string) ([]byte, error) {
-	var limit int64 = 52428800
-	opts := corev1.PodLogOptions{Container: containerName, LimitBytes: &limit}
-	return k.kubecli.CoreV1().Pods(namespace).GetLogs(podName, &opts).Do(ctx).Raw()
-}
-
 func (k *kubeActions) KubeGet(ctx context.Context, groupKind, namespace, name string) ([]byte, error) {
 	gvr, err := k.gvrResolver.Resolve(groupKind, "")
 	if err != nil {
diff --git a/pkg/frontend/frontend.go b/pkg/frontend/frontend.go
index 9cfe34361..29d24f962 100644
--- a/pkg/frontend/frontend.go
+++ b/pkg/frontend/frontend.go
@@ -226,13 +226,6 @@ func (f *frontend) authenticatedRoutes(r *mux.Router) {
 	s.Methods(http.MethodPost).HandlerFunc(f.postAdminKubernetesObjects).Name("postAdminKubernetesObjects")
 	s.Methods(http.MethodDelete).HandlerFunc(f.deleteAdminKubernetesObjects).Name("deleteAdminKubernetesObjects")
 
-	// Pod logs
-	s = r.
-		Path("/admin/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}/kubernetespodlogs").
-		Subrouter()
-
-	s.Methods(http.MethodGet).HandlerFunc(f.getAdminKubernetesPodLogs).Name("getAdminKubernetesPodLogs")
-
 	s = r.
 		Path("/admin/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}/resources").
 		Subrouter()
diff --git a/pkg/frontend/validate.go b/pkg/frontend/validate.go
index 363ebf554..52d309710 100644
--- a/pkg/frontend/validate.go
+++ b/pkg/frontend/validate.go
@@ -119,25 +119,6 @@ func validateAdminVMName(vmName string) error {
 	return nil
 }
 
-func validateAdminKubernetesPodLogs(namespace, podName, containerName string) error {
-	if podName == "" || !rxKubernetesString.MatchString(podName) {
-		return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "", "The provided pod name '%s' is invalid.", podName)
-	}
-
-	if namespace == "" || !rxKubernetesString.MatchString(namespace) {
-		return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "", "The provided namespace '%s' is invalid.", namespace)
-	}
-	// Checking if the namespace is an OpenShift namespace not a customer workload namespace.
-	if !utilnamespace.IsOpenShiftNamespace(namespace) {
-		return api.NewCloudError(http.StatusForbidden, api.CloudErrorCodeForbidden, "", "Access to the provided namespace '%s' is forbidden.", namespace)
-	}
-
-	if containerName == "" || !rxKubernetesString.MatchString(containerName) {
-		return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "", "The provided container name '%s' is invalid.", containerName)
-	}
-	return nil
-}
-
 // Azure resource name rules:
 // https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork
 var rxNetworkInterfaceName = regexp.MustCompile(`^[a-zA-Z0-9].*\w$`)
diff --git a/pkg/operator/controllers/machinehealthcheck/bindata.go b/pkg/operator/controllers/machinehealthcheck/bindata.go
index e3e0183a5..73ea4bd26 100644
--- a/pkg/operator/controllers/machinehealthcheck/bindata.go
+++ b/pkg/operator/controllers/machinehealthcheck/bindata.go
@@ -98,7 +98,7 @@ func machinehealthcheckYaml() (*asset, error) {
 	return a, nil
 }
 
-var _mhcremediationalertYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x91\x4d\x8b\x14\x4d\x10\x84\xef\xfd\x2b\xe2\xf8\xbe\x87\x5e\x5d\x0f\x22\x75\x10\x44\x84\xbd\x2c\xc8\x08\x5e\x44\x86\x9c\xea\x70\xaa\x98\xfa\x68\x32\xb3\x67\xdd\x7f\x2f\xdd\xd3\xea\x5e\xcc\x63\x55\x3e\x11\x4f\x51\x32\xe7\xaf\x54\xcb\xbd\x05\xd4\xde\xb2\x77\xcd\xed\x7c\x17\xbb\xb2\xdb\x5d\xec\xf5\xd5\xf5\x7e\xb8\xe4\x36\x05\x7c\xd6\x5e\xe9\x89\x8b\x1d\x96\xc2\xa1\xd2\x65\x12\x97\x30\x00\x4d\x2a\x03\x6a\x8a\xa3\xb2\x72\xca\xe2\xb9\xb7\x51\x0a\xd5\xf7\x5b\x9b\x25\x32\xa0\xcf\x6c\x96\xf2\x0f\x1f\xab\xc4\x94\x1b\x47\x99\xf3\x00\x14\x39\xb1\xd8\x1a\x05\xcc\x7f\x7a\x02\x2e\xef\x6c\x3b\xd3\x5e\x18\xb0\x05\x8e\xba\x14\xda\x60\x33\xe3\xba\x7f\xd6\xbe\xcc\x1b\x39\xee\x1a\xa6\x1c\xff\xa5\x02\x6c\xf4\xad\x68\xbc\x05\x06\x7c\x39\x7c\x7a\xbc\xe9\x3c\x50\x8a\xa7\x8f\x89\xf1\x72\xf8\x8b\x1f\xc4\xf9\x90\xcf\x69\xa3\x00\xfe\x9c\x35\x20\xb7\xa8\x14\xe3\x7f\x55\xe6\x7c\xdc\x9f\x93\x36\x3e\xae\xfc\xf1\x45\xff\xd1\x96\x18\x69\x76\xf4\xee\x52\xf0\xed\xed\xeb\xfa\xfd\x7f\xbc\xc7\xfd\x9e\xf8\xa1\xb5\xee\xdb\xe6\xae\xb6\xce\x23\xcd\xe4\xcc\x80\xa7\xae\x17\x2a\x5a\x9f\x68\x48\x72\x25\x4e\x64\xc3\xef\x7c\x4e\x78\x83\xae\xa8\x5d\x09\xcf\x95\x86\xdc\xe0\x89\x28\x62\x8e\xd4\x17\x85\xa7\x6c\xa8\xf2\x8c\xdc\xa6\x1c\xc5\x09\x69\x58\x9a\xb9\x9c\x0a\xb7\x82\xd2\x65\x82\x2e\xad\xe5\x76\x46\xbf\xf1\xb1\x2c\xe6\xd4\xdd\xe8\xe5\x1f\xad\x63\xbc\x52\xb3\x3f\x07\x3c\x89\xae\xd8\xf0\x2b\x00\x00\xff\xff\x9e\xca\xa1\xb4\x4d\x02\x00\x00")
+var _mhcremediationalertYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x91\x4d\x8b\x14\x4d\x10\x84\xef\xfd\x2b\xe2\xf8\xbe\x87\x5e\x5d\x0f\x22\x75\x10\x44\x84\xbd\x2c\xc8\x08\x5e\x44\x86\x9c\xea\x70\xaa\x98\xfa\x68\x32\xb3\x67\xdd\x7f\x2f\xdd\xd3\xea\x5e\xcc\x63\x55\x3e\x11\x4f\x51\x32\xe7\xaf\x54\xcb\xbd\x05\xd4\xde\xb2\x77\xcd\xed\x7c\x17\xbb\xb2\xdb\x5d\xec\xf5\xd5\xf5\x7e\xb8\xe4\x36\x05\x7c\xd6\x5e\xe9\x89\x8b\x1d\x96\xc2\xa1\xd2\x65\x12\x97\x30\x00\x4d\x2a\x03\x6a\x8a\xa3\xb2\x72\xca\xe2\xb9\xb7\x51\x0a\xd5\xf7\x5b\x9b\x25\x32\xa0\xcf\x6c\x96\xf2\x0f\x1f\xab\xc4\x94\x1b\x47\x99\xf3\x00\x14\x39\xb1\xd8\x1a\x05\xcc\x7f\x7a\x02\x2e\xef\x6c\x3b\xd3\x5e\x18\xb0\x05\x8e\xba\x14\xda\x60\x33\xe3\xba\x7f\xd6\xbe\xcc\x1b\x39\xee\x1a\xa6\x1c\xff\xa5\x02\x6c\xf4\xad\x68\xbc\x05\x06\x7c\x39\x7c\x7a\xbc\xe9\x3c\x50\x8a\xa7\x8f\x89\xf1\x72\xf8\x8b\x1f\xc4\xf9\x90\xcf\x69\xa3\x00\xfe\x9c\x35\x20\xb7\xa8\x14\xe3\x7f\x55\xe6\x7c\xdc\x9f\x93\x36\x3e\xae\xfc\xf1\x45\xff\xd1\x96\x18\x69\x76\xf4\xee\x52\xf0\xed\xed\xeb\xfa\xfd\x7f\xbc\xc7\xfd\x9e\xf8\xa1\xb5\xee\xdb\xe6\xae\xb6\xce\x23\xcd\xe4\xcc\x00\x3c\x75\xbd\x50\xd1\xfa\x44\x43\x92\x2b\x71\x22\x1b\x7e\x17\x70\xc2\x1b\x74\x45\xed\x4a\x78\xae\x34\xe4\x06\x4f\x44\x11\x73\xa4\xbe\x28\x3c\x65\x43\x95\x67\xe4\x36\xe5\x28\x4e\x48\xc3\xd2\xcc\xe5\x54\xb8\x15\x94\x2e\x13\x74\x69\x2d\xb7\x33\xfa\x8d\x8f\x65\x31\xa7\xee\x4a\x2f\x3f\x69\x1d\xe3\x95\x9a\xfd\x39\xe0\x49\x74\xc5\x86\x5f\x01\x00\x00\xff\xff\x76\x45\x90\xe0\x4e\x02\x00\x00")
 
 func mhcremediationalertYamlBytes() ([]byte, error) {
 	return bindataRead(
diff --git a/pkg/operator/controllers/machinehealthcheck/staticresources/mhcremediationalert.yaml b/pkg/operator/controllers/machinehealthcheck/staticresources/mhcremediationalert.yaml
index 1995448f9..0987a37b6 100644
--- a/pkg/operator/controllers/machinehealthcheck/staticresources/mhcremediationalert.yaml
+++ b/pkg/operator/controllers/machinehealthcheck/staticresources/mhcremediationalert.yaml
@@ -13,6 +13,6 @@ spec:
     - alert: SREMachineHealthCheckRemediationRateHigh
       expr: increase(mapi_machinehealthcheck_remediation_success_total [60m]) > 1
       Annotations:
-        Message: worker nodes have been remediated 2 or more times in the last hour this may indicate an unstable workload running on the cluster
+        Message:  worker nodes have been remediated 2 or more times in the last hour this may indicate an unstable workload running on the cluster
       labels:
         severity: warning
diff --git a/pkg/operator/controllers/muo/bindata.go b/pkg/operator/controllers/muo/bindata.go
new file mode 100644
index 000000000..0c52731e8
--- /dev/null
+++ b/pkg/operator/controllers/muo/bindata.go
@@ -0,0 +1,589 @@
+// Code generated for package muo by go-bindata DO NOT EDIT. (@generated)
+// sources:
+// staticresources/cluster_role.yaml
+// staticresources/cluster_rolebinding.yaml
+// staticresources/config.yaml
+// staticresources/custom_resource_definition.yaml
+// staticresources/deployment.yaml
+// staticresources/managed_upgrade_role.yaml
+// staticresources/managed_upgrade_rolebinding.yaml
+// staticresources/monitoring_reader_role.yaml
+// staticresources/monitoring_reader_rolebinding.yaml
+// staticresources/namespace.yaml
+// staticresources/prometheus_role.yaml
+// staticresources/prometheus_rolebinding.yaml
+// staticresources/pullsecret_reader_role.yaml
+// staticresources/pullsecret_reader_rolebinding.yaml
+// staticresources/service_account.yaml
+// staticresources/trusted_ca_bundle_configmap.yaml
+package muo
+
+import (
+	"bytes"
+	"compress/gzip"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+func bindataRead(data []byte, name string) ([]byte, error) {
+	gz, err := gzip.NewReader(bytes.NewBuffer(data))
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, gz)
+	clErr := gz.Close()
+
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+	if clErr != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
+type asset struct {
+	bytes []byte
+	info  os.FileInfo
+}
+
+type bindataFileInfo struct {
+	name    string
+	size    int64
+	mode    os.FileMode
+	modTime time.Time
+}
+
+// Name return file name
+func (fi bindataFileInfo) Name() string {
+	return fi.name
+}
+
+// Size return file size
+func (fi bindataFileInfo) Size() int64 {
+	return fi.size
+}
+
+// Mode return file mode
+func (fi bindataFileInfo) Mode() os.FileMode {
+	return fi.mode
+}
+
+// Mode return file modify time
+func (fi bindataFileInfo) ModTime() time.Time {
+	return fi.modTime
+}
+
+// IsDir return file whether a directory
+func (fi bindataFileInfo) IsDir() bool {
+	return fi.mode&os.ModeDir != 0
+}
+
+// Sys return file is sys mode
+func (fi bindataFileInfo) Sys() interface{} {
+	return nil
+}
+
+var _cluster_roleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x54\xc1\x8e\xd4\x30\x0c\xbd\xf7\x2b\xa2\xbd\xac\x84\x34\x1d\x71\x43\xbd\x72\xe0\x8e\x10\x77\x4f\xe2\xe9\x58\x9b\xc6\x91\xed\x14\xb1\x5f\x8f\xa6\xc9\xae\x0a\x9d\x32\xbb\x48\x9c\xe2\xbe\xda\x7e\x2f\xcf\x6e\x21\xd3\x77\x14\x25\x4e\x83\x93\x13\xf8\x1e\x8a\x5d\x58\xe8\x19\x8c\x38\xf5\x4f\x9f\xb4\x27\x3e\xce\x1f\xbb\x27\x4a\x61\x70\x9f\x63\x51\x43\xf9\xca\x11\xbb\x09\x0d\x02\x18\x0c\x9d\x73\x5e\x70\x29\xf8\x46\x13\xaa\xc1\x94\x07\x97\x4a\x8c\x9d\x73\x09\x26\x1c\xdc\x04\x09\x46\x0c\x87\x92\x47\x81\x80\x07\xce\x28\x60\x2c\x9d\x94\x88\x3a\x74\x07\x07\x99\xbe\x08\x97\xac\xd7\x76\x07\xf7\xf0\xd0\x39\x27\xa8\x5c\xc4\x63\xc3\x32\x07\x7d\x0d\x8e\x67\x4a\x10\xe9\x19\xe5\x8a\xcd\x28\xa7\x96\xb5\x48\xc1\x25\x0c\x18\xb1\x85\x23\xda\x72\x46\xd2\x1a\x64\x30\x7f\x59\xa2\x92\xc3\x4b\xc1\x8f\x05\x7c\x93\x18\x9c\x31\x59\x95\x93\x38\xe0\x1f\x22\x36\x74\x3b\x9d\x9b\x1f\x7d\xf3\xa7\xe7\x8c\x49\x2f\x74\xb6\x9e\x78\xcb\xd9\xb2\x3d\xa7\x33\x8d\xba\x86\x6e\xbc\x3e\xaa\x81\x95\xff\x6f\x4e\xa5\xbb\xa3\xdc\xd7\xbd\x99\xeb\xaa\xe9\x1a\x7b\x59\x85\x7b\x0e\xbe\x47\xd3\x04\xfe\x42\x09\xef\x88\x6a\x59\xfa\xdb\x03\xda\xfb\x2d\xdb\xe3\xaf\xd6\x14\xa9\xdf\xd2\x9b\xc4\xd4\x92\xcc\x1c\xff\x71\xa3\x5e\xed\xec\x3d\x0b\xf2\xf5\x98\xb6\x6c\x5a\x4e\xea\x85\xb2\xb5\x69\xac\x88\x1e\x3f\x3c\xde\xb8\x10\x27\x32\x16\x4a\xe3\xdf\xdb\xa2\xcc\xe4\xb1\x65\xef\x1b\xb9\x9a\xe0\xce\x9c\x37\x0a\x32\x47\xf2\x3f\x6f\xfe\x14\x02\xa9\x94\xe5\x2a\xa7\x12\xc6\xcd\x00\x77\x9c\xfb\x15\x00\x00\xff\xff\xa3\xcc\x1c\xe4\xfa\x04\x00\x00")
+
+func cluster_roleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_cluster_roleYaml,
+		"cluster_role.yaml",
+	)
+}
+
+func cluster_roleYaml() (*asset, error) {
+	bytes, err := cluster_roleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "cluster_role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _cluster_rolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x90\xbd\x6e\xc3\x30\x0c\x84\x77\x3d\x85\x5e\x40\x2e\xba\x15\xda\xda\x0e\xdd\x5d\x20\x3b\x2d\xd1\x36\x63\x9b\x14\x28\xca\x43\x9e\x3e\x08\x3c\x06\xf9\xd9\x3f\xdc\x77\x77\x0b\x71\x8e\xfe\x77\x6d\xd5\x50\x7b\x59\xf1\x87\x38\x13\x4f\x0e\x0a\x9d\x50\x2b\x09\x47\xaf\x03\xa4\x0e\x9a\xcd\xa2\x74\x01\x23\xe1\x6e\xf9\xaa\x1d\xc9\xc7\xfe\xe9\x36\x34\xc8\x60\x10\x9d\xf7\x0c\x1b\x46\xbf\x01\xc3\x84\x39\xb4\x32\x29\x64\x0c\x52\x50\xc1\x44\x5d\x6d\xc3\x19\x93\xd5\xe8\x82\x3f\xc4\xff\xa8\x3b\x25\xfc\x4e\x49\x1a\xdb\xeb\x84\x03\xa8\x05\x12\x46\x2f\x05\xb9\xce\x34\x5a\x78\xc8\xab\xac\xd8\xe3\x78\xeb\x76\xb7\xf4\x1d\x1b\x14\xfa\x53\x69\xe5\xc9\x07\xee\x1a\x00\x00\xff\xff\xc4\x6f\x81\xf4\x43\x01\x00\x00")
+
+func cluster_rolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_cluster_rolebindingYaml,
+		"cluster_rolebinding.yaml",
+	)
+}
+
+func cluster_rolebindingYaml() (*asset, error) {
+	bytes, err := cluster_rolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "cluster_rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _configYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x52\xdd\x6a\x1b\x3d\x10\xbd\xf7\x53\xe8\x05\xf6\xe3\x73\x7f\xa0\xd5\x5d\xd8\x10\x28\x24\x76\x08\x69\x7b\x3d\x48\x27\xbb\xc2\xda\x91\x18\x8d\xec\xa6\xf4\xe1\x8b\xd7\xbb\x8e\xd3\x6c\xab\xcb\xf3\x33\xe7\x68\x18\xca\xe1\x1b\xa4\x84\xc4\xd6\xec\xd7\xab\x5d\x60\x6f\x4d\x9b\xf8\x29\x74\x77\x94\x57\x03\x94\x3c\x29\xd9\x95\x31\x4c\x03\xac\x19\x88\xa9\x83\x6f\x6a\xee\x84\x3c\x9a\x94\x21\xa4\x49\x1a\x37\x9a\x26\x5d\xc9\xe4\x60\x4d\xca\xe0\xd2\x87\x27\x6d\xfe\x66\x5b\xcd\xd3\x4f\xf6\xff\x9e\x69\x88\xd6\xfc\x5a\x19\x33\x43\x77\xa3\x53\xec\x08\x19\x53\x52\x95\xe3\xe8\xdb\x6d\x7b\x75\x3b\x61\x31\x39\x8a\xa7\xd2\x9b\xc5\x92\xe7\x6e\xc7\x77\x20\x75\xfd\x17\x56\xc8\x9e\xa2\x35\xeb\x11\x1e\x28\xb0\x82\x89\x1d\xe6\x24\x97\x58\x25\xc5\xfb\x48\x8c\xc7\x70\x1c\xfb\xf9\xff\x89\x0a\x1d\x27\x81\xbf\x8a\x10\x2d\xb3\xfe\xb5\xa3\x95\xa0\xc1\x51\xbc\xa0\x1b\xd3\xc6\x5a\x14\xb2\x9d\x3e\x7f\x9d\x0e\xfc\x0f\x16\x63\x79\x3f\x2a\xa6\x9f\x7c\x0f\xec\xd3\x61\x1e\xe9\x11\xe9\xf9\x51\x42\x77\xdc\x8f\x79\x3f\xb7\xd3\x30\x60\x5b\xd5\x9a\xf5\xbb\x13\xc4\xc9\xe3\x5a\x28\xb0\xfd\x53\xf1\xe1\xe3\x84\xe0\x47\x86\x53\xf8\xcd\x2c\x3d\xfd\xf8\xd3\x48\x17\x47\x11\x6f\xbc\x53\x5e\x0f\x8a\xda\xb7\x3d\xdc\xce\xbe\x5e\xcf\x9b\x15\x34\xe6\x5e\xd2\x00\xed\x51\xcb\x43\x8d\xb8\xa1\x10\xab\xa0\x9c\xe9\x96\x98\x93\x3e\x40\x25\x60\x8f\xaf\xd9\x93\x5e\xb0\x37\xb1\x82\xf5\x54\xf1\x65\x73\x53\xd8\x66\xbe\xba\x8b\xb4\x97\xf3\x8b\xa9\xeb\x02\x77\x0b\x8c\xc0\xf7\x74\xbc\x4f\xd9\x41\x73\x24\x87\x05\xd1\x7c\xad\x65\x81\xab\x05\xd2\x1c\x92\xec\x62\x22\xdf\x0c\x89\x83\x26\x59\xce\xca\x21\x23\x06\xc6\xd2\x18\xfa\x59\x05\xe7\x9e\xbf\x03\x00\x00\xff\xff\x6c\x17\x59\x7b\x97\x03\x00\x00")
+
+func configYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_configYaml,
+		"config.yaml",
+	)
+}
+
+func configYaml() (*asset, error) {
+	bytes, err := configYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _custom_resource_definitionYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x59\x4b\x8f\xdb\x38\x12\xbe\xfb\x57\x14\x66\x0f\xd9\x05\x62\x75\x67\x73\x59\xf8\x96\x71\x6f\x30\xc1\xce\x24\x8d\x74\x4f\x2e\x83\xc1\xa2\x2c\x96\x2c\x4e\x53\xa4\x96\x0f\x77\x3c\x8b\xfd\xef\x8b\xa2\x28\xcb\x92\xa9\xb6\x1b\xc9\x3c\x78\x13\x1f\xf5\xae\xaf\x8a\xd4\x72\xb9\x5c\x60\x2b\x3f\x91\x75\xd2\xe8\x15\x60\x2b\xe9\xb3\x27\xcd\x5f\xae\x78\xf8\x87\x2b\xa4\xb9\xda\xbd\x5a\x3c\x48\x2d\x56\xb0\x0e\xce\x9b\xe6\x23\x39\x13\x6c\x49\x37\x54\x49\x2d\xbd\x34\x7a\xd1\x90\x47\x81\x1e\x57\x0b\x00\xd4\xda\x78\xe4\x69\xc7\x9f\x00\xa5\xd1\xde\x1a\xa5\xc8\x2e\xb7\xa4\x8b\x87\xb0\xa1\x4d\x90\x4a\x90\x8d\xc4\x7b\xd6\xbb\xeb\xe2\x75\x71\xbd\x00\x28\x2d\xc5\xe3\xf7\xb2\x21\xe7\xb1\x69\x57\xa0\x83\x52\x0b\x00\x8d\x0d\xad\x20\xb4\x5b\x8b\x82\x4a\xa3\x2b\xb9\x75\x45\xfa\x2c\x1a\xd4\xb8\x25\x51\x98\x96\xb4\xab\x65\xe5\x0b\x69\x16\xae\xa5\x92\xa5\xd8\x5a\x13\xda\xc3\xd1\xfc\xde\x8e\x7e\x12\xba\x53\xf8\xc7\x6e\xff\x3a\xb2\x8a\xf3\x4a\x3a\xff\xaf\xd3\xb5\xef\xa5\xf3\x71\xbd\x55\xc1\xa2\x9a\x0a\x19\x97\x5c\x6d\xac\x7f\x3f\xb0\x58\xf6\x9b\xba\x55\xa9\xb7\x41\xa1\x9d\x1c\x5d\x00\xb8\xd2\xb4\xb4\x82\x78\xb2\xc5\x92\xc4\x02\x20\x59\x2d\x52\x5a\x02\x0a\x11\xfd\x80\xea\xd6\x4a\xed\xc9\xae\x8d\x0a\x8d\x3e\xf0\xf9\xc5\x19\x7d\x8b\xbe\x5e\x41\xc1\x06\x29\x04\x39\x69\x49\x14\x89\x4a\xdc\xd5\x5b\x37\xad\xfd\x7b\xbc\xe6\xf7\x2c\x82\xf3\x56\xea\x6d\x86\xa8\x47\x1f\x5c\x51\x4b\xe7\x8d\xdd\xff\x74\xfd\x73\xd1\xd6\xe8\x68\x44\xf7\x78\xe6\xb9\xd4\x4a\xa3\x3b\x05\x1d\x7f\xf1\xe9\x11\x69\xe7\x71\xfb\x75\x48\x77\xeb\x53\xe2\xc3\xd4\x97\x51\xb7\x84\x6e\x62\xed\xd1\xd4\x97\x51\x6f\xc8\xb9\xc1\x0e\x1d\xf9\xf1\xdc\x09\xfd\x6e\xd3\xee\x15\xaa\xb6\xc6\x57\x5d\x18\x96\x35\x35\xb8\x4a\x27\x38\x3f\xde\xdc\xbe\xfb\xf4\xfa\x6e\x34\x0d\x1c\x25\xa5\x95\xad\x8f\x99\x3b\xca\x04\x90\x0e\x7c\x4d\xd0\x9d\x80\xca\xd8\xf8\x39\xce\x07\x78\x73\xfb\xee\x40\xab\xb5\xa6\x25\xeb\x65\x9f\x17\xdd\x38\x42\xa5\xa3\xd9\x09\xe7\x17\x2c\x5c\xb7\x0b\x04\xc3\x11\x75\xcc\x53\xf0\x92\x48\xfa\x80\xa9\xc0\xd7\xd2\x81\xa5\xd6\x92\x23\xdd\x01\xd4\x88\x30\xf0\x26\xd4\x60\x36\xbf\x50\xe9\x0b\xb8\x23\xcb\x64\x38\x6d\x83\x12\x8c\x62\x3b\xb2\x1e\x2c\x95\x66\xab\xe5\xaf\x07\xda\x0e\xbc\x89\x4c\x15\x7a\x4a\x28\x30\x8c\x98\x8e\x1a\x15\xec\x50\x05\x7a\x09\xa8\x05\x34\xb8\x07\x4b\xcc\x05\x82\x3e\xa2\x17\xb7\xb8\x02\x7e\x30\x96\x40\xea\xca\xac\xa0\xf6\xbe\x75\xab\xab\xab\xad\xf4\x3d\x1a\x97\xa6\x69\x82\x96\x7e\x7f\x15\x81\x55\x6e\x82\x37\xd6\x5d\x09\xda\x91\xba\x72\x72\xbb\x44\x5b\xd6\xd2\x53\xe9\x83\xa5\x2b\x6c\xe5\x32\x8a\xae\x63\xa0\x14\x8d\xf8\x8b\x4d\xf8\xed\x5e\x8c\x64\x3d\x89\x8e\x6e\x44\x20\x7c\xc2\x03\x0c\x86\xec\x73\x4c\x47\x3b\x2d\x06\x43\xf3\x14\x5b\xe7\xe3\x3f\xef\xee\xa1\x67\x1d\x9d\x31\xb5\x7e\xb4\xfb\x70\xd0\x0d\x2e\x60\x83\x49\x5d\x91\xed\x9c\x58\x59\xd3\x44\x9a\xa4\x45\x6b\xa4\xf6\xf1\xa3\x54\x92\xf4\xd4\xfc\x2e\x6c\x1a\xe9\xd9\xef\xff\x09\xe4\x3c\xfb\xaa\x80\x75\x2c\x51\xb0\xe1\xa8\x14\xe8\x49\x14\xf0\x4e\xc3\x1a\x1b\x52\x6b\x74\xf4\x9b\x3b\x80\x2d\xed\x96\x6c\xd8\xcb\x5c\x70\x5c\x5d\xa7\x9b\x3b\xab\x1d\x2d\xf4\x15\x6f\xc6\x5f\xa3\x5c\xbd\x6b\xa9\x1c\xe5\x4d\x02\xff\x08\x7a\xc4\xf9\x70\x5a\x00\x87\xc1\xa1\x9c\xd2\x1a\x1e\xa5\x16\xe6\x31\x4e\x55\x96\xe8\xd7\x7e\x66\x74\x24\x9f\xe8\x3c\x6e\x6f\xbe\x7d\x6b\xb8\xa5\xb0\x28\x63\xdd\x37\xc1\x4f\xf7\x4c\x14\xb9\xaf\x09\x1a\xfc\x2c\x9b\xd0\xc0\xd6\x62\x49\xd0\x92\x95\x46\xf0\x87\xf6\x24\x38\x2b\x11\xb4\x61\xe1\x6a\xe3\x08\x04\xd3\x3e\xa1\x09\x1c\xbb\x1b\x65\xca\x07\x12\xb0\xd9\x03\xc2\xad\x11\x70\x23\x9d\x0d\x91\x11\x7c\x1b\xc4\x96\xfc\x4b\xd8\x50\xc5\x51\xe1\x6b\xf4\x1d\x29\x3e\x58\xb1\xd0\xa2\xc8\x50\xfd\x81\xd0\x05\x36\xa5\xd4\xd0\x48\x1d\x3c\x27\x76\x94\x59\xea\x28\x33\x96\x25\xb5\xbe\xcf\x7a\x26\x76\x1d\xcd\x27\x75\x2e\x39\x78\x94\xe8\x08\xa4\x87\x47\xa9\x14\x78\x2b\xb7\x5b\xb2\x9d\x04\x49\x20\xac\x3c\x75\x68\x4b\x9f\x5b\x2a\x3d\x89\xf7\x46\x0c\x36\xcd\x90\x54\xd8\xba\x9c\xfc\x95\xb1\x0d\xfa\x15\xa3\xd7\xeb\xbf\x9f\xac\x26\x15\x56\x70\x7d\xb2\xd4\x05\x25\x83\xde\x96\xec\x62\x2a\x7f\x8b\xa5\xf4\xfb\x8f\xe4\xc8\xee\x22\x00\x9f\xf1\x31\xc7\xa7\xac\xf6\x20\x2b\x70\x25\x2a\x86\x92\xd0\x32\x46\xd3\x67\x6f\x93\x73\xb9\xc0\xf4\x94\x19\x5f\x7a\xd2\x19\x6d\x93\x0b\xfb\x98\x75\x1e\xad\x77\x6c\x79\x4d\x24\x62\x5b\x95\x53\x66\x63\x8c\x22\x9c\xd2\x4b\x99\x72\xa1\x02\xc7\xb9\xf5\xa1\x25\x7d\xc7\x3d\x27\x58\x52\x34\x34\x45\xc3\x98\xcf\x93\x68\xc6\x1a\xb5\x26\x95\x5b\x9a\x70\x5f\x77\x3b\x21\x38\x12\xd1\x4e\x49\xf3\x5c\x70\xcd\x82\x4f\x3f\x64\x83\x5b\xba\x80\xe9\x3b\xde\x07\x96\x2a\xb2\xa4\x4b\xfa\x3a\xcc\x77\xb9\x4e\x20\xcb\xbe\xef\x06\x4c\x05\x87\xe6\x7e\xd6\xd0\x67\x39\xcf\x60\xec\x61\xe9\x0c\x44\xed\x5b\x2e\x23\x42\x96\xdc\x19\xc4\x20\x58\xab\xe0\x3c\xd9\x04\xab\x16\x64\xd3\x2a\x6a\xfa\x7e\x04\xbc\xc9\xc8\x18\x1c\x31\x98\xb5\x64\x39\x2d\x39\xfc\xfb\x08\x8e\x5d\x0d\x57\xbe\x48\xf4\xe4\x28\xe9\xd0\x9c\x8a\xb8\x84\x0f\x77\x37\x99\xd9\x37\x1f\x3f\xcc\xe8\x9f\x35\x4e\x92\xe1\xcd\x39\x9c\x3e\x4e\x81\x51\xe6\x81\xcf\x61\xd2\x2c\x47\xae\xe0\xa7\x19\xb7\xcc\x96\x8e\xc9\x96\x94\x79\x93\xd9\xa3\x6b\x44\x3f\x75\xd0\xe9\xa2\x42\x1b\xfb\xf1\x8b\x4b\x6d\xdc\x3d\x2a\xb6\x66\xc3\x60\x75\x59\xb5\x9d\x87\x84\x74\x1f\x38\x5b\x2d\x63\xf3\x5b\x1a\x2b\xfa\x13\xcc\x90\x76\x64\xf7\xa3\x6b\xe8\xf1\x90\x9e\x9a\x2c\x04\xe5\xd4\xfc\x2e\x51\x3d\x65\x32\x47\xfe\x1c\xd0\x01\x94\x86\xd3\xc3\x13\xbb\x35\xbf\x63\x28\x55\xdc\xc8\x2d\xb3\x21\xd5\x8d\x33\x08\x13\x9f\x29\xd2\x6d\x6a\x8e\xd5\x18\x5c\x0f\xdb\x53\xf7\x4b\x9e\x95\x3d\x4c\x83\xd4\xce\xa3\x2e\xc9\xe5\xda\x03\x78\xca\xbc\x19\x6e\x43\x64\x24\xea\xb5\x09\x8e\x1c\x54\x92\x94\x70\xa9\x2b\x89\x07\x36\x73\x06\x88\x46\xa8\x69\x88\x36\xd4\x3d\x59\x90\xba\x54\x41\x70\x7d\xed\x7b\xcd\x39\xa1\xcf\x3b\xad\xb7\xe6\x79\xd7\x65\xf4\x5c\xa7\x63\x11\x1c\x0e\xb7\xb6\x83\x6b\xe6\xa5\x82\x67\x84\x42\xb2\xc5\xb9\x80\xe8\x86\x42\xe7\x6f\xad\xd9\x3c\x57\x93\xef\xd1\x75\x10\xd7\x41\xf4\xc1\x71\x8f\xe8\xa0\xac\x89\xfb\xcd\x3f\x48\x9b\x7b\x8b\xda\xc9\xfe\x85\xed\x2b\xa8\xe4\x3b\x82\xdd\xbd\xcc\xe8\xa7\x05\xed\x81\x33\xf6\xe7\xda\xf8\x9a\xec\x1f\x60\x87\xf4\x30\xf2\x0c\xe5\xbf\x0b\x0d\x6a\xb0\x84\x02\x37\x8a\x7a\x02\x7d\x79\xe7\xd4\x11\xe4\x51\xaa\x7c\x7f\x33\x0c\xdc\x98\xe0\xa3\x1f\x7a\xbb\x9d\x8d\xeb\x0b\x75\xea\xde\x92\x9e\xa1\xd2\x5f\x37\x56\x52\xf5\xb7\x74\xf0\xf0\x54\x73\x70\xec\x0b\xf7\x9b\xc8\x19\xab\xff\x33\x43\xef\xee\xd0\x31\xfc\x29\x40\x21\x57\xfb\xcf\xc9\xcf\x31\x6f\xaa\x41\xec\x97\x9c\x2a\x3c\x73\x6f\x03\xbd\x84\xb7\xa8\x1c\xbd\x3c\x13\x3c\x3f\xea\x07\x6d\x1e\x73\x77\x9b\x67\xab\x90\xef\x5f\x67\x15\x88\xbd\xec\x50\xcc\x07\x35\xbe\x5c\x96\x7c\x67\x77\x3c\x96\xe3\x57\xd8\xdc\x86\x93\x6e\xee\x54\x8c\x6c\x1b\x3f\xde\x82\xd6\xe2\x3e\xbb\x23\x3e\x5f\x5f\xd4\x18\xc4\x56\xab\xaf\xc5\x87\x8a\xdb\x39\xff\xb8\x09\x6e\xad\x29\xc9\xcd\xe9\x94\xef\xdd\x7b\x6d\xdf\xd3\xe3\xec\xda\x2d\x69\x31\x6f\xee\x65\xaa\xf9\xe7\x77\x64\x2e\xc4\xfd\x86\xb7\x28\xd5\xec\xf2\x59\x9f\x9f\xcd\xff\xaf\xd6\xd2\x3d\x79\x6d\x9c\xb8\xed\x26\x5d\xcf\x77\xc3\x05\x32\xc2\xcc\x7c\xf7\x7a\x91\x08\x8f\xc6\x3e\x90\x5d\xff\x9e\x8d\x6c\xc7\xf2\xee\x77\xb2\xf2\x53\xd9\xbb\x1c\xfd\xf5\x39\x25\x3a\x93\x91\x73\xb9\x98\x3d\x74\x32\xd9\x5d\xaa\x56\xe0\x6d\x48\x7f\xd6\xbc\xb1\x5c\xeb\x8f\x66\xc2\xe6\xf0\x08\xde\xcb\x9d\x20\x1d\xfe\xfb\xbf\xc5\x80\xee\xfd\x23\xdd\xfb\xe9\x8f\xc1\x6f\xbe\x89\x1f\xfd\xdf\xbe\xf8\x79\x74\x81\x80\x9f\x7e\x5e\x74\x8c\x49\x7c\xea\x7f\xd5\xf1\xe4\xff\x03\x00\x00\xff\xff\x30\x3b\x1c\x49\x70\x1d\x00\x00")
+
+func custom_resource_definitionYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_custom_resource_definitionYaml,
+		"custom_resource_definition.yaml",
+	)
+}
+
+func custom_resource_definitionYaml() (*asset, error) {
+	bytes, err := custom_resource_definitionYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "custom_resource_definition.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _deploymentYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x55\x4d\x6f\xe3\x36\x10\xbd\xfb\x57\x0c\xd2\xb3\xa2\x24\x68\x2f\xbc\x19\x1b\xb7\x5d\xa0\x8e\x0d\xc7\x68\x8f\xc5\x98\x1c\x49\x84\xf9\x55\x72\xe8\x8d\xfe\x7d\x21\xc9\x71\x64\x39\xc6\x1a\x05\x8a\xf5\xc9\x98\x37\x7c\xf3\xf8\x38\x33\xc2\xa0\xff\xa4\x98\xb4\x77\x02\x30\x84\x54\x1e\x1e\x67\x7b\xed\x94\x80\x67\x0a\xc6\xb7\x96\x1c\xcf\x2c\x31\x2a\x64\x14\x33\x00\x87\x96\x04\x58\x74\x58\x93\x2a\x72\xa8\x23\x2a\x2a\x7c\xa0\x88\xec\xe3\x31\x21\x05\x94\x24\xc0\x07\x72\xa9\xd1\x15\x17\x57\xf3\x53\x20\xd9\xd1\x46\x0a\x46\x4b\x4c\x02\x1e\x67\x00\x89\x0c\x49\xf6\xb1\x43\x00\x2c\xb2\x6c\xfe\xc0\x1d\x99\x34\x04\x6e\x50\xc1\x64\x83\x41\xa6\x23\xc3\xe8\x02\xdd\xcf\x9c\x91\xdd\x40\x07\xf0\x2e\xb4\xff\x4f\xf1\xa0\x25\xcd\xa5\xf4\xd9\xf1\xcb\xf7\x0f\x03\x60\x55\x69\xa7\xb9\x1d\xd5\xf4\x8a\xe6\x17\xd1\xce\x89\x7f\xb2\x8e\xa4\x9e\x73\xd4\xae\x7e\x95\x0d\xa9\x6c\xb4\xab\xbf\xd6\xce\x9f\xc2\x8b\x37\x92\x99\xbb\x57\x1b\x9d\x1c\x38\x5f\x8f\xde\x6d\x29\xda\x74\x0e\x17\x83\x95\x8b\xb7\x10\x29\x75\x6f\x3e\xc1\xbb\x8c\x3d\xb5\xa2\xe7\x29\xa2\x37\x74\xbf\xcf\x3b\x8a\x8e\x98\xd2\xbd\xf6\xa5\xc5\xc4\x14\x27\x67\x00\xde\xef\x2a\xe0\xab\xbb\x00\x0f\x68\x32\x5d\x14\xea\x4a\xdd\xdd\x1d\x83\xec\x4d\x47\x30\x16\x54\x00\x55\x15\x49\x16\xf0\xe2\x8f\x1e\xd0\x89\xe2\x76\x8d\x63\x9a\xc1\xb3\xff\xc2\x72\xf0\x26\x5b\x1a\x69\x93\xde\x55\xba\x5e\x62\x18\x5f\x4b\x51\x85\xd9\xf0\xd2\x2b\x12\xf0\xf3\xd3\xc3\x08\xd2\x4c\x97\x6f\xd1\xd7\x97\x58\xec\xb2\x53\x86\xee\x65\xe4\x89\x47\x01\xb9\x11\xc0\x26\x15\x1f\x59\x81\xec\x28\x6b\xe8\x5b\x8e\x39\x31\xa9\x8f\xac\xd9\x6d\xb8\xf4\x8e\x51\x3b\x8a\x23\x69\xc5\x2d\xb3\x30\xfc\x7e\x82\x0d\x05\x83\x92\x80\x1b\x9d\xe0\x9b\xe6\x06\xb8\x21\xd8\x65\x6d\x18\xb4\xc5\x9a\x7a\xb2\xb3\x23\xdb\x21\xd5\x18\xa8\x89\xfb\xa9\x47\x49\x0a\xbc\x03\xd5\xef\x1b\xd8\xb5\x50\x36\x28\xf7\x65\x4d\xae\x2b\xf9\x51\xfa\x64\x41\x3b\x76\xb6\x2b\x23\xe0\xb7\xc5\xcb\x62\x33\xdf\x2e\x9e\x47\x90\xf4\xd6\xa2\x53\x63\xdb\x8b\x5b\xee\xd5\x53\xae\xb3\x31\x6b\x6f\xb4\x6c\x05\xcc\xcd\x37\x6c\xd3\xd9\x88\x26\x9f\xa3\x9c\x76\x75\x37\xb9\x94\xf8\xa2\xd7\x65\xc8\x02\x9e\x1e\xec\x24\x6c\xc9\xfa\xd8\x0a\x78\x7c\x78\x58\xea\x33\xcc\x68\xab\xaf\xd0\xfc\x72\x95\xe6\x69\x42\x43\xee\x30\xed\xb8\xe1\x69\xff\x9a\x6f\xbf\xfc\xfe\xf7\xcb\x7c\xb9\x78\x5d\xcf\xbf\x2c\x26\x74\xfd\xb8\xfe\x1a\xbd\xbd\x9c\xd8\x4a\x93\x51\x1b\xaa\x2e\x91\x23\xb6\xee\x1b\xf6\x7d\xd9\xde\x9f\xbe\x04\x9f\xca\x58\xaf\x9e\x7b\x11\xff\x6f\xfd\x4f\x4b\xaf\xd6\x5d\xb3\xac\x36\x3f\xde\x84\x33\x25\x9f\x89\x10\x70\x77\xad\x65\xef\x46\xf9\xc3\x86\x5a\x76\x9f\xa3\x34\x69\xf8\x2e\x36\x68\x2a\x89\x65\x19\xf6\xba\x94\x58\xf4\x3b\xa1\xa4\x37\x8e\x28\x99\x54\x79\xbe\x57\xbe\xbf\x59\xa0\xef\x77\x54\x2b\x67\xda\x3e\x8f\x66\xff\x06\x00\x00\xff\xff\xb7\xcc\xef\x39\x4b\x08\x00\x00")
+
+func deploymentYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_deploymentYaml,
+		"deployment.yaml",
+	)
+}
+
+func deploymentYaml() (*asset, error) {
+	bytes, err := deploymentYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _managed_upgrade_roleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\xb1\x6e\x03\x21\x10\x44\xfb\xfb\x0a\xe4\x1e\x5b\xe9\x22\x7e\x20\x7d\x8a\xf4\x6b\x18\x9f\x57\xe6\xd8\xd5\x02\x17\xc5\x5f\x1f\xf9\x7c\x27\xd9\x89\xa2\x54\xbc\x19\x8d\xe0\x41\xca\x1f\xb0\xca\x52\x82\xb3\x23\xc5\x3d\xf5\x76\x16\xe3\x2b\x35\x96\xb2\xbf\xbc\xd6\x3d\xcb\x61\x7e\x19\x2e\x5c\x52\x70\xef\x92\x31\x4c\x68\x94\xa8\x51\x18\x9c\x2b\x34\x21\xb8\x89\x0a\x8d\x48\xbe\xeb\x68\x94\xe0\x45\x61\xd4\xc4\xd6\x41\x55\x8a\x08\x4e\x14\xa5\x9e\xf9\xd4\xfc\x9f\x7b\xeb\x19\x35\x0c\xde\x91\xf2\x9b\x49\xd7\x7a\x7b\xc4\xbb\xdd\x6e\x70\xce\x50\xa5\x5b\xc4\xda\x45\x29\x27\x1e\x27\xd2\xba\xc4\x8a\x68\x68\x1b\xdb\xcc\x11\xcf\xe1\x70\xe2\x42\x99\xaf\xb0\x5b\x3f\xc3\x8e\xdb\x45\x06\x6a\x58\x30\x21\x63\xc5\x11\x6d\x39\x33\xd7\x3b\x74\x4d\xdb\xec\x93\x5a\x3c\xff\xb6\x24\x5d\x5c\x7e\x78\x26\x68\x96\xaf\x09\x65\x95\x7b\xc8\xcf\x4a\xde\x19\x34\x73\xa4\x7a\xff\xc7\x83\xe2\xff\x32\xdf\x01\x00\x00\xff\xff\x4e\x92\x80\x9e\xc9\x01\x00\x00")
+
+func managed_upgrade_roleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_managed_upgrade_roleYaml,
+		"managed_upgrade_role.yaml",
+	)
+}
+
+func managed_upgrade_roleYaml() (*asset, error) {
+	bytes, err := managed_upgrade_roleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "managed_upgrade_role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _managed_upgrade_rolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x8e\x31\xce\xc2\x30\x0c\x46\xf7\x9c\x22\x17\x48\x7f\xfd\x1b\xca\x06\x47\x28\x12\xbb\x9b\xb8\xad\x69\x6b\x47\x8e\xd3\x81\xd3\x23\xa4\x4a\x4c\x88\x85\xfd\x7d\xdf\x7b\x50\xe8\x86\x5a\x49\x38\x7a\x1d\x20\x75\xd0\x6c\x16\xa5\x07\x18\x09\x77\xcb\xa9\x76\x24\x7f\xfb\xbf\x5b\x88\x73\xf4\xbd\xac\x78\x21\xce\xc4\x93\xdb\xd0\x20\x83\x41\x74\xde\x33\x6c\x18\xfd\x06\x0c\x13\xe6\xd0\xca\xa4\x90\x31\x48\x41\x05\x13\x3d\x80\x5a\x20\x61\xf4\x52\x90\xeb\x4c\xa3\x85\x8f\xbc\xca\x8a\x3d\x8e\xaf\xe7\xb7\xf7\xbb\xa6\xb6\xe1\x8e\xc9\x6a\x74\xe1\xd8\x5d\x51\x77\x4a\x78\x4e\x49\x1a\xdb\xef\x43\x9f\x01\x00\x00\xff\xff\x45\xec\x1c\xea\x3f\x01\x00\x00")
+
+func managed_upgrade_rolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_managed_upgrade_rolebindingYaml,
+		"managed_upgrade_rolebinding.yaml",
+	)
+}
+
+func managed_upgrade_rolebindingYaml() (*asset, error) {
+	bytes, err := managed_upgrade_rolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "managed_upgrade_rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _monitoring_reader_roleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x8e\xbf\x4e\xc3\x40\x0c\xc6\xf7\x7b\x0a\xab\x7b\x82\xd8\xd0\xbd\x00\x3b\x03\xbb\x7b\x71\x13\xab\x39\xfb\x64\xfb\x82\xc4\xd3\xa3\x86\x80\x40\x5d\x3a\xd9\xdf\x1f\x7d\xfa\x61\xe3\x77\x32\x67\x95\x0c\x76\xc6\x32\x62\x8f\x45\x8d\x3f\x31\x58\x65\xbc\xbe\xf8\xc8\xfa\xb4\x3d\xa7\x2b\xcb\x94\xe1\x4d\x57\x4a\x95\x02\x27\x0c\xcc\x09\x40\xb0\x52\x86\xda\x75\xa8\x2a\x1c\x6a\x2c\xf3\x60\x84\x13\xd9\x91\x7a\xc3\x42\x19\xb4\x91\xf8\xc2\x97\xf8\x53\x4c\xd6\x57\xf2\x9c\x06\xc0\xc6\xaf\xa6\xbd\xf9\x6d\x73\x80\xd3\x29\x01\x18\xb9\x76\x2b\x74\x78\x45\xe5\xc2\x73\xc5\xe6\xbb\x74\xb2\x8d\x0b\x61\x29\xda\x25\x7e\xbc\x62\x14\xff\xf2\x9b\xd8\xc8\xce\xc7\xc8\x4c\xb1\xdf\x95\xfd\xfb\xf9\xc0\x28\xcb\x3d\x80\x69\x0f\x1a\x7f\x99\x47\xd6\x7b\xa0\xbd\xf3\xd8\xfe\x57\x00\x00\x00\xff\xff\xfb\x3d\x00\x65\x66\x01\x00\x00")
+
+func monitoring_reader_roleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_monitoring_reader_roleYaml,
+		"monitoring_reader_role.yaml",
+	)
+}
+
+func monitoring_reader_roleYaml() (*asset, error) {
+	bytes, err := monitoring_reader_roleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "monitoring_reader_role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _monitoring_reader_rolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8e\x31\x4e\x83\x31\x0c\x46\xf7\x9c\x22\x17\xc8\x8f\xd8\x50\x36\x38\x42\x91\xd8\xdd\xe4\x6b\x6a\xda\xd8\x91\xe3\x74\xe0\xf4\x08\xa9\x52\x59\x7e\x75\xf6\x7b\xcf\x1f\x0d\xfe\x82\x4d\x56\xc9\xd1\x8e\x54\x36\x5a\x7e\x56\xe3\x1f\x72\x56\xd9\x2e\x6f\x73\x63\x7d\xb9\xbd\x86\x0b\x4b\xcd\xf1\xa0\x57\x7c\xb0\x54\x96\x16\x3a\x9c\x2a\x39\xe5\x10\xa3\x50\x47\x8e\x7d\x69\xea\x2a\xec\x6a\x2c\x2d\x19\xa8\xc2\xee\xd7\x39\xa8\x20\x47\x1d\x90\x79\xe6\x93\xff\x03\x83\xe9\x15\x07\x9c\xfe\x42\x8f\x37\x4f\xaa\x73\x1d\xbf\x51\x7c\xe6\x90\xee\xd2\x27\xec\xc6\x05\xef\xa5\xe8\x12\x7f\xe8\x24\xd4\x50\xd3\x1a\xcd\xa8\x22\xe9\x80\x91\xeb\xfe\xae\x3d\xfe\x37\x00\x00\xff\xff\xd9\xce\xa4\x95\x2b\x01\x00\x00")
+
+func monitoring_reader_rolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_monitoring_reader_rolebindingYaml,
+		"monitoring_reader_rolebinding.yaml",
+	)
+}
+
+func monitoring_reader_rolebindingYaml() (*asset, error) {
+	bytes, err := monitoring_reader_rolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "monitoring_reader_rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _namespaceYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\xcb\x31\x0e\x42\x21\x0c\x06\xe0\x9d\x53\x34\xec\x68\x5c\x39\x84\xa3\x7b\x7d\xfc\x3e\x1b\xa1\x25\xa5\xcf\xf3\x1b\x27\x17\x0f\xf0\xbd\x44\x5b\xa5\x2b\x0f\xac\xc9\x1b\x12\x4f\xb9\xc1\x97\x98\x56\x7a\x5f\xd2\x40\x70\xe3\xe0\x9a\x88\x94\x07\x2a\xd9\x84\xae\xa7\x3c\xa2\x0c\x56\xde\xd1\xca\x31\x77\xe7\x86\x62\x13\xce\x61\x9e\x88\x3a\xdf\xd1\xd7\x17\xd1\x0f\x9c\xc4\xce\x5b\x3f\x56\xc0\xcb\x30\x95\x30\x17\xdd\x2b\xe5\xf0\x03\x39\x11\xb1\xaa\x05\x87\x98\xfe\xa3\x6a\x0d\x65\xa1\x63\x0b\xf3\x4a\x39\xa7\x4f\x00\x00\x00\xff\xff\x91\x84\xdf\xfb\xbc\x00\x00\x00")
+
+func namespaceYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_namespaceYaml,
+		"namespace.yaml",
+	)
+}
+
+func namespaceYaml() (*asset, error) {
+	bytes, err := namespaceYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _prometheus_roleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x8c\x31\x6e\xc3\x30\x0c\x45\x77\x9d\x82\xc8\x2e\x17\xdd\x02\x5d\xa0\x7b\x87\xee\x8c\xc4\xda\x84\x6d\x91\x20\x29\x17\xe8\xe9\x83\xc4\x9e\xf8\xde\x03\xf1\x51\xf9\x87\xcc\x59\x7a\x01\x7b\x60\x9d\x70\xc4\x22\xc6\xff\x18\x2c\x7d\x5a\xef\x3e\xb1\x7c\x1c\x9f\x69\xe5\xde\x0a\x7c\xcb\x46\x69\xa7\xc0\x86\x81\x25\x01\x74\xdc\xa9\x80\x9a\xec\x14\x0b\x0d\xcf\xeb\xdd\xaf\xec\x8a\x95\x0a\x88\x52\xf7\x85\x7f\x23\xef\xd8\x71\xa6\x96\x87\xce\x86\x8d\xb2\x28\x19\x86\x58\xb2\xb1\x91\x97\x94\x01\x95\xbf\x4c\x86\xfa\x6b\x3a\xc3\xed\x96\x00\x8c\x5c\x86\x55\xba\x9a\x93\x1d\x5c\xc9\xdf\x42\xbd\xa9\x70\x8f\xd3\x54\xda\x0b\x0e\xb2\xc7\xf5\x3c\x53\xbc\xef\xc6\x7e\xc2\x1f\x46\x5d\xd2\x33\x00\x00\xff\xff\xab\xd8\x23\x94\xf5\x00\x00\x00")
+
+func prometheus_roleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_prometheus_roleYaml,
+		"prometheus_role.yaml",
+	)
+}
+
+func prometheus_roleYaml() (*asset, error) {
+	bytes, err := prometheus_roleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "prometheus_role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _prometheus_rolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8f\x31\x6e\x03\x31\x0c\x04\x7b\xbd\x42\x1f\xd0\x05\xe9\x0c\x75\xc9\x13\x1c\x20\x3d\x2d\xad\xef\x98\xf3\x91\x02\x49\xb9\xc8\xeb\x03\x03\x06\x52\xa5\x48\xbb\x58\xcc\xee\xd0\xe0\x4f\x98\xb3\x4a\xcd\x76\xa1\xb6\xd0\x8c\x4d\x8d\xbf\x29\x58\x65\xd9\x4f\xbe\xb0\xbe\xdc\x5f\xd3\xce\xd2\x6b\x3e\xeb\x0d\xef\x2c\x9d\x65\x4d\x07\x82\x3a\x05\xd5\x94\xb3\xd0\x81\x9a\x87\xe9\x81\xd8\x30\xbd\xec\x27\x7f\xc6\x3e\xa8\xa1\x66\x1d\x10\xdf\xf8\x1a\xe5\x20\xa1\x15\xbd\xcc\xb1\x1a\x75\x14\x1d\x30\x0a\xb5\x64\x7a\xc3\x19\xd7\x07\xef\x77\xed\x2f\xb8\xcf\xcb\x17\x5a\x78\x4d\xe5\xd9\xfe\x80\xdd\xb9\xe1\xad\x35\x9d\x12\xff\x3d\xa5\xc2\xa1\xf6\xf0\xfa\x09\x00\x00\xff\xff\xdf\x2c\x62\x3f\x13\x01\x00\x00")
+
+func prometheus_rolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_prometheus_rolebindingYaml,
+		"prometheus_rolebinding.yaml",
+	)
+}
+
+func prometheus_rolebindingYaml() (*asset, error) {
+	bytes, err := prometheus_rolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "prometheus_rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _pullsecret_reader_roleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x8c\xb1\x6a\xc5\x30\x0c\x45\x77\x7d\x85\x78\xbb\x53\xba\x15\xff\x40\xf7\x0e\xdd\xf5\x1c\x25\x11\x71\x2c\x23\xc9\x29\xf4\xeb\x4b\x5f\x32\xdd\xcb\x39\x70\xa8\xcb\x37\x9b\x8b\xb6\x8c\xf6\xa4\x32\xd1\x88\x4d\x4d\x7e\x29\x44\xdb\xb4\x7f\xf8\x24\xfa\x76\xbe\xc3\x2e\x6d\xce\xf8\xa5\x95\xe1\xe0\xa0\x99\x82\x32\x20\x36\x3a\x38\xe3\x31\x34\xf5\x51\xab\x73\x31\x8e\x64\x4c\x33\xdb\x6d\xbd\x53\xe1\x8c\xda\xb9\xf9\x26\x4b\xa4\xa2\x6d\x91\x15\x6c\x54\xf6\x0c\x09\xa9\xcb\xa7\xe9\xe8\xfe\xdf\x4b\xf8\x78\x00\xa2\xb1\xeb\xb0\xc2\x37\xbb\xba\x0e\x88\x27\xdb\xf3\x86\x2b\xc7\x6b\xab\xf8\x75\x7e\x28\xca\x06\x7f\x01\x00\x00\xff\xff\xb2\xe9\x84\x3f\xd2\x00\x00\x00")
+
+func pullsecret_reader_roleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_pullsecret_reader_roleYaml,
+		"pullsecret_reader_role.yaml",
+	)
+}
+
+func pullsecret_reader_roleYaml() (*asset, error) {
+	bytes, err := pullsecret_reader_roleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "pullsecret_reader_role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _pullsecret_reader_rolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8e\x31\x6e\x03\x31\x0c\x04\x7b\xbd\x42\x1f\xd0\x05\xe9\x02\x75\xc9\x13\x1c\x20\x3d\x4d\xed\x9d\x19\xdf\x91\x02\x45\xb9\xc8\xeb\x83\x00\x06\x5c\x19\xa9\x77\x67\x76\xa9\xcb\x17\x7c\x88\x69\xcd\x7e\x26\x5e\x68\xc6\xc5\x5c\x7e\x28\xc4\x74\xb9\xbe\x8d\x45\xec\xe5\xf6\x9a\xae\xa2\xad\xe6\x93\xed\xf8\x10\x6d\xa2\x5b\x3a\x10\xd4\x28\xa8\xa6\x9c\x95\x0e\xd4\x7c\x4c\x2b\x7d\xee\xfb\x00\x3b\xa2\x38\xa8\xc1\xef\xe9\xe8\xc4\xa8\xd9\x3a\x74\x5c\x64\x8d\xc2\xa6\xab\x6c\xc9\x6d\xc7\x09\xeb\x9f\xe4\x31\xf1\x8f\x71\xcc\xf3\x37\x38\x46\x4d\xe5\x0e\x7d\xc2\x6f\xc2\x78\x67\xb6\xa9\xf1\xc0\x49\x69\x43\x2b\xb3\x6f\x4e\x0d\xc5\x3a\x9c\xc2\x9e\x7e\x7a\xda\xff\x0d\x00\x00\xff\xff\x43\xf5\x74\xa0\x27\x01\x00\x00")
+
+func pullsecret_reader_rolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_pullsecret_reader_rolebindingYaml,
+		"pullsecret_reader_rolebinding.yaml",
+	)
+}
+
+func pullsecret_reader_rolebindingYaml() (*asset, error) {
+	bytes, err := pullsecret_reader_rolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "pullsecret_reader_rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _service_accountYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\xca\xb1\x0d\x02\x31\x0c\x05\xd0\x3e\x53\x78\x81\x14\xb4\xe9\x98\x01\x89\xfe\x2b\xf9\x1c\x11\x8a\x6d\x39\xbe\x9b\x9f\x86\x96\xfe\xc1\xe7\x93\xb1\xa7\x69\x93\xeb\x56\x3e\x53\x47\x93\x07\xe3\x9a\x9d\xf7\xde\xed\xd4\x2c\x8b\x89\x81\x44\x2b\x22\x8a\xc5\x26\x0b\x8a\x83\xa3\x9e\x7e\x04\x06\xab\x39\x03\x69\xf1\x03\xdb\xd1\xd9\xc4\x9c\xba\xdf\xf3\x95\xf5\xaf\xff\x06\x00\x00\xff\xff\xfc\xc6\x66\xb9\x7f\x00\x00\x00")
+
+func service_accountYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_service_accountYaml,
+		"service_account.yaml",
+	)
+}
+
+func service_accountYaml() (*asset, error) {
+	bytes, err := service_accountYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "service_account.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _trusted_ca_bundle_configmapYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\xcd\xbd\x12\xc2\x20\x10\xc4\xf1\x9e\xa7\xb8\x49\x4f\x1c\x5b\x5a\x6b\x5b\xfb\x0b\x6c\xe2\x69\x38\x18\x38\x7c\x7e\xc7\x8f\xd1\x7e\xff\xbf\xe5\x2a\x17\xb4\x2e\x45\x03\x3d\x8e\xee\x2e\x9a\x02\x9d\x8a\xae\xb2\x9d\xb9\xba\x0c\xe3\xc4\xc6\xc1\x11\x29\x67\xf4\xca\x11\x81\x4a\x85\xf6\xab\xac\xe6\x33\x2b\x6f\x48\x7e\xd4\xad\x71\x82\x2f\x15\x8d\xad\xb4\xef\x3e\x90\xb5\xd1\x0d\xc9\x47\xf6\xcb\xd0\xb4\xc3\x11\xed\xbc\x60\xef\x2f\x93\x28\xbe\xbf\xe6\x9f\x38\x4b\x39\x88\xde\x10\xcd\xff\xd3\x4f\x19\x68\xb2\x36\x30\xb9\x67\x00\x00\x00\xff\xff\x96\x4c\x4f\xe4\xb5\x00\x00\x00")
+
+func trusted_ca_bundle_configmapYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_trusted_ca_bundle_configmapYaml,
+		"trusted_ca_bundle_configmap.yaml",
+	)
+}
+
+func trusted_ca_bundle_configmapYaml() (*asset, error) {
+	bytes, err := trusted_ca_bundle_configmapYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "trusted_ca_bundle_configmap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+// Asset loads and returns the asset for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func Asset(name string) ([]byte, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
+		}
+		return a.bytes, nil
+	}
+	return nil, fmt.Errorf("Asset %s not found", name)
+}
+
+// MustAsset is like Asset but panics when Asset would return an error.
+// It simplifies safe initialization of global variables.
+func MustAsset(name string) []byte {
+	a, err := Asset(name)
+	if err != nil {
+		panic("asset: Asset(" + name + "): " + err.Error())
+	}
+
+	return a
+}
+
+// AssetInfo loads and returns the asset info for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func AssetInfo(name string) (os.FileInfo, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
+		}
+		return a.info, nil
+	}
+	return nil, fmt.Errorf("AssetInfo %s not found", name)
+}
+
+// AssetNames returns the names of the assets.
+func AssetNames() []string {
+	names := make([]string, 0, len(_bindata))
+	for name := range _bindata {
+		names = append(names, name)
+	}
+	return names
+}
+
+// _bindata is a table, holding each asset generator, mapped to its name.
+var _bindata = map[string]func() (*asset, error){
+	"cluster_role.yaml":                  cluster_roleYaml,
+	"cluster_rolebinding.yaml":           cluster_rolebindingYaml,
+	"config.yaml":                        configYaml,
+	"custom_resource_definition.yaml":    custom_resource_definitionYaml,
+	"deployment.yaml":                    deploymentYaml,
+	"managed_upgrade_role.yaml":          managed_upgrade_roleYaml,
+	"managed_upgrade_rolebinding.yaml":   managed_upgrade_rolebindingYaml,
+	"monitoring_reader_role.yaml":        monitoring_reader_roleYaml,
+	"monitoring_reader_rolebinding.yaml": monitoring_reader_rolebindingYaml,
+	"namespace.yaml":                     namespaceYaml,
+	"prometheus_role.yaml":               prometheus_roleYaml,
+	"prometheus_rolebinding.yaml":        prometheus_rolebindingYaml,
+	"pullsecret_reader_role.yaml":        pullsecret_reader_roleYaml,
+	"pullsecret_reader_rolebinding.yaml": pullsecret_reader_rolebindingYaml,
+	"service_account.yaml":               service_accountYaml,
+	"trusted_ca_bundle_configmap.yaml":   trusted_ca_bundle_configmapYaml,
+}
+
+// AssetDir returns the file names below a certain
+// directory embedded in the file by go-bindata.
+// For example if you run go-bindata on data/... and data contains the
+// following hierarchy:
+//     data/
+//       foo.txt
+//       img/
+//         a.png
+//         b.png
+// then AssetDir("data") would return []string{"foo.txt", "img"}
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// AssetDir("") will return []string{"data"}.
+func AssetDir(name string) ([]string, error) {
+	node := _bintree
+	if len(name) != 0 {
+		cannonicalName := strings.Replace(name, "\\", "/", -1)
+		pathList := strings.Split(cannonicalName, "/")
+		for _, p := range pathList {
+			node = node.Children[p]
+			if node == nil {
+				return nil, fmt.Errorf("Asset %s not found", name)
+			}
+		}
+	}
+	if node.Func != nil {
+		return nil, fmt.Errorf("Asset %s not found", name)
+	}
+	rv := make([]string, 0, len(node.Children))
+	for childName := range node.Children {
+		rv = append(rv, childName)
+	}
+	return rv, nil
+}
+
+type bintree struct {
+	Func     func() (*asset, error)
+	Children map[string]*bintree
+}
+
+var _bintree = &bintree{nil, map[string]*bintree{
+	"cluster_role.yaml":                  {cluster_roleYaml, map[string]*bintree{}},
+	"cluster_rolebinding.yaml":           {cluster_rolebindingYaml, map[string]*bintree{}},
+	"config.yaml":                        {configYaml, map[string]*bintree{}},
+	"custom_resource_definition.yaml":    {custom_resource_definitionYaml, map[string]*bintree{}},
+	"deployment.yaml":                    {deploymentYaml, map[string]*bintree{}},
+	"managed_upgrade_role.yaml":          {managed_upgrade_roleYaml, map[string]*bintree{}},
+	"managed_upgrade_rolebinding.yaml":   {managed_upgrade_rolebindingYaml, map[string]*bintree{}},
+	"monitoring_reader_role.yaml":        {monitoring_reader_roleYaml, map[string]*bintree{}},
+	"monitoring_reader_rolebinding.yaml": {monitoring_reader_rolebindingYaml, map[string]*bintree{}},
+	"namespace.yaml":                     {namespaceYaml, map[string]*bintree{}},
+	"prometheus_role.yaml":               {prometheus_roleYaml, map[string]*bintree{}},
+	"prometheus_rolebinding.yaml":        {prometheus_rolebindingYaml, map[string]*bintree{}},
+	"pullsecret_reader_role.yaml":        {pullsecret_reader_roleYaml, map[string]*bintree{}},
+	"pullsecret_reader_rolebinding.yaml": {pullsecret_reader_rolebindingYaml, map[string]*bintree{}},
+	"service_account.yaml":               {service_accountYaml, map[string]*bintree{}},
+	"trusted_ca_bundle_configmap.yaml":   {trusted_ca_bundle_configmapYaml, map[string]*bintree{}},
+}}
+
+// RestoreAsset restores an asset under the given directory
+func RestoreAsset(dir, name string) error {
+	data, err := Asset(name)
+	if err != nil {
+		return err
+	}
+	info, err := AssetInfo(name)
+	if err != nil {
+		return err
+	}
+	err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
+	if err != nil {
+		return err
+	}
+	err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+	if err != nil {
+		return err
+	}
+	err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// RestoreAssets restores an asset under the given directory recursively
+func RestoreAssets(dir, name string) error {
+	children, err := AssetDir(name)
+	// File
+	if err != nil {
+		return RestoreAsset(dir, name)
+	}
+	// Dir
+	for _, child := range children {
+		err = RestoreAssets(dir, filepath.Join(name, child))
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func _filePath(dir, name string) string {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+}
diff --git a/pkg/operator/controllers/muo/deploy.go b/pkg/operator/controllers/muo/deploy.go
new file mode 100644
index 000000000..0aa0643b9
--- /dev/null
+++ b/pkg/operator/controllers/muo/deploy.go
@@ -0,0 +1,174 @@
+package muo
+
+// Copyright (c) Microsoft Corporation.
+// Licensed under the Apache License 2.0.
+
+import (
+	"context"
+	"errors"
+	"strings"
+
+	"github.com/ghodss/yaml"
+	"github.com/ugorji/go/codec"
+	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+	kruntime "k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/kubernetes/scheme"
+
+	"github.com/Azure/ARO-RP/pkg/api"
+	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
+	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
+	"github.com/Azure/ARO-RP/pkg/util/dynamichelper"
+	"github.com/Azure/ARO-RP/pkg/util/ready"
+)
+
+type muoConfig struct {
+	api.MissingFields
+	ConfigManager struct {
+		api.MissingFields
+		Source          string `json:"source,omitempty"`
+		OcmBaseUrl      string `json:"ocmBaseUrl,omitempty"`
+		LocalConfigName string `json:"localConfigName,omitempty"`
+	} `json:"configManager,omitempty"`
+}
+
+type Deployer interface {
+	CreateOrUpdate(context.Context, *arov1alpha1.Cluster, *config.MUODeploymentConfig) error
+	Remove(context.Context) error
+	IsReady(ctx context.Context) (bool, error)
+	Resources(*config.MUODeploymentConfig) ([]kruntime.Object, error)
+}
+
+type deployer struct {
+	kubernetescli kubernetes.Interface
+	dh            dynamichelper.Interface
+
+	jsonHandle *codec.JsonHandle
+}
+
+func newDeployer(kubernetescli kubernetes.Interface, dh dynamichelper.Interface) Deployer {
+	return &deployer{
+		kubernetescli: kubernetescli,
+		dh:            dh,
+
+		jsonHandle: new(codec.JsonHandle),
+	}
+}
+
+func (o *deployer) Resources(config *config.MUODeploymentConfig) ([]kruntime.Object, error) {
+	results := []kruntime.Object{}
+	for _, assetName := range AssetNames() {
+		b, err := Asset(assetName)
+		if err != nil {
+			return nil, err
+		}
+
+		obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(b, nil, nil)
+		if err != nil {
+			return nil, err
+		}
+
+		// set the image for the deployments
+		if d, ok := obj.(*appsv1.Deployment); ok {
+			for i := range d.Spec.Template.Spec.Containers {
+				d.Spec.Template.Spec.Containers[i].Image = config.Pullspec
+			}
+		}
+
+		if cm, ok := obj.(*corev1.ConfigMap); ok {
+			if cm.Name == "managed-upgrade-operator-config" && cm.Namespace == "openshift-managed-upgrade-operator" {
+				// read the config.yaml from the MUO ConfigMap which stores defaults
+				configDataJSON, err := yaml.YAMLToJSON([]byte(cm.Data["config.yaml"]))
+				if err != nil {
+					return nil, err
+				}
+
+				var configData muoConfig
+				err = codec.NewDecoderBytes(configDataJSON, o.jsonHandle).Decode(&configData)
+				if err != nil {
+					return nil, err
+				}
+
+				if config.EnableConnected {
+					configData.ConfigManager.Source = "OCM"
+					configData.ConfigManager.OcmBaseUrl = config.OCMBaseURL
+					configData.ConfigManager.LocalConfigName = ""
+				} else {
+					configData.ConfigManager.Source = "LOCAL"
+					configData.ConfigManager.LocalConfigName = "managed-upgrade-config"
+					configData.ConfigManager.OcmBaseUrl = ""
+				}
+
+				// Write the yaml back into the ConfigMap
+				var b []byte
+				err = codec.NewEncoderBytes(&b, o.jsonHandle).Encode(configData)
+				if err != nil {
+					return nil, err
+				}
+
+				cmYaml, err := yaml.JSONToYAML(b)
+				if err != nil {
+					return nil, err
+				}
+				cm.Data["config.yaml"] = string(cmYaml)
+			}
+		}
+
+		results = append(results, obj)
+	}
+
+	return results, nil
+}
+
+func (o *deployer) CreateOrUpdate(ctx context.Context, cluster *arov1alpha1.Cluster, config *config.MUODeploymentConfig) error {
+	resources, err := o.Resources(config)
+	if err != nil {
+		return err
+	}
+
+	err = dynamichelper.SetControllerReferences(resources, cluster)
+	if err != nil {
+		return err
+	}
+
+	err = dynamichelper.Prepare(resources)
+	if err != nil {
+		return err
+	}
+
+	return o.dh.Ensure(ctx, resources...)
+}
+
+func (o *deployer) Remove(ctx context.Context) error {
+	resources, err := o.Resources(&config.MUODeploymentConfig{})
+	if err != nil {
+		return err
+	}
+
+	var errs []error
+	for _, obj := range resources {
+		// delete any deployments we have
+		if d, ok := obj.(*appsv1.Deployment); ok {
+			err := o.dh.EnsureDeleted(ctx, "Deployment", d.Namespace, d.Name)
+			// Don't error out because then we might delete some resources and not others
+			if err != nil {
+				errs = append(errs, err)
+			}
+		}
+	}
+
+	if len(errs) != 0 {
+		errContent := []string{"error removing MUO:"}
+		for _, err := range errs {
+			errContent = append(errContent, err.Error())
+		}
+		return errors.New(strings.Join(errContent, "\n"))
+	}
+
+	return nil
+}
+
+func (o *deployer) IsReady(ctx context.Context) (bool, error) {
+	return ready.CheckDeploymentIsReady(ctx, o.kubernetescli.AppsV1().Deployments("openshift-managed-upgrade-operator"), "managed-upgrade-operator")()
+}
diff --git a/pkg/operator/controllers/muo/generate.go b/pkg/operator/controllers/muo/generate.go
new file mode 100644
index 000000000..2d682e94c
--- /dev/null
+++ b/pkg/operator/controllers/muo/generate.go
@@ -0,0 +1,12 @@
+package muo
+
+// Copyright (c) Microsoft Corporation.
+// Licensed under the Apache License 2.0.
+
+// bindata for the above yaml files
+//go:generate go run ../../../../vendor/github.com/go-bindata/go-bindata/go-bindata -nometadata -pkg muo -prefix staticresources/ -o bindata.go staticresources/...
+//go:generate gofmt -s -l -w bindata.go
+
+//go:generate rm -rf ../../mocks/$GOPACKAGE
+//go:generate go run ../../../../vendor/github.com/golang/mock/mockgen -destination=../../mocks/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/operator/controllers/$GOPACKAGE Deployer
+//go:generate go run ../../../../vendor/golang.org/x/tools/cmd/goimports -local=github.com/Azure/ARO-RP -e -w ../../mocks/$GOPACKAGE/$GOPACKAGE.go
diff --git a/pkg/operator/controllers/muo/muo_controller.go b/pkg/operator/controllers/muo/muo_controller.go
index d71fe31cb..ca0b9da52 100644
--- a/pkg/operator/controllers/muo/muo_controller.go
+++ b/pkg/operator/controllers/muo/muo_controller.go
@@ -5,7 +5,6 @@ package muo
 
 import (
 	"context"
-	"embed"
 	"fmt"
 	"strings"
 	"time"
@@ -24,7 +23,6 @@ import (
 	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
 	aroclient "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned"
 	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
-	"github.com/Azure/ARO-RP/pkg/util/deployer"
 	"github.com/Azure/ARO-RP/pkg/util/dynamichelper"
 	"github.com/Azure/ARO-RP/pkg/util/pullsecret"
 	"github.com/Azure/ARO-RP/pkg/util/version"
@@ -43,9 +41,6 @@ const (
 	pullSecretOCMKey = "cloud.openshift.com"
 )
 
-//go:embed staticresources
-var staticFiles embed.FS
-
 var pullSecretName = types.NamespacedName{Name: "pull-secret", Namespace: "openshift-config"}
 
 type MUODeploymentConfig struct {
@@ -57,7 +52,7 @@ type MUODeploymentConfig struct {
 type Reconciler struct {
 	arocli        aroclient.Interface
 	kubernetescli kubernetes.Interface
-	deployer      deployer.Deployer
+	deployer      Deployer
 
 	readinessPollTime time.Duration
 	readinessTimeout  time.Duration
@@ -67,7 +62,7 @@ func NewReconciler(arocli aroclient.Interface, kubernetescli kubernetes.Interfac
 	return &Reconciler{
 		arocli:        arocli,
 		kubernetescli: kubernetescli,
-		deployer:      deployer.NewDeployer(kubernetescli, dh, staticFiles, "staticresources"),
+		deployer:      newDeployer(kubernetescli, dh),
 
 		readinessPollTime: 10 * time.Second,
 		readinessTimeout:  5 * time.Minute,
@@ -143,13 +138,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.
 		defer cancel()
 
 		err := wait.PollImmediateUntil(r.readinessPollTime, func() (bool, error) {
-			return r.deployer.IsReady(ctx, "openshift-managed-upgrade-operator", "managed-upgrade-operator")
+			return r.deployer.IsReady(ctx)
 		}, timeoutCtx.Done())
 		if err != nil {
 			return reconcile.Result{}, fmt.Errorf("managed Upgrade Operator deployment timed out on Ready: %w", err)
 		}
 	} else if strings.EqualFold(managed, "false") {
-		err := r.deployer.Remove(ctx, config.MUODeploymentConfig{})
+		err := r.deployer.Remove(ctx)
 		if err != nil {
 			return reconcile.Result{}, err
 		}
@@ -167,7 +162,7 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
 	builder := ctrl.NewControllerManagedBy(mgr).
 		For(&arov1alpha1.Cluster{}, builder.WithPredicates(aroClusterPredicate))
 
-	resources, err := r.deployer.Template(&config.MUODeploymentConfig{}, staticFiles)
+	resources, err := r.deployer.Resources(&config.MUODeploymentConfig{})
 	if err != nil {
 		return err
 	}
diff --git a/pkg/operator/controllers/muo/staticresources/config.yaml b/pkg/operator/controllers/muo/staticresources/config.yaml
index 5b08f2032..228bdb617 100644
--- a/pkg/operator/controllers/muo/staticresources/config.yaml
+++ b/pkg/operator/controllers/muo/staticresources/config.yaml
@@ -6,9 +6,8 @@ metadata:
 data:
   config.yaml: |
     configManager:
-      source: {{ if .EnableConnected }}OCM{{ else }}LOCAL{{ end }}
-      {{ if .EnableConnected }}ocmBaseUrl: {{.OCMBaseURL}}{{end}}
-      {{ if not .EnableConnected }}localConfigName: managed-upgrade-config{{end}}
+      source: LOCAL
+      localConfigName: managed-upgrade-config
       watchInterval: 1
     maintenance:
       controlPlaneTime: 90
diff --git a/pkg/operator/controllers/muo/staticresources/deployment.yaml b/pkg/operator/controllers/muo/staticresources/deployment.yaml
index 142bc8235..19e682ca8 100644
--- a/pkg/operator/controllers/muo/staticresources/deployment.yaml
+++ b/pkg/operator/controllers/muo/staticresources/deployment.yaml
@@ -40,7 +40,7 @@ spec:
         - name: managed-upgrade-operator
           # Replace this with the built image name
           # This will get replaced on deploy by /hack/generate-operator-bundle.py
-          image: "{{ .Pullspec }}"
+          image: GENERATED
           command:
           - managed-upgrade-operator
           imagePullPolicy: Always
diff --git a/pkg/operator/deploy/bindata.go b/pkg/operator/deploy/bindata.go
new file mode 100644
index 000000000..81d7fa386
--- /dev/null
+++ b/pkg/operator/deploy/bindata.go
@@ -0,0 +1,478 @@
+// Code generated for package deploy by go-bindata DO NOT EDIT. (@generated)
+// sources:
+// deploy/staticresources/aro.openshift.io_clusters.yaml
+// deploy/staticresources/master/deployment.yaml
+// deploy/staticresources/master/rolebinding.yaml
+// deploy/staticresources/master/service.yaml
+// deploy/staticresources/master/serviceaccount.yaml
+// deploy/staticresources/namespace.yaml
+// deploy/staticresources/preview.aro.openshift.io_previewfeatures.yaml
+// deploy/staticresources/worker/deployment.yaml
+// deploy/staticresources/worker/role.yaml
+// deploy/staticresources/worker/rolebinding.yaml
+// deploy/staticresources/worker/serviceaccount.yaml
+package deploy
+
+import (
+	"bytes"
+	"compress/gzip"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+func bindataRead(data []byte, name string) ([]byte, error) {
+	gz, err := gzip.NewReader(bytes.NewBuffer(data))
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, gz)
+	clErr := gz.Close()
+
+	if err != nil {
+		return nil, fmt.Errorf("Read %q: %v", name, err)
+	}
+	if clErr != nil {
+		return nil, err
+	}
+
+	return buf.Bytes(), nil
+}
+
+type asset struct {
+	bytes []byte
+	info  os.FileInfo
+}
+
+type bindataFileInfo struct {
+	name    string
+	size    int64
+	mode    os.FileMode
+	modTime time.Time
+}
+
+// Name return file name
+func (fi bindataFileInfo) Name() string {
+	return fi.name
+}
+
+// Size return file size
+func (fi bindataFileInfo) Size() int64 {
+	return fi.size
+}
+
+// Mode return file mode
+func (fi bindataFileInfo) Mode() os.FileMode {
+	return fi.mode
+}
+
+// Mode return file modify time
+func (fi bindataFileInfo) ModTime() time.Time {
+	return fi.modTime
+}
+
+// IsDir return file whether a directory
+func (fi bindataFileInfo) IsDir() bool {
+	return fi.mode&os.ModeDir != 0
+}
+
+// Sys return file is sys mode
+func (fi bindataFileInfo) Sys() interface{} {
+	return nil
+}
+
+var _aroOpenshiftIo_clustersYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x58\xcd\x72\xdb\x36\x10\xbe\xeb\x29\x76\xd2\x83\x0f\xad\xa8\x64\x7a\x68\xab\x9b\x2b\x27\xa9\x26\x69\xac\xb1\x3c\xb9\x64\x72\x58\x81\x4b\x6a\x63\x12\x60\x81\x85\x12\xa7\xd3\x77\xef\x00\x24\x25\x4a\xa6\x64\xd1\x99\xf4\x50\x5e\x24\x2e\xf6\x7f\xbf\x5d\x00\x1c\x8d\xc7\xe3\x11\x56\xfc\x9e\xac\x63\xa3\xa7\x80\x15\xd3\x17\x21\x1d\xde\x5c\x72\xf7\xab\x4b\xd8\x4c\x36\x2f\x46\x77\xac\xd3\x29\xcc\xbc\x13\x53\xde\x90\x33\xde\x2a\xba\xa2\x8c\x35\x0b\x1b\x3d\x2a\x49\x30\x45\xc1\xe9\x08\x00\xb5\x36\x82\x81\xec\xc2\x2b\x80\x32\x5a\xac\x29\x0a\xb2\xe3\x9c\x74\x72\xe7\x57\xb4\xf2\x5c\xa4\x64\xa3\xf2\xd6\xf4\xe6\x79\xf2\x4b\xf2\x7c\x04\xa0\x2c\x45\xf1\x5b\x2e\xc9\x09\x96\xd5\x14\xb4\x2f\x8a\x11\x80\xc6\x92\xa6\xa0\x0a\xef\x84\xac\x4b\xd0\x9a\xc4\x54\xa4\xdd\x9a\x33\x49\xd8\x8c\x5c\x45\x2a\xd8\xcc\xad\xf1\xd5\x14\x1e\xac\xd7\x1a\x1a\xb7\x9a\x90\x6a\x65\x91\x52\xb0\x93\x37\x5d\xea\x5b\x76\x12\x57\xaa\xc2\x5b\x2c\x76\xa6\x23\xd1\xb1\xce\x7d\x81\x76\x4b\x1e\x01\x38\x65\x2a\xea\x6a\x6d\xc2\x8b\x36\xc7\x4d\x00\x9b\x17\x58\x54\x6b\x7c\x51\x6b\x51\x6b\x2a\xb1\x76\x09\x20\xb8\x7b\xb9\x98\xbf\xff\x79\xb9\x47\x06\x48\xc9\x29\xcb\x95\xc4\x54\x35\xea\x81\x1d\xc8\x9a\xa0\xe6\x85\xcc\xd8\xf8\xda\x3a\x09\x97\x8b\xf9\x56\xbe\xb2\xa6\x22\x2b\xdc\x46\x5f\x3f\x9d\xd2\x77\xa8\x07\xd6\x2e\x82\x43\x35\x17\xa4\xa1\xe6\x54\x9b\x6d\x42\xa3\xb4\x89\x01\x4c\x06\xb2\x66\x07\x96\x2a\x4b\x8e\x74\x8d\x82\x3d\xc5\x10\x98\x50\x83\x59\x7d\x22\x25\x09\x2c\xc9\x06\x35\xe0\xd6\xc6\x17\x69\x80\xca\x86\xac\x80\x25\x65\x72\xcd\x5f\xb7\xba\x1d\x88\x89\x46\x0b\x14\x6a\x8a\xb2\x7b\x58\x0b\x59\x8d\x05\x6c\xb0\xf0\xf4\x13\xa0\x4e\xa1\xc4\x7b\xb0\x14\xac\x80\xd7\x1d\x7d\x91\xc5\x25\xf0\xa7\xb1\x04\xac\x33\x33\x85\xb5\x48\xe5\xa6\x93\x49\xce\xd2\x42\x5e\x99\xb2\xf4\x9a\xe5\x7e\x12\xd1\xcb\x2b\x2f\xc6\xba\x49\x4a\x1b\x2a\x26\x8e\xf3\x31\x5a\xb5\x66\x21\x25\xde\xd2\x04\x2b\x1e\x47\xd7\x75\x84\x7d\x52\xa6\x3f\xd8\xa6\x49\xdc\xc5\x9e\xaf\x72\x1f\xe0\xe1\xc4\xb2\xce\x3b\x0b\x11\x8b\x27\x2a\x10\x50\x19\xaa\x8d\x8d\x68\x1d\xc5\x2e\xd1\x81\x14\xb2\x73\xf3\x72\x79\x0b\xad\xe9\x58\x8c\xc3\xec\xc7\xbc\xef\x04\xdd\xae\x04\x21\x61\xac\x33\xb2\x75\x11\x33\x6b\xca\xa8\x93\x74\x5a\x19\xd6\xd2\x60\x8b\x49\x1f\xa6\xdf\xf9\x55\xc9\x12\xea\xfe\x97\x27\x27\xa1\x56\x09\xcc\xe2\x1c\x80\x15\x81\xaf\x52\x14\x4a\x13\x98\x6b\x98\x61\x49\xc5\x0c\x1d\x7d\xf7\x02\x84\x4c\xbb\x71\x48\xec\x79\x25\xe8\x8e\xb0\x43\xe6\x3a\x6b\x9d\x85\x76\xd0\x1c\xa9\x57\xd3\x9f\xcb\x8a\xd4\x5e\xc7\xa4\xe4\xd8\x06\x4c\x0b\x0a\x85\x4e\xe8\x4e\x9f\xf6\xe9\xef\xd4\xf0\xa0\xb2\x57\xa6\x44\xd6\x87\x0b\x47\x83\x82\xba\xc7\xe7\x5a\xe6\x8b\x61\x42\x9d\xec\xf6\x4e\x88\x9d\x7c\x68\xbe\xfc\x20\x06\x00\xfc\xfa\x52\x6f\xd8\x1a\x5d\x92\x96\x41\xa6\x57\xa8\x35\xd9\x87\x22\x7b\x19\xfe\x3d\x32\x6d\x93\xcb\x19\x60\x4b\x6b\x46\xc9\x8a\xc2\xbf\xcf\xba\x1d\x1c\x2a\xee\x5d\x0f\xfc\x3c\x95\x6f\x68\x36\xaf\xde\x08\x1e\x89\xe2\x28\x74\xa2\xd2\xba\xec\xed\x46\xfa\x3a\x6c\x57\xf3\x74\x50\x96\xd2\xe1\x40\xc8\x51\xe8\x33\xde\xd7\x10\xea\x09\x96\x85\xca\xde\x1c\x9c\x11\x26\x5a\x8b\xf7\xfd\xf6\x16\x96\x37\x28\xf4\xb2\x19\x23\x03\x81\x98\x93\xa6\x0d\xbe\x35\x79\xce\x3a\x7f\x28\xf9\x68\xf1\x32\xce\x8f\xe2\x37\x2a\x40\x09\x7b\xc7\x14\x2e\x3e\x3c\x1f\xff\xf6\xf1\xc7\xa4\xfe\xb9\x18\x5e\x6f\x80\xd2\x68\x16\x13\x16\x5f\xcf\x96\x97\x4a\x19\x7f\x0c\x38\xa4\x7d\xd9\xbf\x32\x86\xcb\x9b\xeb\xf6\xf8\x61\x72\x37\x7f\x77\x7b\x16\xdf\xe2\xe6\xfa\xea\x2c\xc6\x6f\x0e\xec\x64\x5f\x3f\x16\xdc\x15\x63\xae\x8d\x13\x56\x6e\x61\x4d\x7a\x84\xeb\xf6\xe1\x16\xdf\x2e\xcd\xf0\x15\xb2\xcd\xf0\xcb\x37\xc7\xf1\x2e\x1c\x05\x2b\x54\xf4\x3f\x28\xd1\x89\x59\xc3\x3a\xb3\x38\x70\xb8\xb0\xce\x2d\x39\x37\xb0\x55\xeb\x53\x18\xc9\x6c\x4d\xea\xae\x6f\x82\x9f\x6e\x56\x6f\x8b\x5e\xfa\x89\xc1\xf4\x88\x43\x5d\x86\xbe\x01\x75\x32\x6f\x85\x51\xf1\xf8\x3a\x28\x05\x21\x3e\x14\x63\xb3\x02\xf3\x1e\x8f\x31\x4d\xe3\x7d\x09\x8b\xc5\xc9\x54\x9c\x8c\x69\x6f\x1f\xbc\x6e\x0c\xbe\x0a\x06\xb7\xdb\x61\x46\x18\x36\xee\x38\x81\xdd\xf6\x5e\x70\x79\x73\xbd\xe5\x1f\x92\x89\xf6\x3c\xd9\x07\xa2\x3d\x67\xda\xfd\x6c\x7e\xd5\xde\x4c\x2e\xbf\x06\x37\x76\x0a\xea\x2b\x02\x75\x2e\x4c\x67\x07\xee\xc8\x6e\x58\xd1\xd2\xaf\x34\xc9\x7f\xb0\x7b\x39\x31\x16\x73\x5a\xfa\x2c\xe3\x2f\x83\x40\xb0\xd1\x24\x83\x1a\xee\xd8\x21\x53\x50\xbc\x3b\xe3\x98\x19\xf9\xf6\x0e\x9a\x66\x15\xd2\xf5\xf4\x93\xa6\x32\xba\x46\xea\x90\x44\xf7\x02\x73\xd6\x6a\x0a\x90\xf8\xe4\x5d\x7d\x8d\x70\x82\x3a\x45\x9b\xee\x0c\x41\xc6\x54\xa4\x2e\xe9\xd1\x7b\x7a\x6c\x00\x14\xe8\xe4\xd6\xa2\x76\xdc\x7e\x35\x38\x36\x2b\x32\x63\x4b\x94\x29\x84\xfb\xc8\x58\xb8\xa4\xa7\xce\x94\x92\x9c\xc3\xfc\xa8\x9d\x47\xe5\x2d\xa1\x3b\x76\x22\x39\x43\xbc\x0f\x19\x03\xc4\x23\xc3\xd3\x84\x4f\x8c\x89\x53\xcd\xd4\xce\xc5\x47\xae\x12\xbd\x66\x2d\xa5\x7f\xa0\xbc\xa1\x7b\xb7\xa8\xef\xac\xdf\xbb\xf7\x7b\x63\x7c\x40\xac\x1b\x6c\x0a\x62\x7d\x0d\xa3\x66\x60\x74\x29\x7e\xb5\xfd\x0c\xd0\x7a\xd7\x94\x0e\xfe\xfe\x67\xb4\xab\x22\x2a\x45\x95\x50\xfa\xee\xf0\xeb\xd4\xb3\x67\xf1\xa5\xfd\xfc\x14\x5f\x3b\xbd\x09\x1f\x3e\x8e\x6a\xc3\x94\xbe\x6f\x3f\x34\x05\xe2\xbf\x01\x00\x00\xff\xff\xa7\x08\xf4\x35\xd8\x13\x00\x00")
+
+func aroOpenshiftIo_clustersYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_aroOpenshiftIo_clustersYaml,
+		"aro.openshift.io_clusters.yaml",
+	)
+}
+
+func aroOpenshiftIo_clustersYaml() (*asset, error) {
+	bytes, err := aroOpenshiftIo_clustersYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "aro.openshift.io_clusters.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _masterDeploymentYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x52\xc1\x6e\xdb\x30\x0c\xbd\xfb\x2b\x88\xde\xdd\xa4\xb7\x42\xb7\x62\x0d\x7a\x19\x82\x62\x59\x77\x67\x64\x26\x16\x22\x8b\x02\x49\x07\x75\xbf\x7e\x10\x92\x28\xce\x0a\x64\x3a\x19\x7c\x8f\xef\x3d\xd2\xc4\x1c\xfe\x90\x68\xe0\xe4\x00\x73\xd6\xc5\xf1\xa9\x39\x84\xd4\x39\x78\xa5\x1c\x79\x1a\x28\x59\x33\x90\x61\x87\x86\xae\x01\x88\xb8\xa5\xa8\xe5\x0b\x4a\x83\x03\x14\x6e\x39\x93\xa0\xb1\xb4\x03\xaa\x91\x34\x00\x09\x07\xba\x87\x69\x46\x4f\x0e\x38\x53\xd2\x3e\xec\xac\xc5\xaf\x51\xa8\x92\x1b\xcd\xe4\x8b\x89\x50\x8e\xc1\xa3\x3a\x78\x6a\x00\x94\x22\x79\x63\x39\xd9\x0f\x68\xbe\xff\x39\xcb\x73\x37\x91\x9a\xa0\xd1\x7e\x3a\x51\x85\x63\x0c\x69\xff\x91\x3b\x34\xba\x74\x0f\xf8\xb9\x19\x65\x4f\x27\xb3\x73\xe5\x23\xe1\x11\x43\xc4\x6d\x24\x07\xcb\x06\xc0\x68\xc8\xb1\x76\xcd\x77\x53\x5e\xbc\xc9\x73\x37\x11\xc0\x65\xca\xf2\x3c\x27\xc3\x90\x48\x6a\x73\x0b\x9e\x87\x01\x53\x77\x55\x6b\x8b\xd4\x55\x5b\xf6\x3a\xc7\xea\xf6\xae\xa5\x99\x59\x79\x61\xc0\x32\xde\xdb\x6a\xbd\xfa\xf5\xf2\x7b\xf5\x5a\x81\xef\xff\xab\x42\x99\xc5\x6e\x6c\x6a\xd2\x77\x16\x73\xf0\xbc\x7c\x5e\x56\xf4\xa2\xd4\x9b\xe5\x5a\x8c\xe1\x48\x89\x54\xdf\x85\xb7\xe4\x66\xdc\xc2\x7a\x23\x9b\x97\x00\x32\x5a\xef\x60\xd1\x13\x46\xeb\xbf\x16\x42\xd8\x4d\xb7\x84\x7f\x6d\x13\x77\xb4\xb9\x39\x8d\x4b\xb5\x15\x8e\xf4\x78\x18\xb7\x24\x89\x8c\xf4\x31\xf0\xe2\xb4\x12\x07\x0f\x0f\x67\xaa\x92\x1c\x83\xa7\x17\xef\x79\x4c\xb6\xbe\x73\xb9\xdf\xd9\xf7\x98\x59\x02\x4b\xb0\xe9\x47\x44\xd5\x93\xac\x4e\x6a\x34\xb4\x3e\x8e\x85\xd7\x7a\x09\x16\x3c\xc6\x73\x83\x71\x2c\x3a\x81\xd3\xec\x06\x0e\x34\xb9\xff\xcc\x52\x47\xbe\xe4\x70\xb0\xfa\x0c\x6a\x5a\x01\xda\xed\xc8\x9b\x83\x35\x6f\x7c\x4f\xdd\x18\xa9\xf9\x1b\x00\x00\xff\xff\x57\x5c\x5d\xa2\xfa\x03\x00\x00")
+
+func masterDeploymentYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_masterDeploymentYaml,
+		"master/deployment.yaml",
+	)
+}
+
+func masterDeploymentYaml() (*asset, error) {
+	bytes, err := masterDeploymentYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "master/deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _masterRolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x8e\xb1\x4e\x03\x31\x0c\x40\x77\x7f\x85\x7f\x20\x87\xd8\x50\x36\x60\x60\x2f\x12\xbb\x9b\xb8\xd4\xf4\x62\x47\x8e\xd3\xa1\x5f\x8f\xaa\xa2\x5b\x90\x6e\xb5\xdf\xf3\x33\x75\xf9\x62\x1f\x62\x9a\xd1\x8f\x54\x16\x9a\x71\x36\x97\x1b\x85\x98\x2e\x97\x97\xb1\x88\x3d\x5d\x9f\xe1\x22\x5a\x33\xbe\xaf\x73\x04\xfb\xc1\x56\x7e\x13\xad\xa2\xdf\xd0\x38\xa8\x52\x50\x06\x44\xa5\xc6\x19\xc9\x2d\x59\x67\xa7\x30\x4f\x8d\xee\x02\xb8\xad\x7c\xe0\xd3\x1d\xa2\x2e\x1f\x6e\xb3\xef\x04\x01\xf1\x5f\x6f\x3b\x5f\x1e\xb3\x44\xb5\x89\xc2\x98\xc7\x1f\x2e\x31\x32\xa4\x3f\xe7\x93\xfd\x2a\x85\x5f\x4b\xb1\xa9\xb1\xfb\xd5\x63\x37\x3a\x15\xce\x68\x9d\x75\x9c\xe5\x14\x89\x6e\xd3\x79\x83\xe1\x37\x00\x00\xff\xff\x4f\x98\xa4\x7c\x24\x01\x00\x00")
+
+func masterRolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_masterRolebindingYaml,
+		"master/rolebinding.yaml",
+	)
+}
+
+func masterRolebindingYaml() (*asset, error) {
+	bytes, err := masterRolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "master/rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _masterServiceYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x8d\x41\xca\xc2\x40\x0c\x46\xf7\x73\x8a\x5c\x60\xa0\xff\xae\xcc\x29\x7e\x10\xdc\x87\xe9\xa7\x1d\xb4\x93\x90\xc4\x2e\x3c\xbd\xd4\x16\x5d\xb9\x0b\xef\x7b\xbc\xb0\xb6\x33\xcc\x9b\xf4\x42\xeb\x5f\xba\xb5\x3e\x15\x3a\xc1\xd6\x56\x91\x16\x04\x4f\x1c\x5c\x12\x51\xe7\x05\x85\xd8\x24\x8b\xc2\x38\xc4\xf2\xc2\x1e\xb0\x63\x73\xe5\x8a\x42\xa2\xe8\x3e\xb7\x4b\x64\x7e\x3e\x0c\x1f\x39\xb9\xa2\x6e\x1d\xc7\x1d\x35\xc4\xb6\x9b\x88\x55\x7f\x45\x55\x2c\x7c\xb7\xf2\xf1\x7d\x8e\xd0\x37\xd8\xd7\x42\xe3\x30\x0e\x07\x08\xb6\x2b\xe2\xff\x8b\x5f\x01\x00\x00\xff\xff\x10\x70\xf6\x36\xda\x00\x00\x00")
+
+func masterServiceYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_masterServiceYaml,
+		"master/service.yaml",
+	)
+}
+
+func masterServiceYaml() (*asset, error) {
+	bytes, err := masterServiceYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "master/service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _masterServiceaccountYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x31\x8e\x02\x31\x0c\x05\xd0\x3e\xa7\xf0\x05\x52\x6c\xeb\x6e\xcf\x80\x44\xff\x95\xf9\x08\x0b\xc5\x8e\x1c\xcf\x14\x9c\x9e\x06\x51\xbf\x87\x65\x77\xe6\xb6\x70\x95\xeb\xaf\xbd\xcc\x0f\x95\x1b\xf3\xb2\xc1\xff\x31\xe2\xf4\x6a\x93\x85\x03\x05\x6d\x22\x8e\x49\x15\x64\xf4\x58\x4c\x54\x64\x9f\xd8\xc5\xfc\xda\x5e\x18\x54\x89\x45\xdf\x4f\x7b\x54\xc7\xfb\x4c\xfe\x72\xfb\x04\x00\x00\xff\xff\xe4\xf5\x04\x25\x70\x00\x00\x00")
+
+func masterServiceaccountYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_masterServiceaccountYaml,
+		"master/serviceaccount.yaml",
+	)
+}
+
+func masterServiceaccountYaml() (*asset, error) {
+	bytes, err := masterServiceaccountYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "master/serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _namespaceYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\xca\xb1\x0d\x02\x31\x0c\x05\xd0\x3e\x53\x58\xd7\x07\x44\x9b\x21\x28\xe9\xbf\x2e\x1f\x61\x41\xec\x28\x36\x14\x4c\x8f\xa8\xae\x7f\x98\x7a\xe3\x0a\x75\x6b\xf2\xb9\x94\xa7\x5a\x6f\x72\xc5\x60\x4c\xec\x2c\x83\x89\x8e\x44\x2b\x22\x86\xc1\x26\x3e\x69\xf1\xd0\x7b\x56\x7c\xdf\x8b\xd5\x27\x17\xd2\x57\x11\x81\x99\x27\x52\xdd\xe2\xef\xe5\xb0\x27\xf5\xb3\x79\x67\x0d\xbe\xb8\xa7\xaf\x26\xdb\x56\x7e\x01\x00\x00\xff\xff\xc1\xaf\xa6\x4c\x7c\x00\x00\x00")
+
+func namespaceYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_namespaceYaml,
+		"namespace.yaml",
+	)
+}
+
+func namespaceYaml() (*asset, error) {
+	bytes, err := namespaceYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _previewAroOpenshiftIo_previewfeaturesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x58\x4d\x73\xdb\x38\x12\xbd\xeb\x57\x74\x65\x0f\xbe\x44\xb4\xbd\xa9\xca\xee\xea\xe6\xb2\x93\x94\x6b\x13\x27\x65\xbb\x9c\xc3\xd4\x1c\x5a\x44\x93\x44\x0c\x02\x0c\xd0\x90\x46\x33\x35\xff\x7d\x0a\x00\x29\x91\x14\x69\x7b\x32\x33\x3c\x89\xf8\x78\xdd\x78\xfd\xba\xd1\xd4\x62\xb9\x5c\x2e\xb0\x91\x0f\x64\x9d\x34\x7a\x05\xd8\x48\xfa\x85\x49\x87\x37\x97\x3d\xfe\xd7\x65\xd2\x9c\x6e\xce\x17\x8f\x52\x8b\x15\x5c\x7a\xc7\xa6\xbe\x25\x67\xbc\xcd\xe9\x8a\x0a\xa9\x25\x4b\xa3\x17\x35\x31\x0a\x64\x5c\x2d\x00\x50\x6b\xc3\x18\x86\x5d\x78\x05\xc8\x8d\x66\x6b\x94\x22\xbb\x2c\x49\x67\x8f\x7e\x4d\x6b\x2f\x95\x20\x1b\xc1\x3b\xd3\x9b\xb3\xec\x3f\xd9\xd9\x02\x20\xb7\x14\xb7\xdf\xcb\x9a\x1c\x63\xdd\xac\x40\x7b\xa5\x16\x00\x1a\x6b\x5a\x41\x63\x69\x23\x69\x5b\x10\xb2\xb7\xe4\xb2\xf6\x3d\x43\x6b\x32\xd3\x90\x76\x95\x2c\x38\x93\x66\xe1\x1a\xca\x83\x0b\xa5\x35\xbe\xd9\xef\x3b\x5e\x97\x80\x5b\x6f\xd3\x49\xbf\xa4\xb5\xef\x93\x8d\x38\xa1\xa4\xe3\xff\x4f\x4c\x7e\x94\x8e\xe3\x82\x46\x79\x8b\xea\xc8\xbf\x38\xe7\xa4\x2e\xbd\x42\x3b\x9e\x5d\x00\xb8\xdc\x34\xb4\x82\x4b\xe5\x1d\x93\x5d\x00\xb4\x8c\x44\x7f\x96\xed\x99\x37\xe7\xa8\x9a\x0a\xcf\x13\x58\x5e\x51\x8d\xc9\x5d\x80\x70\x94\x8b\x2f\xd7\x0f\x6f\xee\x06\xc3\x00\x82\x5c\x6e\x65\xc3\x91\xdd\xa1\xcf\x20\x1d\x70\x45\x90\xb6\x40\x61\x6c\x7c\x6d\x7d\x83\xd6\x39\xb8\xf8\x72\xbd\x47\x6b\xac\x69\xc8\xb2\xec\x78\x4a\x4f\x4f\x3b\xbd\xd1\x91\xed\x93\xe0\x5e\x5a\x05\x22\x88\x86\x92\xf5\xf6\xa0\x24\xda\x13\x81\x29\x80\x2b\xe9\xc0\x52\x63\xc9\x91\x4e\x32\x1a\x00\x43\x58\x84\x1a\xcc\xfa\x1b\xe5\x9c\xc1\x1d\xd9\x00\x03\xae\x32\x5e\x89\xa0\xb5\x0d\x59\x06\x4b\xb9\x29\xb5\xfc\x75\x8f\xed\x80\x4d\x34\xaa\x90\xa9\x0d\xd8\xe1\x91\x9a\xc9\x6a\x54\xb0\x41\xe5\xe9\x35\xa0\x16\x50\xe3\x0e\x2c\x05\x2b\xe0\x75\x0f\x2f\x2e\x71\x19\x7c\x32\x81\x47\x5d\x98\x15\x54\xcc\x8d\x5b\x9d\x9e\x96\x92\xbb\x9c\xc9\x4d\x5d\x7b\x2d\x79\x77\x1a\xe5\x2f\xd7\x9e\x8d\x75\xa7\x82\x36\xa4\x4e\x9d\x2c\x97\x68\xf3\x4a\x32\xe5\x81\xe8\x53\x6c\xe4\x32\xba\xae\x63\xde\x64\xb5\xf8\x97\x6d\xb3\xcc\x9d\x0c\x7c\xe5\x5d\x10\x8b\x63\x2b\x75\xd9\x9b\x88\xaa\x7d\x22\x02\x41\xb8\x21\xe8\xd8\x6e\x4d\xa7\x38\x10\x1d\x86\x02\x3b\xb7\xef\xee\xee\xa1\x33\x1d\x83\x31\x66\x3f\xf2\x7e\xd8\xe8\x0e\x21\x08\x84\x49\x5d\x90\x4d\x41\x2c\xac\xa9\x23\x26\x69\xd1\x18\xa9\x39\xbe\xe4\x4a\x92\x1e\xd3\xef\xfc\xba\x96\x1c\xe2\xfe\xdd\x93\xe3\x10\xab\x0c\x2e\x63\x21\x81\x35\x81\x6f\x04\x32\x89\x0c\xae\x35\x5c\x62\x4d\xea\x12\x1d\xfd\xe3\x01\x08\x4c\xbb\x65\x20\xf6\x65\x21\xe8\xd7\xc0\xf1\xe2\xc4\x5a\x6f\xa2\x2b\x4d\x33\xf1\x1a\x66\xeb\x5d\x43\xf9\x20\x71\xc6\x79\x1a\xf2\xf7\xe2\xf6\xf3\x00\x6f\x3a\x5f\xc3\xa3\x5d\xf9\x5e\x99\xed\x47\x53\x1e\x4d\x8d\xdc\xb8\xb9\xfb\xd0\xad\x8c\x55\x1c\xa5\x8e\x3f\x0a\x59\x7a\x1b\x73\x33\x9a\xbe\xb9\xfb\x00\x85\x32\x5b\x50\xa6\x74\xd9\x11\x24\xc0\xe7\x5a\xb6\xd1\x1f\xec\x95\x05\xec\x8c\x07\x61\xf4\x09\xc3\x16\xf5\x7e\x4d\x7b\x5d\x84\x94\x0d\x89\xa7\x73\xa9\x68\x02\xf6\x19\xbb\xf3\x0c\x84\x87\x34\xae\x15\x89\xa9\xa9\x71\xf2\xbc\x4b\x4b\x07\x21\x58\x53\x85\x1b\x69\xbc\x4d\x45\x8b\x0e\x8e\xda\x69\x48\x80\x6d\x45\x1a\xd8\x7a\x1a\x1f\x73\x2b\x95\x02\xb6\xbb\x74\x5e\xcc\xab\xb8\x40\x90\x93\x96\xc4\x90\xb3\xd7\x4f\x61\x17\xa8\x1c\x81\xe4\x01\xa0\x90\x2e\x78\x1f\x21\x0f\x64\x9d\x4c\xe2\x24\xb1\xae\x8d\x51\x84\xe3\xb2\x1b\x1e\x4d\xbc\x35\xf6\xf1\x2b\x72\x5e\x91\xbd\xbe\x7a\x01\x79\x37\xa3\x2d\x51\xf9\xb2\x90\x2d\x8d\xd7\x57\x1d\x7f\x2d\xf6\xdc\xf9\xd2\xfe\x29\x71\xcd\x26\x64\xf7\x58\xe2\x94\xd6\x57\xb8\x9b\x94\x42\x70\xb9\x40\xaf\x78\x05\xff\x3b\x7b\xfe\x48\xb7\x7d\xbc\xde\x79\x2a\xb3\x85\x1a\xf5\x0e\x44\x18\xef\xf8\x0e\x74\xcf\x1c\xaa\xbd\xb3\xd6\x41\x3c\x21\xb7\x48\x4c\x9f\xaf\x30\xb6\x46\x5e\x85\x5b\xea\xcd\xbf\x9f\x60\x20\xdc\x62\x65\x6c\x21\x8e\x2c\xb1\xb1\x58\xd2\x45\x9e\x1b\xaf\xb9\x6b\xe0\xae\x5f\xa2\xfe\xbb\xe9\xad\xfb\xb8\xb5\xd0\x80\x69\x01\x78\x47\x62\xe6\xbc\xa1\x56\xe4\x41\xf2\xf9\xfe\xbe\x39\x28\x12\x3e\x79\x17\xab\xbd\xd4\x09\x17\xeb\xc0\x4b\x19\x0a\x85\x29\xe6\x10\xdb\xed\x3f\xa4\x0b\xb6\x58\x14\x32\xbf\xd0\xa8\x76\x2c\x73\x77\x1d\x9a\x80\x0d\xaa\x67\x24\xf2\xf6\xac\x7e\x41\xcd\xe8\xc0\x00\x19\xb6\x95\x0c\x39\x6d\x42\x2a\x0b\x9f\x73\x72\x1b\x3b\xbb\x19\x3c\xc4\x96\x62\xae\x6e\xbc\x3d\xab\x5f\xc3\xf9\x59\x9d\xc1\x55\xcf\x87\x99\x14\x26\xed\xeb\x69\xa0\xe5\xac\xe7\xcb\x80\xfe\x77\x30\xf8\xd1\x94\xfb\xdf\x5f\x8d\x7d\x74\x0d\xbe\x50\x65\xb7\xf4\xdd\xc7\x6a\x17\x34\x72\x3f\x82\x9d\xd4\xc6\x0c\x59\x7b\xc5\xfc\x35\x6d\x6c\xa6\x9a\xda\x83\xe7\x6d\x18\xa6\x93\x71\x70\xb0\x71\xdf\xdb\x02\x07\x07\xfb\xd7\xd7\xb4\x93\x4f\x05\xf3\x7c\x66\xfc\x47\x0a\x84\x6d\xd9\x3f\xb6\xb5\xec\xee\xc9\xa3\x99\x99\xc6\x66\xbe\xe3\x61\x64\xef\x5e\xde\xf3\xc4\xe5\x83\x2b\xd7\xac\x5d\xe8\x34\x45\x84\xa2\xc0\xe0\xc4\x57\x5a\xf7\xcc\x5f\xfe\x21\x09\x65\xef\xf3\xb4\xff\x48\xa6\x7a\x32\x0f\x07\x9e\x7e\x6e\xc8\x22\x1b\x7b\xd9\x21\x85\xce\xfa\x5b\x90\x68\x2a\x88\xa8\x05\x5a\x71\x30\x04\x85\x24\x25\x26\x3b\xa3\xa7\x7b\x14\x00\x85\x8e\xef\x2d\x6a\x27\xbb\x2f\xe2\xb9\x2a\xd1\x5d\x12\xa1\x55\x5e\xb2\x9c\x4d\x90\x67\x84\x1f\xfa\x58\xe7\xb0\x9c\xb5\xf3\xec\x7e\x4b\xe8\xe6\x32\xe7\x05\xdb\xa7\x74\xf2\x27\xb6\xc7\x05\x3f\xb6\x79\x56\xd1\x87\x49\xb4\x16\x77\xe3\x2f\xa2\x56\x0d\x93\xdf\xc1\x4f\x9a\x9d\x34\x78\x34\x98\x44\xbf\x8a\x9d\x63\x1a\x48\x37\x6e\x7f\xc4\xaf\xf7\x9f\x8b\x9d\xfd\x96\x47\xf8\xed\xf7\xc5\x81\x52\xcc\x73\x6a\x98\xc4\xcd\xf8\xff\x8e\x57\xaf\x06\x7f\x61\xc4\xd7\x5e\xa2\xc0\x4f\x3f\x2f\x92\x61\x12\x0f\xdd\xdf\x13\x61\xf0\x8f\x00\x00\x00\xff\xff\xca\x65\xb2\xa4\x41\x12\x00\x00")
+
+func previewAroOpenshiftIo_previewfeaturesYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_previewAroOpenshiftIo_previewfeaturesYaml,
+		"preview.aro.openshift.io_previewfeatures.yaml",
+	)
+}
+
+func previewAroOpenshiftIo_previewfeaturesYaml() (*asset, error) {
+	bytes, err := previewAroOpenshiftIo_previewfeaturesYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "preview.aro.openshift.io_previewfeatures.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _workerDeploymentYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x52\xcb\x6e\xdb\x40\x0c\xbc\xeb\x2b\x88\xdc\x15\x27\xb7\x60\x6f\x41\x63\xe4\x52\x04\x45\xd3\xf4\x4e\xaf\xa6\xd6\xc2\xfb\x02\x49\xbb\x55\xbe\xbe\x10\x64\xcb\x32\x02\x88\x27\x61\x38\x9c\x19\x2e\xc5\x35\xfc\x86\x68\x28\xd9\x11\xd7\xaa\x9b\xd3\x63\x73\x08\xb9\x73\xf4\x82\x1a\xcb\x90\x90\xad\x49\x30\xee\xd8\xd8\x35\x44\x91\x77\x88\x3a\x7e\xd1\x38\xe0\x88\xa5\xb4\xa5\x42\xd8\x8a\xb4\x7f\x8b\x1c\x20\x0d\x51\xe6\x84\xb5\x9e\x56\xf6\x70\x54\x2a\xb2\xf6\xe1\x8f\xb5\xfc\x79\x14\xcc\xe4\x46\x2b\xfc\x68\x22\xa8\x31\x78\x56\x47\x8f\x0d\x91\x22\xc2\x5b\x91\xc9\x3e\xb1\xf9\xfe\xfb\x22\xcf\x6a\x22\x35\x61\xc3\x7e\x98\xa8\x52\x62\x0c\x79\xff\x51\x3b\x36\x5c\xa6\x13\xff\x7b\x3f\xca\x1e\x93\xd9\x19\xf9\xc8\x7c\xe2\x10\x79\x17\xe1\xe8\xa1\x21\x32\xa4\x1a\xe7\xa9\xe5\xdb\x8c\x15\x6f\xf2\xac\x26\x22\xba\x6c\x39\x96\x2f\xd9\x38\x64\xc8\x3c\xdc\x92\x2f\x29\x71\xee\xae\x6a\xed\x28\x75\xd5\x96\xbd\x2e\x7b\xf3\xeb\x5d\xa1\x85\xd9\x58\x21\xf1\xb8\xde\xeb\xf6\x6d\xfb\xf3\xf9\xd7\xf6\x65\x6e\x7c\xbd\xd7\xdc\x8a\xe1\x84\x0c\xd5\x1f\x52\x76\xb8\xda\x11\xf5\x66\xf5\x15\xb6\x84\x88\x2a\x5b\xef\x68\xd3\x83\xa3\xf5\x9f\x1b\x01\x77\xc3\x2d\xa1\x88\x39\x7a\x7a\x78\x7a\x38\xc3\xb9\x74\x78\xbf\x39\xec\x05\x6d\xa5\x44\xdc\x1f\x8e\x3b\x48\x86\x41\xef\x43\xd9\x4c\x0b\x39\xba\xbb\x3b\x53\x15\x72\x0a\x1e\xcf\xde\x97\x63\xb6\xb7\x95\xff\xee\x2b\x7b\x8d\x59\x25\x14\x09\x36\x7c\x8b\xac\x3a\xc9\xea\xa0\x86\xd4\xfa\x78\x54\x83\xb4\x5e\x82\x05\xcf\xb1\xf9\x1f\x00\x00\xff\xff\x4f\x57\x4a\x02\x45\x03\x00\x00")
+
+func workerDeploymentYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_workerDeploymentYaml,
+		"worker/deployment.yaml",
+	)
+}
+
+func workerDeploymentYaml() (*asset, error) {
+	bytes, err := workerDeploymentYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "worker/deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _workerRoleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x8e\xb1\x6e\x2c\x31\x08\x45\x7b\xbe\x82\x1f\xb0\x57\xaf\x7b\x72\x9b\x22\x7d\x14\xa5\x67\x3d\x24\x83\xc6\x63\x2c\xc0\xbb\x52\xbe\x3e\x9a\xd9\x6d\x53\xa5\xe2\x0a\x1d\x0e\x37\xa5\x04\x34\xe4\x83\xcd\x45\x7b\x41\xbb\x52\xcd\x34\x63\x55\x93\x6f\x0a\xd1\x9e\xb7\xff\x9e\x45\x2f\xb7\x7f\xb0\x49\x5f\x0a\xbe\xb4\xe9\xc1\xf6\xa6\x8d\x61\xe7\xa0\x85\x82\x0a\x20\x56\xe3\xf3\xe0\x5d\x76\xf6\xa0\x7d\x14\xec\xb3\x35\x40\xec\xb4\x73\x41\x32\x4d\x3a\xd8\x28\xd4\xd2\x5d\x6d\x63\x03\x9b\x8d\xbd\x40\x42\x1a\xf2\x6a\x3a\x87\x1f\xa6\x74\xb0\x59\x07\x77\x5f\xe5\x33\xb2\x28\x20\x1a\xbb\x4e\xab\xfc\x24\xea\xa3\x85\x03\xe2\x8d\xed\xfa\xdc\x7e\x71\x9c\xb3\x89\x3f\xc2\x9d\xa2\xae\x7f\xf1\x5f\x3c\x28\xe6\x2f\x6f\xc6\x69\x3f\xd2\x1c\x0b\x05\xc3\x4f\x00\x00\x00\xff\xff\x6c\x8c\x8d\xa2\x4f\x01\x00\x00")
+
+func workerRoleYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_workerRoleYaml,
+		"worker/role.yaml",
+	)
+}
+
+func workerRoleYaml() (*asset, error) {
+	bytes, err := workerRoleYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "worker/role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _workerRolebindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x8d\x31\x6e\xc3\x30\x0c\x45\x77\x9d\x82\x17\x90\x8b\x6e\x85\xb6\xb6\x43\x77\x17\xe8\x4e\xcb\x74\xcd\xda\x26\x05\x8a\x72\x01\x9f\x3e\x08\x12\x64\x09\xe0\xf9\xbf\xf7\x1f\x16\xfe\x21\xab\xac\x92\xc0\x06\xcc\x1d\x36\x9f\xd5\xf8\x40\x67\x95\x6e\x79\xab\x1d\xeb\xcb\xfe\x1a\x16\x96\x31\xc1\xe7\xda\xaa\x93\xf5\xba\xd2\x07\xcb\xc8\xf2\x1b\x36\x72\x1c\xd1\x31\x05\x00\xc1\x8d\x12\xa0\x69\xd4\x42\x86\xae\x16\xff\xd5\x16\xb2\x60\xba\x52\x4f\xd3\x15\xc2\xc2\x5f\xa6\xad\x9c\x04\x03\xc0\x53\xef\xf4\xbe\xb6\xe1\x8f\xb2\xd7\x14\xe2\xdd\xfc\x26\xdb\x39\xd3\x7b\xce\xda\xc4\x4f\xe5\xdb\x56\x0b\x66\x4a\xa0\x85\xa4\xce\x3c\x79\xc4\xa3\x19\x3d\xe0\x70\x09\x00\x00\xff\xff\x73\xce\x57\x9b\x2a\x01\x00\x00")
+
+func workerRolebindingYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_workerRolebindingYaml,
+		"worker/rolebinding.yaml",
+	)
+}
+
+func workerRolebindingYaml() (*asset, error) {
+	bytes, err := workerRolebindingYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "worker/rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+var _workerServiceaccountYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x31\x8a\xc3\x40\x0c\x05\xd0\x7e\x4e\xa1\x0b\x4c\xb1\xad\xba\x3d\x43\x20\xfd\x67\xfc\x43\x84\xb1\x34\x68\x64\x07\x72\xfa\x34\x21\xf5\x7b\x98\x76\x67\x2e\x0b\x57\xb9\xfe\xda\x6e\xbe\xa9\xdc\x98\x97\x0d\xfe\x8f\x11\xa7\x57\x3b\x58\xd8\x50\xd0\x26\xe2\x38\xa8\x82\x8c\x1e\x93\x89\x8a\xec\xaf\xc8\x9d\xf9\xb5\x35\x31\xa8\x12\x93\xbe\x9e\xf6\xa8\x8e\xf7\x99\xfc\xe5\xf6\x09\x00\x00\xff\xff\xe3\x3c\x43\x66\x70\x00\x00\x00")
+
+func workerServiceaccountYamlBytes() ([]byte, error) {
+	return bindataRead(
+		_workerServiceaccountYaml,
+		"worker/serviceaccount.yaml",
+	)
+}
+
+func workerServiceaccountYaml() (*asset, error) {
+	bytes, err := workerServiceaccountYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "worker/serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info}
+	return a, nil
+}
+
+// Asset loads and returns the asset for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func Asset(name string) ([]byte, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
+		}
+		return a.bytes, nil
+	}
+	return nil, fmt.Errorf("Asset %s not found", name)
+}
+
+// MustAsset is like Asset but panics when Asset would return an error.
+// It simplifies safe initialization of global variables.
+func MustAsset(name string) []byte {
+	a, err := Asset(name)
+	if err != nil {
+		panic("asset: Asset(" + name + "): " + err.Error())
+	}
+
+	return a
+}
+
+// AssetInfo loads and returns the asset info for the given name.
+// It returns an error if the asset could not be found or
+// could not be loaded.
+func AssetInfo(name string) (os.FileInfo, error) {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	if f, ok := _bindata[cannonicalName]; ok {
+		a, err := f()
+		if err != nil {
+			return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
+		}
+		return a.info, nil
+	}
+	return nil, fmt.Errorf("AssetInfo %s not found", name)
+}
+
+// AssetNames returns the names of the assets.
+func AssetNames() []string {
+	names := make([]string, 0, len(_bindata))
+	for name := range _bindata {
+		names = append(names, name)
+	}
+	return names
+}
+
+// _bindata is a table, holding each asset generator, mapped to its name.
+var _bindata = map[string]func() (*asset, error){
+	"aro.openshift.io_clusters.yaml":                aroOpenshiftIo_clustersYaml,
+	"master/deployment.yaml":                        masterDeploymentYaml,
+	"master/rolebinding.yaml":                       masterRolebindingYaml,
+	"master/service.yaml":                           masterServiceYaml,
+	"master/serviceaccount.yaml":                    masterServiceaccountYaml,
+	"namespace.yaml":                                namespaceYaml,
+	"preview.aro.openshift.io_previewfeatures.yaml": previewAroOpenshiftIo_previewfeaturesYaml,
+	"worker/deployment.yaml":                        workerDeploymentYaml,
+	"worker/role.yaml":                              workerRoleYaml,
+	"worker/rolebinding.yaml":                       workerRolebindingYaml,
+	"worker/serviceaccount.yaml":                    workerServiceaccountYaml,
+}
+
+// AssetDir returns the file names below a certain
+// directory embedded in the file by go-bindata.
+// For example if you run go-bindata on data/... and data contains the
+// following hierarchy:
+//     data/
+//       foo.txt
+//       img/
+//         a.png
+//         b.png
+// then AssetDir("data") would return []string{"foo.txt", "img"}
+// AssetDir("data/img") would return []string{"a.png", "b.png"}
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// AssetDir("") will return []string{"data"}.
+func AssetDir(name string) ([]string, error) {
+	node := _bintree
+	if len(name) != 0 {
+		cannonicalName := strings.Replace(name, "\\", "/", -1)
+		pathList := strings.Split(cannonicalName, "/")
+		for _, p := range pathList {
+			node = node.Children[p]
+			if node == nil {
+				return nil, fmt.Errorf("Asset %s not found", name)
+			}
+		}
+	}
+	if node.Func != nil {
+		return nil, fmt.Errorf("Asset %s not found", name)
+	}
+	rv := make([]string, 0, len(node.Children))
+	for childName := range node.Children {
+		rv = append(rv, childName)
+	}
+	return rv, nil
+}
+
+type bintree struct {
+	Func     func() (*asset, error)
+	Children map[string]*bintree
+}
+
+var _bintree = &bintree{nil, map[string]*bintree{
+	"aro.openshift.io_clusters.yaml": {aroOpenshiftIo_clustersYaml, map[string]*bintree{}},
+	"master": {nil, map[string]*bintree{
+		"deployment.yaml":     {masterDeploymentYaml, map[string]*bintree{}},
+		"rolebinding.yaml":    {masterRolebindingYaml, map[string]*bintree{}},
+		"service.yaml":        {masterServiceYaml, map[string]*bintree{}},
+		"serviceaccount.yaml": {masterServiceaccountYaml, map[string]*bintree{}},
+	}},
+	"namespace.yaml": {namespaceYaml, map[string]*bintree{}},
+	"preview.aro.openshift.io_previewfeatures.yaml": {previewAroOpenshiftIo_previewfeaturesYaml, map[string]*bintree{}},
+	"worker": {nil, map[string]*bintree{
+		"deployment.yaml":     {workerDeploymentYaml, map[string]*bintree{}},
+		"role.yaml":           {workerRoleYaml, map[string]*bintree{}},
+		"rolebinding.yaml":    {workerRolebindingYaml, map[string]*bintree{}},
+		"serviceaccount.yaml": {workerServiceaccountYaml, map[string]*bintree{}},
+	}},
+}}
+
+// RestoreAsset restores an asset under the given directory
+func RestoreAsset(dir, name string) error {
+	data, err := Asset(name)
+	if err != nil {
+		return err
+	}
+	info, err := AssetInfo(name)
+	if err != nil {
+		return err
+	}
+	err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
+	if err != nil {
+		return err
+	}
+	err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+	if err != nil {
+		return err
+	}
+	err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// RestoreAssets restores an asset under the given directory recursively
+func RestoreAssets(dir, name string) error {
+	children, err := AssetDir(name)
+	// File
+	if err != nil {
+		return RestoreAsset(dir, name)
+	}
+	// Dir
+	for _, child := range children {
+		err = RestoreAssets(dir, filepath.Join(name, child))
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func _filePath(dir, name string) string {
+	cannonicalName := strings.Replace(name, "\\", "/", -1)
+	return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+}
diff --git a/pkg/operator/deploy/deploy.go b/pkg/operator/deploy/deploy.go
index bafed828a..043bd2759 100644
--- a/pkg/operator/deploy/deploy.go
+++ b/pkg/operator/deploy/deploy.go
@@ -5,7 +5,6 @@ package deploy
 
 import (
 	"context"
-	"embed"
 	"errors"
 	"fmt"
 	"strings"
@@ -33,7 +32,6 @@ import (
 	aroclient "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned"
 	"github.com/Azure/ARO-RP/pkg/operator/controllers/genevalogging"
 	"github.com/Azure/ARO-RP/pkg/util/dynamichelper"
-	utilembed "github.com/Azure/ARO-RP/pkg/util/embed"
 	"github.com/Azure/ARO-RP/pkg/util/pullsecret"
 	"github.com/Azure/ARO-RP/pkg/util/ready"
 	"github.com/Azure/ARO-RP/pkg/util/restconfig"
@@ -42,9 +40,6 @@ import (
 	"github.com/Azure/ARO-RP/pkg/util/version"
 )
 
-//go:embed staticresources
-var embeddedFiles embed.FS
-
 type Operator interface {
 	CreateOrUpdate(context.Context) error
 	IsReady(context.Context) (bool, error)
@@ -85,8 +80,13 @@ func New(log *logrus.Entry, env env.Interface, oc *api.OpenShiftCluster, arocli
 
 func (o *operator) staticResources() ([]kruntime.Object, error) {
 	results := []kruntime.Object{}
-	for _, fileBytes := range utilembed.ReadDirRecursive(embeddedFiles, "staticresources") {
-		obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(fileBytes, nil, nil)
+	for _, assetName := range AssetNames() {
+		b, err := Asset(assetName)
+		if err != nil {
+			return nil, err
+		}
+
+		obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(b, nil, nil)
 		if err != nil {
 			return nil, err
 		}
diff --git a/pkg/operator/generate.go b/pkg/operator/generate.go
index f473b1194..c01c88bc8 100644
--- a/pkg/operator/generate.go
+++ b/pkg/operator/generate.go
@@ -15,3 +15,7 @@ package operator
 // for worker deployment - less privileges as it only runs the internetchecker
 // rbac (based on in-code tags - search for "+kubebuilder:rbac")
 //go:generate go run ../../vendor/sigs.k8s.io/controller-tools/cmd/controller-gen rbac:roleName=aro-operator-worker paths="controllers/internetchecker/..." output:dir=deploy/staticresources/worker
+
+// bindata for the above yaml files
+//go:generate go run ../../vendor/github.com/go-bindata/go-bindata/go-bindata -nometadata -pkg deploy -prefix deploy/staticresources/ -o deploy/bindata.go deploy/staticresources/...
+//go:generate gofmt -s -l -w deploy/bindata.go
diff --git a/pkg/util/mocks/deployer/deployer.go b/pkg/operator/mocks/muo/muo.go
similarity index 63%
rename from pkg/util/mocks/deployer/deployer.go
rename to pkg/operator/mocks/muo/muo.go
index b8a24828b..17d3f141a 100644
--- a/pkg/util/mocks/deployer/deployer.go
+++ b/pkg/operator/mocks/muo/muo.go
@@ -1,18 +1,18 @@
 // Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/Azure/ARO-RP/pkg/util/deployer (interfaces: Deployer)
+// Source: github.com/Azure/ARO-RP/pkg/operator/controllers/muo (interfaces: Deployer)
 
-// Package mock_deployer is a generated GoMock package.
-package mock_deployer
+// Package mock_muo is a generated GoMock package.
+package mock_muo
 
 import (
 	context "context"
-	fs "io/fs"
 	reflect "reflect"
 
 	gomock "github.com/golang/mock/gomock"
 	runtime "k8s.io/apimachinery/pkg/runtime"
 
 	v1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
+	config "github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
 )
 
 // MockDeployer is a mock of Deployer interface.
@@ -39,7 +39,7 @@ func (m *MockDeployer) EXPECT() *MockDeployerMockRecorder {
 }
 
 // CreateOrUpdate mocks base method.
-func (m *MockDeployer) CreateOrUpdate(arg0 context.Context, arg1 *v1alpha1.Cluster, arg2 interface{}) error {
+func (m *MockDeployer) CreateOrUpdate(arg0 context.Context, arg1 *v1alpha1.Cluster, arg2 *config.MUODeploymentConfig) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateOrUpdate", arg0, arg1, arg2)
 	ret0, _ := ret[0].(error)
@@ -53,45 +53,45 @@ func (mr *MockDeployerMockRecorder) CreateOrUpdate(arg0, arg1, arg2 interface{})
 }
 
 // IsReady mocks base method.
-func (m *MockDeployer) IsReady(arg0 context.Context, arg1, arg2 string) (bool, error) {
+func (m *MockDeployer) IsReady(arg0 context.Context) (bool, error) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsReady", arg0, arg1, arg2)
+	ret := m.ctrl.Call(m, "IsReady", arg0)
 	ret0, _ := ret[0].(bool)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
 
 // IsReady indicates an expected call of IsReady.
-func (mr *MockDeployerMockRecorder) IsReady(arg0, arg1, arg2 interface{}) *gomock.Call {
+func (mr *MockDeployerMockRecorder) IsReady(arg0 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsReady", reflect.TypeOf((*MockDeployer)(nil).IsReady), arg0, arg1, arg2)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsReady", reflect.TypeOf((*MockDeployer)(nil).IsReady), arg0)
 }
 
 // Remove mocks base method.
-func (m *MockDeployer) Remove(arg0 context.Context, arg1 interface{}) error {
+func (m *MockDeployer) Remove(arg0 context.Context) error {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Remove", arg0, arg1)
+	ret := m.ctrl.Call(m, "Remove", arg0)
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // Remove indicates an expected call of Remove.
-func (mr *MockDeployerMockRecorder) Remove(arg0, arg1 interface{}) *gomock.Call {
+func (mr *MockDeployerMockRecorder) Remove(arg0 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockDeployer)(nil).Remove), arg0, arg1)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockDeployer)(nil).Remove), arg0)
 }
 
-// Template mocks base method.
-func (m *MockDeployer) Template(arg0 interface{}, arg1 fs.FS) ([]runtime.Object, error) {
+// Resources mocks base method.
+func (m *MockDeployer) Resources(arg0 *config.MUODeploymentConfig) ([]runtime.Object, error) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Template", arg0, arg1)
+	ret := m.ctrl.Call(m, "Resources", arg0)
 	ret0, _ := ret[0].([]runtime.Object)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
 
-// Template indicates an expected call of Template.
-func (mr *MockDeployerMockRecorder) Template(arg0, arg1 interface{}) *gomock.Call {
+// Resources indicates an expected call of Resources.
+func (mr *MockDeployerMockRecorder) Resources(arg0 interface{}) *gomock.Call {
 	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Template", reflect.TypeOf((*MockDeployer)(nil).Template), arg0, arg1)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Resources", reflect.TypeOf((*MockDeployer)(nil).Resources), arg0)
 }
diff --git a/pkg/util/deployer/deployer.go b/pkg/util/deployer/deployer.go
deleted file mode 100644
index a0228ac39..000000000
--- a/pkg/util/deployer/deployer.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// deployer is used to template and deploy services in an ARO cluster.
-// Some example usage can be found in the muo package.
-package deployer
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"bytes"
-	"context"
-	"errors"
-	"io"
-	"io/fs"
-	"path/filepath"
-	"strings"
-	"text/template"
-
-	appsv1 "k8s.io/api/apps/v1"
-	kruntime "k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/kubernetes/scheme"
-
-	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
-	"github.com/Azure/ARO-RP/pkg/util/dynamichelper"
-	"github.com/Azure/ARO-RP/pkg/util/ready"
-)
-
-type Deployer interface {
-	CreateOrUpdate(context.Context, *arov1alpha1.Cluster, interface{}) error
-	Remove(context.Context, interface{}) error
-	IsReady(context.Context, string, string) (bool, error)
-	Template(interface{}, fs.FS) ([]kruntime.Object, error)
-}
-
-type deployer struct {
-	kubernetescli kubernetes.Interface
-	dh            dynamichelper.Interface
-	fs            fs.FS
-	directory     string
-}
-
-func NewDeployer(kubernetescli kubernetes.Interface, dh dynamichelper.Interface, fs fs.FS, directory string) Deployer {
-	return &deployer{
-		kubernetescli: kubernetescli,
-		dh:            dh,
-		fs:            fs,
-		directory:     directory,
-	}
-}
-
-func (depl *deployer) Template(data interface{}, fsys fs.FS) ([]kruntime.Object, error) {
-	results := make([]kruntime.Object, 0)
-	template, err := template.ParseFS(fsys, filepath.Join(depl.directory, "*"))
-	if err != nil {
-		return nil, err
-	}
-
-	buffer := new(bytes.Buffer)
-	for _, templ := range template.Templates() {
-		err := templ.Execute(buffer, data)
-		if err != nil {
-			return nil, err
-		}
-		bytes, err := io.ReadAll(buffer)
-		if err != nil {
-			return nil, err
-		}
-
-		obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(bytes, nil, nil)
-		if err != nil {
-			return nil, err
-		}
-		results = append(results, obj)
-		buffer.Reset()
-	}
-
-	return results, nil
-}
-
-func (depl *deployer) CreateOrUpdate(ctx context.Context, cluster *arov1alpha1.Cluster, config interface{}) error {
-	resources, err := depl.Template(config, depl.fs)
-	if err != nil {
-		return err
-	}
-
-	err = dynamichelper.SetControllerReferences(resources, cluster)
-	if err != nil {
-		return err
-	}
-
-	err = dynamichelper.Prepare(resources)
-	if err != nil {
-		return err
-	}
-
-	return depl.dh.Ensure(ctx, resources...)
-}
-
-func (depl *deployer) Remove(ctx context.Context, data interface{}) error {
-	resources, err := depl.Template(data, depl.fs)
-	if err != nil {
-		return err
-	}
-
-	var errs []error
-	for _, obj := range resources {
-		// delete any deployments we have
-		if deployment, ok := obj.(*appsv1.Deployment); ok {
-			err := depl.dh.EnsureDeleted(ctx, "Deployment", deployment.Namespace, deployment.Name)
-			// Don't error out because then we might delete some resources and not others
-			if err != nil {
-				errs = append(errs, err)
-			}
-		}
-	}
-
-	if len(errs) != 0 {
-		errContent := []string{"error removing deployment:"}
-		for _, err := range errs {
-			errContent = append(errContent, err.Error())
-		}
-		return errors.New(strings.Join(errContent, "\n"))
-	}
-
-	return nil
-}
-
-func (depl *deployer) IsReady(ctx context.Context, namespace, deploymentName string) (bool, error) {
-	return ready.CheckDeploymentIsReady(ctx, depl.kubernetescli.AppsV1().Deployments(namespace), deploymentName)()
-}
diff --git a/pkg/util/deployer/generate.go b/pkg/util/deployer/generate.go
deleted file mode 100644
index d83f7b25d..000000000
--- a/pkg/util/deployer/generate.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package deployer
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-//go:generate go run ../../../vendor/github.com/golang/mock/mockgen -destination=../mocks/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/util/$GOPACKAGE Deployer
-//go:generate go run ../../../vendor/golang.org/x/tools/cmd/goimports -local=github.com/Azure/ARO-RP -e -w ../mocks/$GOPACKAGE/$GOPACKAGE.go
diff --git a/pkg/util/deployer/staticresources/deployment.yaml b/pkg/util/deployer/staticresources/deployment.yaml
deleted file mode 100644
index dfdbcf574..000000000
--- a/pkg/util/deployer/staticresources/deployment.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: managed-upgrade-operator
-  namespace: openshift-managed-upgrade-operator
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      name: managed-upgrade-operator
-  template:
-    metadata:
-      labels:
-        name: managed-upgrade-operator
-    spec:
-      serviceAccountName: managed-upgrade-operator
-      containers:
-        - name: managed-upgrade-operator
-          image: "{{ .Pullspec }}"
-          command:
-          - managed-upgrade-operator
-          imagePullPolicy: Always
diff --git a/pkg/util/embed/embeddedfiles.go b/pkg/util/embed/embeddedfiles.go
deleted file mode 100644
index 48286024f..000000000
--- a/pkg/util/embed/embeddedfiles.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package embed
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"embed"
-	"path"
-)
-
-func ReadDirRecursive(fs embed.FS, dir string) [][]byte {
-	result := make([][]byte, 0)
-	entries, err := fs.ReadDir(dir)
-	if err != nil {
-		return nil
-	}
-	for _, v := range entries {
-		if v.IsDir() {
-			result = append(result, ReadDirRecursive(fs, path.Join(dir, v.Name()))...)
-		} else {
-			bytes, err := fs.ReadFile(path.Join(dir, v.Name()))
-			if err != nil {
-				result = append(result, nil)
-			}
-			result = append(result, bytes)
-		}
-	}
-
-	return result
-}
diff --git a/pkg/util/mocks/adminactions/adminactions.go b/pkg/util/mocks/adminactions/adminactions.go
index 506e7a24d..21501dc6a 100644
--- a/pkg/util/mocks/adminactions/adminactions.go
+++ b/pkg/util/mocks/adminactions/adminactions.go
@@ -81,21 +81,6 @@ func (mr *MockKubeActionsMockRecorder) KubeGet(arg0, arg1, arg2, arg3 interface{
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KubeGet", reflect.TypeOf((*MockKubeActions)(nil).KubeGet), arg0, arg1, arg2, arg3)
 }
 
-// KubeGetPodLogs mocks base method.
-func (m *MockKubeActions) KubeGetPodLogs(arg0 context.Context, arg1, arg2, arg3 string) ([]byte, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "KubeGetPodLogs", arg0, arg1, arg2, arg3)
-	ret0, _ := ret[0].([]byte)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// KubeGetPodLogs indicates an expected call of KubeGetPodLogs.
-func (mr *MockKubeActionsMockRecorder) KubeGetPodLogs(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KubeGetPodLogs", reflect.TypeOf((*MockKubeActions)(nil).KubeGetPodLogs), arg0, arg1, arg2, arg3)
-}
-
 // KubeList mocks base method.
 func (m *MockKubeActions) KubeList(arg0 context.Context, arg1, arg2 string) ([]byte, error) {
 	m.ctrl.T.Helper()
diff --git a/portal/v1/package-lock.json b/portal/v1/package-lock.json
index 9fa07634f..3c96e023d 100644
--- a/portal/v1/package-lock.json
+++ b/portal/v1/package-lock.json
@@ -2305,9 +2305,9 @@
             }
         },
         "node_modules/eventsource": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
-            "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
+            "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
             "dev": true,
             "dependencies": {
                 "original": "^1.0.0"
@@ -9527,9 +9527,9 @@
             "dev": true
         },
         "eventsource": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
-            "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
+            "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
             "dev": true,
             "requires": {
                 "original": "^1.0.0"
diff --git a/portal/v2/package-lock.json b/portal/v2/package-lock.json
index 0ff82589f..25f5a2c94 100644
--- a/portal/v2/package-lock.json
+++ b/portal/v2/package-lock.json
@@ -7823,9 +7823,9 @@
       }
     },
     "node_modules/eventsource": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
-      "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
+      "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
       "dependencies": {
         "original": "^1.0.0"
       },
@@ -26464,9 +26464,9 @@
       "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
     },
     "eventsource": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
-      "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
+      "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
       "requires": {
         "original": "^1.0.0"
       }
diff --git a/python/az/aro/azext_aro/_aad.py b/python/az/aro/azext_aro/_aad.py
index 44990f855..ceae1d072 100644
--- a/python/az/aro/azext_aro/_aad.py
+++ b/python/az/aro/azext_aro/_aad.py
@@ -1,41 +1,65 @@
 # Copyright (c) Microsoft Corporation.
 # Licensed under the Apache License 2.0.
 
+import datetime
 import time
+import uuid
 
-from azure.cli.command_modules.role import graph_client_factory
-from azure.cli.command_modules.role import GraphError
-
+from azure.cli.core._profile import Profile
+from azure.cli.core.commands.client_factory import configure_common_settings
+from azure.cli.core.azclierror import BadRequestError
+from azure.graphrbac import GraphRbacManagementClient
+from azure.graphrbac.models import ApplicationCreateParameters
+from azure.graphrbac.models import GraphErrorException
+from azure.graphrbac.models import PasswordCredential
+from azure.graphrbac.models import ServicePrincipalCreateParameters
 from knack.log import get_logger
 
 logger = get_logger(__name__)
 
 
-# All methods now return the text based values
-# for consistency and hiding implementation details
 class AADManager:
     def __init__(self, cli_ctx):
-        self.client = graph_client_factory(cli_ctx)
+        profile = Profile(cli_ctx=cli_ctx)
         self.cli_ctx = cli_ctx
+        credentials, _, tenant_id = profile.get_login_credentials(
+            resource=cli_ctx.cloud.endpoints.active_directory_graph_resource_id)
+        self.client = GraphRbacManagementClient(
+            credentials, tenant_id, base_url=cli_ctx.cloud.endpoints.active_directory_graph_resource_id)
+        configure_common_settings(cli_ctx, self.client)
 
     def create_application(self, display_name):
-        request_body = {"displayName": display_name}
-        app = self.client.application_create(request_body)
-        obj_id = app["id"]
-        app_id = app["appId"]
-        password = self.add_password(obj_id)
-        return app_id, password
-
-    def get_service_principal_id(self, app_id):
-        sps = self.client.service_principal_list(f"appId eq '{app_id}'")
+        password = uuid.uuid4()
+        start_date = datetime.datetime.utcnow()
+        end_date = datetime.datetime(2299, 12, 31, tzinfo=datetime.timezone.utc)
+
+        app = self.client.applications.create(ApplicationCreateParameters(
+            display_name=display_name,
+            identifier_uris=[],
+            password_credentials=[
+                PasswordCredential(
+                    custom_key_identifier=str(start_date).encode(),
+                    start_date=start_date,
+                    end_date=end_date,
+                    value=password,
+                ),
+            ],
+        ))
+
+        return app, password
+
+    def get_service_principal(self, app_id):
+        sps = list(self.client.service_principals.list(
+            filter=f"appId eq '{app_id}'"))
         if sps:
-            return sps[0]["id"]
+            return sps[0]
         return None
 
-    def get_application_object_id_by_client_id(self, client_id):
-        apps = self.client.application_list(f"appId eq '{client_id}'")
+    def get_application_by_client_id(self, client_id):
+        apps = list(self.client.applications.list(
+            filter=f"appId eq '{client_id}'"))
         if apps:
-            return apps[0]["id"]
+            return apps[0]
         return None
 
     def create_service_principal(self, app_id):
@@ -43,14 +67,44 @@ class AADManager:
         retries = 0
         while True:
             try:
-                return self.client.service_principal_create({"appId": app_id})["id"]
-            except GraphError as ex:
+                return self.client.service_principals.create(
+                    ServicePrincipalCreateParameters(app_id=app_id))
+            except GraphErrorException as ex:
                 if retries >= max_retries:
                     raise
                 retries += 1
                 logger.warning("%s; retry %d of %d", ex, retries, max_retries)
                 time.sleep(10)
 
-    def add_password(self, obj_id):
-        cred = self.client.application_add_password(obj_id, {})
-        return cred["secretText"]
+    def refresh_application_credentials(self, object_id):
+        password = uuid.uuid4()
+        key_id = uuid.uuid4()
+        start_date = datetime.datetime.utcnow()
+        end_date = datetime.datetime(2299, 12, 31, tzinfo=datetime.timezone.utc)
+
+        try:
+            credentials = list(self.client.applications.list_password_credentials(object_id))
+        except GraphErrorException as e:
+            logger.error(e.message)
+            raise
+
+        # keys created with older version of cli are not updatable
+        # https://github.com/Azure/azure-sdk-for-python/issues/18131
+        for c in credentials:
+            if c.custom_key_identifier is None:
+                raise BadRequestError("Cluster AAD application contains a client secret with an empty identifier.\n\
+Please either manually remove the existing client secret and run `az aro update --refresh-credentials`, \n\
+or manually create a new client secret and run `az aro update --client-secret <ClientSecret>`.")
+
+        # when appending credentials ALL fields must be present, otherwise
+        # azure gives ambiguous errors about not being able to update old keys
+        credentials.append(PasswordCredential(
+            custom_key_identifier=str(start_date).encode(),  # bytearray
+            key_id=str(key_id),
+            start_date=start_date,
+            end_date=end_date,
+            value=password))
+
+        self.client.applications.update_password_credentials(object_id, credentials)
+
+        return password
diff --git a/python/az/aro/azext_aro/custom.py b/python/az/aro/azext_aro/custom.py
index 81989026a..a0fbf11cd 100644
--- a/python/az/aro/azext_aro/custom.py
+++ b/python/az/aro/azext_aro/custom.py
@@ -5,25 +5,23 @@ import random
 import os
 from base64 import b64decode
 
-import azext_aro.vendored_sdks.azure.mgmt.redhatopenshift.v2022_04_01.models as openshiftcluster
-
-from azure.cli.command_modules.role import GraphError
 from azure.cli.core.commands.client_factory import get_mgmt_service_client
 from azure.cli.core.commands.client_factory import get_subscription_id
 from azure.cli.core.profiles import ResourceType
 from azure.cli.core.util import sdk_no_wait
 from azure.cli.core.azclierror import FileOperationError, ResourceNotFoundError, UnauthorizedError
-from azext_aro._aad import AADManager
-from azext_aro._rbac import assign_role_to_resource, \
-    has_role_assignment_on_resource
-from azext_aro._rbac import ROLE_NETWORK_CONTRIBUTOR, ROLE_READER
-from azext_aro._validators import validate_subnets
-
-from knack.log import get_logger
-
+from azure.graphrbac.models import GraphErrorException
 from msrestazure.azure_exceptions import CloudError
 from msrestazure.tools import resource_id, parse_resource_id
 from msrest.exceptions import HttpOperationError
+from knack.log import get_logger
+
+import azext_aro.vendored_sdks.azure.mgmt.redhatopenshift.v2022_04_01.models as openshiftcluster
+
+from azext_aro._aad import AADManager
+from azext_aro._rbac import assign_role_to_resource, has_role_assignment_on_resource
+from azext_aro._rbac import ROLE_NETWORK_CONTRIBUTOR, ROLE_READER
+from azext_aro._validators import validate_subnets
 
 logger = get_logger(__name__)
 
@@ -75,14 +73,15 @@ def aro_create(cmd,  # pylint: disable=too-many-locals
 
     aad = AADManager(cmd.cli_ctx)
     if client_id is None:
-        client_id, client_secret = aad.create_application(cluster_resource_group or 'aro-' + random_id)
+        app, client_secret = aad.create_application(cluster_resource_group or 'aro-' + random_id)
+        client_id = app.app_id
 
-    client_sp_id = aad.get_service_principal_id(client_id)
-    if not client_sp_id:
-        client_sp_id = aad.create_service_principal(client_id)
+    client_sp = aad.get_service_principal(client_id)
+    if not client_sp:
+        client_sp = aad.create_service_principal(client_id)
 
-    rp_client_sp_id = aad.get_service_principal_id(resolve_rp_client_id())
-    if not rp_client_sp_id:
+    rp_client_sp = aad.get_service_principal(resolve_rp_client_id())
+    if not rp_client_sp:
         raise ResourceNotFoundError("RP service principal not found.")
 
     if rp_mode_development():
@@ -143,7 +142,7 @@ def aro_create(cmd,  # pylint: disable=too-many-locals
         ],
     )
 
-    sp_obj_ids = [client_sp_id, rp_client_sp_id]
+    sp_obj_ids = [client_sp.object_id, rp_client_sp.object_id]
     ensure_resource_permissions(cmd.cli_ctx, oc, True, sp_obj_ids)
 
     return sdk_no_wait(no_wait, client.begin_create_or_update,
@@ -154,7 +153,7 @@ def aro_create(cmd,  # pylint: disable=too-many-locals
 
 def aro_delete(cmd, client, resource_group_name, resource_name, no_wait=False):
     # TODO: clean up rbac
-    rp_client_sp_id = None
+    rp_client_sp = None
 
     try:
         oc = client.get(resource_group_name, resource_name)
@@ -169,16 +168,16 @@ def aro_delete(cmd, client, resource_group_name, resource_name, no_wait=False):
 
     # Best effort - assume the role assignments on the SP exist if exception raised
     try:
-        rp_client_sp_id = aad.get_service_principal_id(resolve_rp_client_id())
-        if not rp_client_sp_id:
+        rp_client_sp = aad.get_service_principal(resolve_rp_client_id())
+        if not rp_client_sp:
             raise ResourceNotFoundError("RP service principal not found.")
-    except GraphError as e:
+    except GraphErrorException as e:
         logger.info(e.message)
 
     # Customers frequently remove the Cluster or RP's service principal permissions.
     # Attempt to fix this before performing any action against the cluster
-    if rp_client_sp_id:
-        ensure_resource_permissions(cmd.cli_ctx, oc, False, [rp_client_sp_id])
+    if rp_client_sp:
+        ensure_resource_permissions(cmd.cli_ctx, oc, False, [rp_client_sp.object_id])
 
     return sdk_no_wait(no_wait, client.begin_delete,
                        resource_group_name=resource_group_name,
@@ -340,8 +339,8 @@ def cluster_application_update(cli_ctx,
                                refresh_cluster_credentials):
     # QUESTION: is there possible unification with the create path?
 
-    rp_client_sp_id = None
-    client_sp_id = None
+    rp_client_sp = None
+    client_sp = None
     random_id = generate_random_id()
 
     # if any of these are set - we expect users to have access to fix rbac so we fail
@@ -352,10 +351,10 @@ def cluster_application_update(cli_ctx,
 
     # check if we can see if RP service principal exists
     try:
-        rp_client_sp_id = aad.get_service_principal_id(resolve_rp_client_id())
-        if not rp_client_sp_id:
+        rp_client_sp = aad.get_service_principal(resolve_rp_client_id())
+        if not rp_client_sp:
             raise ResourceNotFoundError("RP service principal not found.")
-    except GraphError as e:
+    except GraphErrorException as e:
         if fail:
             logger.error(e.message)
             raise
@@ -366,32 +365,33 @@ def cluster_application_update(cli_ctx,
     # If application does not exist - creates new one
     if refresh_cluster_credentials:
         try:
-            app = aad.get_application_object_id_by_client_id(client_id or oc.service_principal_profile.client_id)
+            app = aad.get_application_by_client_id(client_id or oc.service_principal_profile.client_id)
             if not app:
                 # we were not able to find and applications, create new one
                 parts = parse_resource_id(oc.cluster_profile.resource_group_id)
                 cluster_resource_group = parts['resource_group']
 
-                client_id, client_secret = aad.create_application(cluster_resource_group or 'aro-' + random_id)
+                app, client_secret = aad.create_application(cluster_resource_group or 'aro-' + random_id)
+                client_id = app.app_id
             else:
-                client_secret = aad.add_password(app)
-        except GraphError as e:
+                client_secret = aad.refresh_application_credentials(app.object_id)
+        except GraphErrorException as e:
             logger.error(e.message)
             raise
 
     # attempt to get/create SP if one was not found.
     try:
-        client_sp_id = aad.get_service_principal_id(client_id or oc.service_principal_profile.client_id)
-    except GraphError as e:
+        client_sp = aad.get_service_principal(client_id or oc.service_principal_profile.client_id)
+    except GraphErrorException as e:
         if fail:
             logger.error(e.message)
             raise
         logger.info(e.message)
 
-    if fail and not client_sp_id:
-        client_sp_id = aad.create_service_principal(client_id or oc.service_principal_profile.client_id)
+    if fail and not client_sp:
+        client_sp = aad.create_service_principal(client_id or oc.service_principal_profile.client_id)
 
-    sp_obj_ids = [sp for sp in [rp_client_sp_id, client_sp_id] if sp]
+    sp_obj_ids = [sp.object_id for sp in [rp_client_sp, client_sp] if sp]
     ensure_resource_permissions(cli_ctx, oc, fail, sp_obj_ids)
 
     return client_id, client_secret


Test patch:
diff --git a/pkg/frontend/admin_openshiftcluster_kubernetespods_logs_test.go b/pkg/frontend/admin_openshiftcluster_kubernetespods_logs_test.go
deleted file mode 100644
index 5e10a8151..000000000
--- a/pkg/frontend/admin_openshiftcluster_kubernetespods_logs_test.go
+++ /dev/null
@@ -1,152 +0,0 @@
-package frontend
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"net/http"
-	"strings"
-	"testing"
-
-	"github.com/golang/mock/gomock"
-	"github.com/sirupsen/logrus"
-
-	"github.com/Azure/ARO-RP/pkg/api"
-	"github.com/Azure/ARO-RP/pkg/env"
-	"github.com/Azure/ARO-RP/pkg/frontend/adminactions"
-	"github.com/Azure/ARO-RP/pkg/metrics/noop"
-	mock_adminactions "github.com/Azure/ARO-RP/pkg/util/mocks/adminactions"
-)
-
-func TestAdminKubernetesGetPodLogs(t *testing.T) {
-	mockSubID := "00000000-0000-0000-0000-000000000000"
-	mockTenantID := "00000000-0000-0000-0000-000000000000"
-	method := http.MethodGet
-	ctx := context.Background()
-
-	type test struct {
-		name                    string
-		namespace               string
-		podName                 string
-		containerName           string
-		mocks                   func(*test, *mock_adminactions.MockKubeActions)
-		wantStatusCode          int
-		wantResponse            []byte
-		wantResponseContentType string
-		wantError               string
-	}
-
-	for _, tt := range []*test{
-		{
-			name:          "cluster exist in db",
-			namespace:     "openshift-image-registry",
-			podName:       "config",
-			containerName: "container-1",
-			mocks: func(tt *test, k *mock_adminactions.MockKubeActions) {
-				k.EXPECT().
-					KubeGetPodLogs(gomock.Any(), tt.namespace, tt.podName, tt.containerName).
-					Return([]byte(`fake logs`), nil)
-			},
-			wantStatusCode:          http.StatusOK,
-			wantResponseContentType: "text/plain",
-			wantResponse:            []byte(`fake logs` + "\n"),
-		},
-		{
-			name:          "AdminKubernetesGetPodLogs handles errors",
-			namespace:     "openshift-image-registry",
-			podName:       "config",
-			containerName: "container-1",
-			mocks: func(tt *test, k *mock_adminactions.MockKubeActions) {
-				k.EXPECT().
-					KubeGetPodLogs(gomock.Any(), tt.namespace, tt.podName, tt.containerName).
-					Return(nil, errors.New("i/o timeout"))
-			},
-			wantStatusCode:          http.StatusInternalServerError,
-			wantResponseContentType: "application/json",
-			wantError:               "500: InternalServerError: : Internal server error.",
-		},
-		{
-			name:                    "customer namespace, validation should fail",
-			namespace:               "customer-namespace",
-			podName:                 "config",
-			containerName:           "container-1",
-			wantStatusCode:          http.StatusForbidden,
-			wantResponseContentType: "application/json",
-			wantError:               "403: Forbidden: : Access to the provided namespace 'customer-namespace' is forbidden.",
-		},
-		{
-			name:                    "empty container name",
-			namespace:               "openshift-image-registry",
-			podName:                 "config",
-			containerName:           "",
-			wantStatusCode:          http.StatusBadRequest,
-			wantResponseContentType: "application/json",
-			wantError:               "400: InvalidParameter: : The provided container name '' is invalid.",
-		},
-	} {
-		t.Run(fmt.Sprintf("%s: %s", method, tt.name), func(t *testing.T) {
-			resourceID := fmt.Sprintf("/subscriptions/%s/resourcegroups/resourceGroup/providers/Microsoft.RedHatOpenShift/openShiftClusters/resourceName", mockSubID)
-			ti := newTestInfra(t).WithOpenShiftClusters().WithSubscriptions()
-			defer ti.done()
-			k := mock_adminactions.NewMockKubeActions(ti.controller)
-
-			if tt.mocks != nil {
-				tt.mocks(tt, k)
-			}
-
-			ti.fixture.AddOpenShiftClusterDocuments(&api.OpenShiftClusterDocument{
-				Key: strings.ToLower(resourceID),
-				OpenShiftCluster: &api.OpenShiftCluster{
-					ID:   resourceID,
-					Name: "resourceName",
-					Type: "Microsoft.RedHatOpenShift/openshiftClusters",
-					Properties: api.OpenShiftClusterProperties{
-						NetworkProfile: api.NetworkProfile{
-							APIServerPrivateEndpointIP: "0.0.0.0",
-						},
-					},
-				},
-			})
-			ti.fixture.AddSubscriptionDocuments(&api.SubscriptionDocument{
-				ID: mockSubID,
-				Subscription: &api.Subscription{
-					State: api.SubscriptionStateRegistered,
-					Properties: &api.SubscriptionProperties{
-						TenantID: mockTenantID,
-					},
-				},
-			})
-
-			err := ti.buildFixtures(nil)
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, api.APIs, &noop.Noop{}, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
-				return k, nil
-			}, nil, nil)
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			go f.Run(ctx, nil, nil)
-
-			resp, b, err := ti.request(method,
-				fmt.Sprintf("https://server/admin%s/kubernetespodlogs?container=%s&namespace=%s&podname=%s", resourceID, tt.containerName, tt.namespace, tt.podName),
-				nil, nil)
-			if err != nil {
-				t.Fatal(err)
-			}
-			err = validateResponse(resp, b, tt.wantStatusCode, tt.wantError, tt.wantResponse)
-			if err != nil {
-				t.Error(err)
-			}
-			if tt.wantResponseContentType != resp.Header.Get("Content-Type") {
-				t.Error(fmt.Errorf("unexpected \"Content-Type\" response header value \"%s\", wanted \"%s\"", resp.Header.Get("Content-Type"), tt.wantResponseContentType))
-			}
-		})
-	}
-}
diff --git a/pkg/frontend/validate_test.go b/pkg/frontend/validate_test.go
deleted file mode 100644
index 2e442a657..000000000
--- a/pkg/frontend/validate_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package frontend
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"strings"
-	"testing"
-)
-
-func TestValidateAdminKubernetesPodLogs(t *testing.T) {
-	longName := strings.Repeat("x", 256)
-
-	for _, tt := range []struct {
-		test          string
-		containerName string
-		namespace     string
-		name          string
-		wantErr       string
-	}{
-		{
-			test:          "valid openshift namespace",
-			namespace:     "openshift",
-			containerName: "container-01",
-			name:          "Valid-NAME-01",
-		},
-		{
-			test:          "customer namespace",
-			namespace:     "customer",
-			name:          "Valid-NAME-01",
-			containerName: "container-01",
-			wantErr:       "403: Forbidden: : Access to the provided namespace 'customer' is forbidden.",
-		},
-		{
-			test:          "invalid namespace",
-			namespace:     "openshift-/",
-			name:          "Valid-NAME-01",
-			containerName: "container-01",
-			wantErr:       "400: InvalidParameter: : The provided namespace 'openshift-/' is invalid.",
-		},
-		{
-			test:          "invalid name",
-			namespace:     "openshift-image-registry",
-			name:          longName,
-			containerName: "container-01",
-			wantErr:       "400: InvalidParameter: : The provided pod name '" + longName + "' is invalid.",
-		},
-		{
-			test:          "empty name",
-			namespace:     "openshift-image-registry",
-			containerName: "container-01",
-			wantErr:       "400: InvalidParameter: : The provided pod name '' is invalid.",
-		},
-		{
-			test:      "empty container name",
-			namespace: "openshift-image-registry",
-			name:      "pod-name",
-			wantErr:   "400: InvalidParameter: : The provided container name '' is invalid.",
-		},
-		{
-			test:          "empty namespace",
-			containerName: "container-01",
-			name:          "pod-name",
-			wantErr:       "400: InvalidParameter: : The provided namespace '' is invalid.",
-		},
-		{
-			test:          "valid container name",
-			containerName: "container-01",
-			name:          "Valid-NAME-01",
-			namespace:     "openshift-image-registry",
-		},
-		{
-			test:          "valid name",
-			containerName: "container-01",
-			namespace:     "openshift-image-registry",
-			name:          "Valid-NAME-01",
-		},
-		{
-			test:          "invalid container name",
-			containerName: "container_invalid",
-			namespace:     "openshift-image-registry",
-			name:          "Valid-pod-name-01",
-			wantErr:       "400: InvalidParameter: : The provided container name 'container_invalid' is invalid.",
-		},
-	} {
-		t.Run(tt.test, func(t *testing.T) {
-			err := validateAdminKubernetesPodLogs(tt.namespace, tt.name, tt.containerName)
-			if err != nil && err.Error() != tt.wantErr ||
-				err == nil && tt.wantErr != "" {
-				t.Error(err)
-			}
-		})
-	}
-}
diff --git a/pkg/operator/controllers/muo/deploy_test.go b/pkg/operator/controllers/muo/deploy_test.go
new file mode 100644
index 000000000..ef6916ca3
--- /dev/null
+++ b/pkg/operator/controllers/muo/deploy_test.go
@@ -0,0 +1,350 @@
+package muo
+
+// Copyright (c) Microsoft Corporation.
+// Licensed under the Apache License 2.0.
+
+import (
+	"context"
+	"errors"
+	"strings"
+	"testing"
+
+	"github.com/go-test/deep"
+	"github.com/golang/mock/gomock"
+	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/meta"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	kruntime "k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/kubernetes/fake"
+
+	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
+	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
+	mock_dynamichelper "github.com/Azure/ARO-RP/pkg/util/mocks/dynamichelper"
+)
+
+func TestDeployCreateOrUpdateCorrectKinds(t *testing.T) {
+	controller := gomock.NewController(t)
+	defer controller.Finish()
+
+	setPullSpec := "MyMUOPullSpec"
+	cluster := &arov1alpha1.Cluster{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: arov1alpha1.SingletonClusterName,
+		},
+	}
+
+	k8scli := fake.NewSimpleClientset()
+	dh := mock_dynamichelper.NewMockInterface(controller)
+
+	// When the DynamicHelper is called, count the number of objects it creates
+	// and capture any deployments so that we can check the pullspec
+	var deployments []*appsv1.Deployment
+	deployedObjects := make(map[string]int)
+	check := func(ctx context.Context, objs ...kruntime.Object) error {
+		m := meta.NewAccessor()
+		for _, i := range objs {
+			kind, err := m.Kind(i)
+			if err != nil {
+				return err
+			}
+			if d, ok := i.(*appsv1.Deployment); ok {
+				deployments = append(deployments, d)
+			}
+			deployedObjects[kind] = deployedObjects[kind] + 1
+		}
+		return nil
+	}
+	dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
+
+	deployer := newDeployer(k8scli, dh)
+	err := deployer.CreateOrUpdate(context.Background(), cluster, &config.MUODeploymentConfig{Pullspec: setPullSpec})
+	if err != nil {
+		t.Error(err)
+	}
+
+	// We expect these numbers of resources to be created
+	expectedKinds := map[string]int{
+		"ClusterRole":              1,
+		"ConfigMap":                2,
+		"ClusterRoleBinding":       1,
+		"CustomResourceDefinition": 1,
+		"Deployment":               1,
+		"Namespace":                1,
+		"Role":                     4,
+		"RoleBinding":              4,
+		"ServiceAccount":           1,
+	}
+	errs := deep.Equal(deployedObjects, expectedKinds)
+	for _, e := range errs {
+		t.Error(e)
+	}
+
+	// Ensure we have set the pullspec set on the containers
+	for _, d := range deployments {
+		for _, c := range d.Spec.Template.Spec.Containers {
+			if c.Image != setPullSpec {
+				t.Errorf("expected %s, got %s for pullspec", setPullSpec, c.Image)
+			}
+		}
+	}
+}
+
+func TestDeployCreateOrUpdateSetsOwnerReferences(t *testing.T) {
+	controller := gomock.NewController(t)
+	defer controller.Finish()
+
+	setPullSpec := "MyMUOPullSpec"
+	cluster := &arov1alpha1.Cluster{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: arov1alpha1.SingletonClusterName,
+		},
+	}
+
+	k8scli := fake.NewSimpleClientset()
+	dh := mock_dynamichelper.NewMockInterface(controller)
+
+	// the OwnerReference that we expect to be set on each object we Ensure
+	pointerToTrueForSomeReason := bool(true)
+	expectedOwner := metav1.OwnerReference{
+		APIVersion:         "aro.openshift.io/v1alpha1",
+		Kind:               "Cluster",
+		Name:               arov1alpha1.SingletonClusterName,
+		UID:                cluster.UID,
+		BlockOwnerDeletion: &pointerToTrueForSomeReason,
+		Controller:         &pointerToTrueForSomeReason,
+	}
+
+	// save the list of OwnerReferences on each of the Ensured objects
+	var ownerReferences [][]metav1.OwnerReference
+	check := func(ctx context.Context, objs ...kruntime.Object) error {
+		for _, i := range objs {
+			obj, err := meta.Accessor(i)
+			if err != nil {
+				return err
+			}
+			ownerReferences = append(ownerReferences, obj.GetOwnerReferences())
+		}
+		return nil
+	}
+	dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
+
+	deployer := newDeployer(k8scli, dh)
+	err := deployer.CreateOrUpdate(context.Background(), cluster, &config.MUODeploymentConfig{Pullspec: setPullSpec})
+	if err != nil {
+		t.Error(err)
+	}
+
+	// Check that each list of OwnerReferences contains our controller
+	for _, references := range ownerReferences {
+		errs := deep.Equal([]metav1.OwnerReference{expectedOwner}, references)
+		for _, e := range errs {
+			t.Error(e)
+		}
+	}
+}
+
+func TestDeployDelete(t *testing.T) {
+	controller := gomock.NewController(t)
+	defer controller.Finish()
+
+	k8scli := fake.NewSimpleClientset()
+	dh := mock_dynamichelper.NewMockInterface(controller)
+	dh.EXPECT().EnsureDeleted(gomock.Any(), "Deployment", "openshift-managed-upgrade-operator", "managed-upgrade-operator").Return(nil)
+
+	deployer := newDeployer(k8scli, dh)
+	err := deployer.Remove(context.Background())
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestDeployDeleteFailure(t *testing.T) {
+	controller := gomock.NewController(t)
+	defer controller.Finish()
+
+	k8scli := fake.NewSimpleClientset()
+	dh := mock_dynamichelper.NewMockInterface(controller)
+	dh.EXPECT().EnsureDeleted(gomock.Any(), "Deployment", "openshift-managed-upgrade-operator", "managed-upgrade-operator").Return(errors.New("fail"))
+
+	deployer := newDeployer(k8scli, dh)
+	err := deployer.Remove(context.Background())
+	if err == nil {
+		t.Error(err)
+	}
+	if err.Error() != "error removing MUO:\nfail" {
+		t.Error(err)
+	}
+}
+
+func TestDeployIsReady(t *testing.T) {
+	specReplicas := int32(1)
+	k8scli := fake.NewSimpleClientset(&appsv1.Deployment{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:       "managed-upgrade-operator",
+			Namespace:  "openshift-managed-upgrade-operator",
+			Generation: 1234,
+		},
+		Spec: appsv1.DeploymentSpec{
+			Replicas: &specReplicas,
+		},
+		Status: appsv1.DeploymentStatus{
+			ObservedGeneration:  1234,
+			Replicas:            1,
+			ReadyReplicas:       1,
+			UpdatedReplicas:     1,
+			AvailableReplicas:   1,
+			UnavailableReplicas: 0,
+		},
+	})
+
+	deployer := newDeployer(k8scli, nil)
+	ready, err := deployer.IsReady(context.Background())
+	if err != nil {
+		t.Error(err)
+	}
+	if !ready {
+		t.Error("deployment is not seen as ready")
+	}
+}
+
+func TestDeployIsReadyMissing(t *testing.T) {
+	k8scli := fake.NewSimpleClientset()
+	deployer := newDeployer(k8scli, nil)
+	ready, err := deployer.IsReady(context.Background())
+	if err != nil {
+		t.Error(err)
+	}
+	if ready {
+		t.Error("deployment is wrongly seen as ready")
+	}
+}
+
+func TestDeployConfig(t *testing.T) {
+	controller := gomock.NewController(t)
+	defer controller.Finish()
+
+	cluster := &arov1alpha1.Cluster{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: arov1alpha1.SingletonClusterName,
+		},
+	}
+
+	tests := []struct {
+		name             string
+		deploymentConfig *config.MUODeploymentConfig
+		expected         []string
+	}{
+		{
+			name:             "local",
+			deploymentConfig: &config.MUODeploymentConfig{EnableConnected: false},
+			expected: []string{
+				"configManager:",
+				"  localConfigName: managed-upgrade-config",
+				"  source: LOCAL",
+				"  watchInterval: 1",
+				"healthCheck:",
+				"  ignoredCriticals:",
+				"  - PrometheusRuleFailures",
+				"  - CannotRetrieveUpdates",
+				"  - FluentdNodeDown",
+				"  ignoredNamespaces:",
+				"  - openshift-logging",
+				"  - openshift-redhat-marketplace",
+				"  - openshift-operators",
+				"  - openshift-user-workload-monitoring",
+				"  - openshift-pipelines",
+				"  - openshift-azure-logging",
+				"maintenance:",
+				"  controlPlaneTime: 90",
+				"  ignoredAlerts:",
+				"    controlPlaneCriticals:",
+				"    - ClusterOperatorDown",
+				"    - ClusterOperatorDegraded",
+				"nodeDrain:",
+				"  expectedNodeDrainTime: 8",
+				"  timeOut: 45",
+				"scale:",
+				"  timeOut: 30",
+				"upgradeWindow:",
+				"  delayTrigger: 30",
+				"  timeOut: 120",
+				"",
+			},
+		},
+		{
+			name:             "connected",
+			deploymentConfig: &config.MUODeploymentConfig{EnableConnected: true, OCMBaseURL: "https://example.com"},
+			expected: []string{
+				"configManager:",
+				"  ocmBaseUrl: https://example.com",
+				"  source: OCM",
+				"  watchInterval: 1",
+				"healthCheck:",
+				"  ignoredCriticals:",
+				"  - PrometheusRuleFailures",
+				"  - CannotRetrieveUpdates",
+				"  - FluentdNodeDown",
+				"  ignoredNamespaces:",
+				"  - openshift-logging",
+				"  - openshift-redhat-marketplace",
+				"  - openshift-operators",
+				"  - openshift-user-workload-monitoring",
+				"  - openshift-pipelines",
+				"  - openshift-azure-logging",
+				"maintenance:",
+				"  controlPlaneTime: 90",
+				"  ignoredAlerts:",
+				"    controlPlaneCriticals:",
+				"    - ClusterOperatorDown",
+				"    - ClusterOperatorDegraded",
+				"nodeDrain:",
+				"  expectedNodeDrainTime: 8",
+				"  timeOut: 45",
+				"scale:",
+				"  timeOut: 30",
+				"upgradeWindow:",
+				"  delayTrigger: 30",
+				"  timeOut: 120",
+				"",
+			},
+		},
+	}
+	for _, tt := range tests {
+		k8scli := fake.NewSimpleClientset()
+		dh := mock_dynamichelper.NewMockInterface(controller)
+
+		// When the DynamicHelper is called, capture configmaps to inspect them
+		var configs []*corev1.ConfigMap
+		check := func(ctx context.Context, objs ...kruntime.Object) error {
+			for _, i := range objs {
+				if cm, ok := i.(*corev1.ConfigMap); ok {
+					configs = append(configs, cm)
+				}
+			}
+			return nil
+		}
+		dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
+
+		deployer := newDeployer(k8scli, dh)
+		err := deployer.CreateOrUpdate(context.Background(), cluster, tt.deploymentConfig)
+		if err != nil {
+			t.Error(err)
+		}
+
+		foundConfig := false
+		for _, cms := range configs {
+			if cms.Name == "managed-upgrade-operator-config" && cms.Namespace == "openshift-managed-upgrade-operator" {
+				foundConfig = true
+				errs := deep.Equal(tt.expected, strings.Split(cms.Data["config.yaml"], "\n"))
+				for _, e := range errs {
+					t.Error(e)
+				}
+			}
+		}
+
+		if !foundConfig {
+			t.Error("MUO config was not found")
+		}
+	}
+}
diff --git a/pkg/operator/controllers/muo/muo_controller_test.go b/pkg/operator/controllers/muo/muo_controller_test.go
index fd43ecb96..2d577cd65 100644
--- a/pkg/operator/controllers/muo/muo_controller_test.go
+++ b/pkg/operator/controllers/muo/muo_controller_test.go
@@ -18,13 +18,13 @@ import (
 	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
 	arofake "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned/fake"
 	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
-	mock_deployer "github.com/Azure/ARO-RP/pkg/util/mocks/deployer"
+	mock_muo "github.com/Azure/ARO-RP/pkg/operator/mocks/muo"
 )
 
 func TestMUOReconciler(t *testing.T) {
 	tests := []struct {
 		name  string
-		mocks func(*mock_deployer.MockDeployer, *arov1alpha1.Cluster)
+		mocks func(*mock_muo.MockDeployer, *arov1alpha1.Cluster)
 		flags arov1alpha1.OperatorFlags
 		// connected MUO -- cluster pullsecret
 		pullsecret string
@@ -46,13 +46,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerManaged:  "true",
 				controllerPullSpec: "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -61,13 +61,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerEnabled: "true",
 				controllerManaged: "true",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "acrtest.example.com/managed-upgrade-operator:aro-b4",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -78,13 +78,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerForceLocalOnly: "false",
 				controllerPullSpec:       "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -96,13 +96,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerPullSpec:       "wonderfulPullspec",
 			},
 			pullsecret: "{\"auths\": {}}",
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -114,13 +114,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerPullSpec:       "wonderfulPullspec",
 			},
 			pullsecret: "i'm a little json, short and stout",
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -132,14 +132,14 @@ func TestMUOReconciler(t *testing.T) {
 				controllerPullSpec:       "wonderfulPullspec",
 			},
 			pullsecret: "{\"auths\": {\"" + pullSecretOCMKey + "\": {\"auth\": \"secret value\"}}}",
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: true,
 					OCMBaseURL:      "https://api.openshift.com",
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -152,14 +152,14 @@ func TestMUOReconciler(t *testing.T) {
 				controllerPullSpec:       "wonderfulPullspec",
 			},
 			pullsecret: "{\"auths\": {\"" + pullSecretOCMKey + "\": {\"auth\": \"secret value\"}}}",
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: true,
 					OCMBaseURL:      "https://example.com",
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -171,13 +171,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerPullSpec:       "wonderfulPullspec",
 			},
 			pullsecret: "{\"auths\": {\"" + pullSecretOCMKey + "\": {\"auth\": \"secret value\"}}}",
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
 			},
 		},
 		{
@@ -187,13 +187,13 @@ func TestMUOReconciler(t *testing.T) {
 				controllerManaged:  "true",
 				controllerPullSpec: "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				expectedConfig := &config.MUODeploymentConfig{
 					Pullspec:        "wonderfulPullspec",
 					EnableConnected: false,
 				}
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
-				md.EXPECT().IsReady(gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(false, nil)
 			},
 			wantErr: "managed Upgrade Operator deployment timed out on Ready: timed out waiting for the condition",
 		},
@@ -204,7 +204,7 @@ func TestMUOReconciler(t *testing.T) {
 				controllerManaged:  "true",
 				controllerPullSpec: "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, gomock.AssignableToTypeOf(&config.MUODeploymentConfig{})).Return(errors.New("failed ensure"))
 			},
 			wantErr: "failed ensure",
@@ -216,8 +216,8 @@ func TestMUOReconciler(t *testing.T) {
 				controllerManaged:  "false",
 				controllerPullSpec: "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
-				md.EXPECT().Remove(gomock.Any(), gomock.Any()).Return(nil)
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
+				md.EXPECT().Remove(gomock.Any()).Return(nil)
 			},
 		},
 		{
@@ -227,8 +227,8 @@ func TestMUOReconciler(t *testing.T) {
 				controllerManaged:  "false",
 				controllerPullSpec: "wonderfulPullspec",
 			},
-			mocks: func(md *mock_deployer.MockDeployer, cluster *arov1alpha1.Cluster) {
-				md.EXPECT().Remove(gomock.Any(), gomock.Any()).Return(errors.New("failed delete"))
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
+				md.EXPECT().Remove(gomock.Any()).Return(errors.New("failed delete"))
 			},
 			wantErr: "failed delete",
 		},
@@ -257,7 +257,7 @@ func TestMUOReconciler(t *testing.T) {
 			}
 			arocli := arofake.NewSimpleClientset(cluster)
 			kubecli := fake.NewSimpleClientset()
-			deployer := mock_deployer.NewMockDeployer(controller)
+			deployer := mock_muo.NewMockDeployer(controller)
 
 			if tt.pullsecret != "" {
 				_, err := kubecli.CoreV1().Secrets(pullSecretName.Namespace).Create(context.Background(),
diff --git a/pkg/operator/controllers/muo/template_test.go b/pkg/operator/controllers/muo/template_test.go
deleted file mode 100644
index 68c232343..000000000
--- a/pkg/operator/controllers/muo/template_test.go
+++ /dev/null
@@ -1,170 +0,0 @@
-package muo
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"context"
-	_ "embed"
-	"testing"
-
-	"github.com/ghodss/yaml"
-	"github.com/go-test/deep"
-	"github.com/golang/mock/gomock"
-	appsv1 "k8s.io/api/apps/v1"
-	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/meta"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	kruntime "k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/kubernetes/fake"
-
-	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
-	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
-	"github.com/Azure/ARO-RP/pkg/util/deployer"
-	mock_dynamichelper "github.com/Azure/ARO-RP/pkg/util/mocks/dynamichelper"
-)
-
-//go:embed test_files/local.yaml
-var expectedLocalConfig []byte
-
-//go:embed test_files/connected.yaml
-var expectedConnectedConfig []byte
-
-func TestDeployCreateOrUpdateCorrectKinds(t *testing.T) {
-	controller := gomock.NewController(t)
-	defer controller.Finish()
-
-	setPullSpec := "MyMUOPullSpec"
-	cluster := &arov1alpha1.Cluster{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: arov1alpha1.SingletonClusterName,
-		},
-	}
-
-	k8scli := fake.NewSimpleClientset()
-	dh := mock_dynamichelper.NewMockInterface(controller)
-
-	// When the DynamicHelper is called, count the number of objects it creates
-	// and capture any deployments so that we can check the pullspec
-	var deployments []*appsv1.Deployment
-	deployedObjects := make(map[string]int)
-	check := func(ctx context.Context, objs ...kruntime.Object) error {
-		m := meta.NewAccessor()
-		for _, i := range objs {
-			kind, err := m.Kind(i)
-			if err != nil {
-				return err
-			}
-			if d, ok := i.(*appsv1.Deployment); ok {
-				deployments = append(deployments, d)
-			}
-			deployedObjects[kind] = deployedObjects[kind] + 1
-		}
-		return nil
-	}
-	dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
-
-	deployer := deployer.NewDeployer(k8scli, dh, staticFiles, "staticresources")
-	err := deployer.CreateOrUpdate(context.Background(), cluster, &config.MUODeploymentConfig{Pullspec: setPullSpec})
-	if err != nil {
-		t.Error(err)
-	}
-
-	// We expect these numbers of resources to be created
-	expectedKinds := map[string]int{
-		"ClusterRole":              1,
-		"ConfigMap":                2,
-		"ClusterRoleBinding":       1,
-		"CustomResourceDefinition": 1,
-		"Deployment":               1,
-		"Namespace":                1,
-		"Role":                     4,
-		"RoleBinding":              4,
-		"ServiceAccount":           1,
-	}
-	errs := deep.Equal(deployedObjects, expectedKinds)
-	for _, e := range errs {
-		t.Error(e)
-	}
-
-	// Ensure we have set the pullspec set on the containers
-	for _, d := range deployments {
-		for _, c := range d.Spec.Template.Spec.Containers {
-			if c.Image != setPullSpec {
-				t.Errorf("expected %s, got %s for pullspec", setPullSpec, c.Image)
-			}
-		}
-	}
-}
-
-func TestDeployConfig(t *testing.T) {
-	controller := gomock.NewController(t)
-	defer controller.Finish()
-
-	cluster := &arov1alpha1.Cluster{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: arov1alpha1.SingletonClusterName,
-		},
-	}
-
-	tests := []struct {
-		name             string
-		deploymentConfig *config.MUODeploymentConfig
-		expected         []byte
-	}{
-		{
-			name:             "local",
-			deploymentConfig: &config.MUODeploymentConfig{EnableConnected: false},
-			expected:         expectedLocalConfig,
-		},
-		{
-			name:             "connected",
-			deploymentConfig: &config.MUODeploymentConfig{EnableConnected: true, OCMBaseURL: "https://example.com"},
-			expected:         expectedConnectedConfig,
-		},
-	}
-	for _, tt := range tests {
-		k8scli := fake.NewSimpleClientset()
-		dh := mock_dynamichelper.NewMockInterface(controller)
-
-		// When the DynamicHelper is called, capture configmaps to inspect them
-		var configs []*corev1.ConfigMap
-		check := func(ctx context.Context, objs ...kruntime.Object) error {
-			for _, i := range objs {
-				if cm, ok := i.(*corev1.ConfigMap); ok {
-					configs = append(configs, cm)
-				}
-			}
-			return nil
-		}
-		dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
-
-		deployer := deployer.NewDeployer(k8scli, dh, staticFiles, "staticresources")
-		err := deployer.CreateOrUpdate(context.Background(), cluster, tt.deploymentConfig)
-		if err != nil {
-			t.Error(err)
-		}
-
-		foundConfig := false
-		for _, cms := range configs {
-			if cms.Name == "managed-upgrade-operator-config" && cms.Namespace == "openshift-managed-upgrade-operator" {
-				foundConfig = true
-
-				expectedMap := make(map[string]interface{})
-				yaml.Unmarshal(tt.expected, &expectedMap)
-
-				resultMap := make(map[string]interface{})
-				yaml.Unmarshal([]byte(cms.Data["config.yaml"]), &resultMap)
-
-				err := deep.Equal(expectedMap, resultMap)
-				if err != nil {
-					t.Error(err)
-				}
-			}
-		}
-
-		if !foundConfig {
-			t.Error("MUO config was not found")
-		}
-	}
-}
diff --git a/pkg/operator/controllers/muo/test_files/connected.yaml b/pkg/operator/controllers/muo/test_files/connected.yaml
deleted file mode 100644
index 971a4eee2..000000000
--- a/pkg/operator/controllers/muo/test_files/connected.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-configManager:
-  ocmBaseUrl: https://example.com
-  source: OCM
-  watchInterval: 1
-healthCheck:
-  ignoredCriticals:
-  - PrometheusRuleFailures
-  - CannotRetrieveUpdates
-  - FluentdNodeDown
-  ignoredNamespaces:
-  - openshift-logging
-  - openshift-redhat-marketplace
-  - openshift-operators
-  - openshift-user-workload-monitoring
-  - openshift-pipelines
-  - openshift-azure-logging
-maintenance:
-  controlPlaneTime: 90
-  ignoredAlerts:
-    controlPlaneCriticals:
-    - ClusterOperatorDown
-    - ClusterOperatorDegraded
-nodeDrain:
-  expectedNodeDrainTime: 8
-  timeOut: 45
-scale:
-  timeOut: 30
-upgradeWindow:
-  delayTrigger: 30
-  timeOut: 120
diff --git a/pkg/operator/controllers/muo/test_files/local.yaml b/pkg/operator/controllers/muo/test_files/local.yaml
deleted file mode 100644
index 60d956178..000000000
--- a/pkg/operator/controllers/muo/test_files/local.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-configManager:
-  localConfigName: managed-upgrade-config
-  source: LOCAL
-  watchInterval: 1
-healthCheck:
-  ignoredCriticals:
-  - PrometheusRuleFailures
-  - CannotRetrieveUpdates
-  - FluentdNodeDown
-  ignoredNamespaces:
-  - openshift-logging
-  - openshift-redhat-marketplace
-  - openshift-operators
-  - openshift-user-workload-monitoring
-  - openshift-pipelines
-  - openshift-azure-logging
-maintenance:
-  controlPlaneTime: 90
-  ignoredAlerts:
-    controlPlaneCriticals:
-    - ClusterOperatorDown
-    - ClusterOperatorDegraded
-nodeDrain:
-  expectedNodeDrainTime: 8
-  timeOut: 45
-scale:
-  timeOut: 30
-upgradeWindow:
-  delayTrigger: 30
-  timeOut: 120
diff --git a/pkg/util/deployer/deploy_test.go b/pkg/util/deployer/deploy_test.go
deleted file mode 100644
index 0b87be581..000000000
--- a/pkg/util/deployer/deploy_test.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package deployer
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-// files in staticresources are example files that are not used anywhere
-
-import (
-	"context"
-	"embed"
-	"errors"
-	"testing"
-
-	"github.com/go-test/deep"
-	"github.com/golang/mock/gomock"
-	appsv1 "k8s.io/api/apps/v1"
-	"k8s.io/apimachinery/pkg/api/meta"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	kruntime "k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/kubernetes/fake"
-
-	arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1"
-	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
-	mock_dynamichelper "github.com/Azure/ARO-RP/pkg/util/mocks/dynamichelper"
-)
-
-//go:embed staticresources
-var staticFiles embed.FS
-
-func TestDeployCreateOrUpdateSetsOwnerReferences(t *testing.T) {
-	controller := gomock.NewController(t)
-	defer controller.Finish()
-
-	setPullSpec := "MyMUOPullSpec"
-	cluster := &arov1alpha1.Cluster{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: arov1alpha1.SingletonClusterName,
-		},
-	}
-
-	k8scli := fake.NewSimpleClientset()
-	dh := mock_dynamichelper.NewMockInterface(controller)
-
-	// the OwnerReference that we expect to be set on each object we Ensure
-	trueValue := true
-	truePtr := &trueValue
-	expectedOwner := metav1.OwnerReference{
-		APIVersion:         "aro.openshift.io/v1alpha1",
-		Kind:               "Cluster",
-		Name:               arov1alpha1.SingletonClusterName,
-		UID:                cluster.UID,
-		BlockOwnerDeletion: truePtr,
-		Controller:         truePtr,
-	}
-
-	// save the list of OwnerReferences on each of the Ensured objects
-	var ownerReferences [][]metav1.OwnerReference
-	check := func(ctx context.Context, objs ...kruntime.Object) error {
-		for _, i := range objs {
-			obj, err := meta.Accessor(i)
-			if err != nil {
-				return err
-			}
-			ownerReferences = append(ownerReferences, obj.GetOwnerReferences())
-		}
-		return nil
-	}
-	dh.EXPECT().Ensure(gomock.Any(), gomock.Any()).Do(check).Return(nil)
-
-	deployer := NewDeployer(k8scli, dh, staticFiles, "staticresources")
-	err := deployer.CreateOrUpdate(context.Background(), cluster, &config.MUODeploymentConfig{Pullspec: setPullSpec})
-	if err != nil {
-		t.Error(err)
-	}
-
-	// Check that each list of OwnerReferences contains our controller
-	for _, references := range ownerReferences {
-		errs := deep.Equal([]metav1.OwnerReference{expectedOwner}, references)
-		for _, e := range errs {
-			t.Error(e)
-		}
-	}
-}
-
-func TestDeployDelete(t *testing.T) {
-	controller := gomock.NewController(t)
-	defer controller.Finish()
-
-	k8scli := fake.NewSimpleClientset()
-	dh := mock_dynamichelper.NewMockInterface(controller)
-	dh.EXPECT().EnsureDeleted(gomock.Any(), "Deployment", "openshift-managed-upgrade-operator", "managed-upgrade-operator").Return(nil)
-
-	deployer := NewDeployer(k8scli, dh, staticFiles, "staticresources")
-	err := deployer.Remove(context.Background(), config.MUODeploymentConfig{})
-	if err != nil {
-		t.Error(err)
-	}
-}
-
-func TestDeployDeleteFailure(t *testing.T) {
-	controller := gomock.NewController(t)
-	defer controller.Finish()
-
-	k8scli := fake.NewSimpleClientset()
-	dh := mock_dynamichelper.NewMockInterface(controller)
-	dh.EXPECT().EnsureDeleted(gomock.Any(), "Deployment", "openshift-managed-upgrade-operator", "managed-upgrade-operator").Return(errors.New("fail"))
-
-	deployer := NewDeployer(k8scli, dh, staticFiles, "staticresources")
-	err := deployer.Remove(context.Background(), config.MUODeploymentConfig{})
-	if err == nil {
-		t.Error(err)
-	}
-	if err.Error() != "error removing deployment:\nfail" {
-		t.Error(err)
-	}
-}
-
-func TestDeployIsReady(t *testing.T) {
-	specReplicas := int32(1)
-	k8scli := fake.NewSimpleClientset(&appsv1.Deployment{
-		ObjectMeta: metav1.ObjectMeta{
-			Name:       "managed-upgrade-operator",
-			Namespace:  "openshift-managed-upgrade-operator",
-			Generation: 1234,
-		},
-		Spec: appsv1.DeploymentSpec{
-			Replicas: &specReplicas,
-		},
-		Status: appsv1.DeploymentStatus{
-			ObservedGeneration:  1234,
-			Replicas:            1,
-			ReadyReplicas:       1,
-			UpdatedReplicas:     1,
-			AvailableReplicas:   1,
-			UnavailableReplicas: 0,
-		},
-	})
-
-	deployer := NewDeployer(k8scli, nil, staticFiles, "staticresources")
-	ready, err := deployer.IsReady(context.Background(), "openshift-managed-upgrade-operator", "managed-upgrade-operator")
-	if err != nil {
-		t.Error(err)
-	}
-	if !ready {
-		t.Error("deployment is not seen as ready")
-	}
-}
-
-func TestDeployIsReadyMissing(t *testing.T) {
-	k8scli := fake.NewSimpleClientset()
-	deployer := NewDeployer(k8scli, nil, staticFiles, "staticresources")
-	ready, err := deployer.IsReady(context.Background(), "openshift-managed-upgrade-operator", "managed-upgrade-operator")
-	if err != nil {
-		t.Error(err)
-	}
-	if ready {
-		t.Error("deployment is wrongly seen as ready")
-	}
-}
diff --git a/test/e2e/adminapi.go b/test/e2e/adminapi.go
index 782f01486..0c8b7d1c2 100644
--- a/test/e2e/adminapi.go
+++ b/test/e2e/adminapi.go
@@ -70,14 +70,6 @@ func adminRequest(ctx context.Context, method, path string, params url.Values, i
 
 	if out != nil && resp.Header.Get("Content-Type") == "application/json" {
 		return resp, json.NewDecoder(resp.Body).Decode(&out)
-	} else if out != nil && resp.Header.Get("Content-Type") == "text/plain" {
-		strOut := out.(*string)
-		p, err := ioutil.ReadAll(resp.Body)
-		if err == nil {
-			*strOut = string(p)
-		}
-
-		return resp, err
 	}
 
 	return resp, nil
diff --git a/test/e2e/adminapi_cluster_getlogs.go b/test/e2e/adminapi_cluster_getlogs.go
deleted file mode 100644
index 390432005..000000000
--- a/test/e2e/adminapi_cluster_getlogs.go
+++ /dev/null
@@ -1,120 +0,0 @@
-package e2e
-
-// Copyright (c) Microsoft Corporation.
-// Licensed under the Apache License 2.0.
-
-import (
-	"context"
-	"net/http"
-	"net/url"
-	"time"
-
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/wait"
-)
-
-var _ = Describe("[Admin API] Kubernetes get pod logs action", func() {
-	BeforeEach(skipIfNotInDevelopmentEnv)
-
-	const containerName = "e2e-test-container-name"
-	const podName = "e2e-test-pod-name"
-
-	When("in a standard openshift namespace", func() {
-		const namespace = "openshift-azure-operator"
-
-		It("should be able to get logs from a container of a pod", func() {
-			ctx := context.Background()
-			testGetPodLogsOK(ctx, containerName, podName, namespace)
-		})
-	})
-
-	When("in a customer namespace", func() {
-		const namespace = "e2e-test-namespace"
-
-		It("should be not be able to get logs from customer workload namespaces", func() {
-			ctx := context.Background()
-			testGetPodLogsFromCustomerNamespaceForbidden(ctx, containerName, podName, namespace)
-		})
-	})
-})
-
-// We will create a pod with known logs of its container and will compare the logs gotten through the kubernetes client and through the Admin API.
-func testGetPodLogsOK(ctx context.Context, containerName, podName, namespace string) {
-	By("creating a pod in openshift-azure-operator namespace with some known logs then comparing those logs with the logs of the container in the pod created")
-	pod := mockPod(containerName, podName, namespace)
-	pod, err := clients.Kubernetes.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
-	Expect(err).NotTo(HaveOccurred())
-	defer func() {
-		err = clients.Kubernetes.CoreV1().Pods(namespace).Delete(ctx, pod.Name, metav1.DeleteOptions{})
-		Expect(err).NotTo(HaveOccurred())
-	}()
-	err = wait.Poll(time.Second, time.Second*60, func() (done bool, err error) {
-		pod, err = clients.Kubernetes.CoreV1().Pods(namespace).Get(ctx, pod.Name, metav1.GetOptions{})
-		Expect(err).NotTo(HaveOccurred())
-		if pod.Status.Phase == corev1.PodSucceeded {
-			return true, nil
-		}
-
-		return false, nil
-	})
-	Expect(err).NotTo(HaveOccurred())
-
-	params := url.Values{
-		"container": []string{containerName},
-		"namespace": []string{namespace},
-		"podname":   []string{podName},
-	}
-
-	var logs string
-	resp, err := adminRequest(ctx, http.MethodGet, "/admin"+resourceIDFromEnv()+"/kubernetespodlogs", params, nil, &logs)
-	Expect(err).NotTo(HaveOccurred())
-	Expect(resp.StatusCode).To(Equal(http.StatusOK))
-
-	podOptions := corev1.PodLogOptions{
-		Container: pod.Spec.Containers[0].Name,
-	}
-	r := clients.Kubernetes.CoreV1().Pods(namespace).GetLogs(pod.Name, &podOptions)
-	result, err := r.Do(ctx).Raw()
-	Expect(err).NotTo(HaveOccurred())
-	result = append(result, "\n"...)
-	Expect(logs).To(Equal(string(result)))
-}
-
-func testGetPodLogsFromCustomerNamespaceForbidden(ctx context.Context, containerName, podName, namespace string) {
-	params := url.Values{
-		"container": []string{containerName},
-		"namespace": []string{namespace},
-		"podname":   []string{podName},
-	}
-	resp, err := adminRequest(ctx, http.MethodGet, "/admin"+resourceIDFromEnv()+"/kubernetespodlogs", params, nil, nil)
-	Expect(err).NotTo(HaveOccurred())
-	Expect(resp.StatusCode).To(Equal(http.StatusForbidden))
-}
-
-func mockPod(containerName, podName, namespace string) *corev1.Pod {
-	return &corev1.Pod{
-		TypeMeta: metav1.TypeMeta{
-			Kind:       "Pod",
-			APIVersion: "v1",
-		},
-		ObjectMeta: metav1.ObjectMeta{
-			Name:      podName,
-			Namespace: namespace,
-		},
-		Spec: corev1.PodSpec{
-			Containers: []corev1.Container{{
-				Name:    containerName,
-				Image:   "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:103505c93bf45c4a29301f282f1ff046e35b63bceaf4df1cca2e631039289da2",
-				Command: []string{"/bin/bash", "-c", "echo 'mock-pod-logs'"},
-			}},
-			RestartPolicy: "Never",
-			HostNetwork:   true,
-			HostPID:       true,
-		},
-		Status: corev1.PodStatus{},
-	}
-}