diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafana_types.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafana_types.go
index dc818237950cde99f2b40bdc059bd3e51d4fea7c..33551a4a011b8c09497dfca02549366b9786117a 100644
--- a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafana_types.go
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafana_types.go
@@ -3,6 +3,7 @@ package v1alpha1
 import (
 	v12 "github.com/openshift/api/route/v1"
 	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -17,18 +18,20 @@ var (
 // GrafanaSpec defines the desired state of Grafana
 // +k8s:openapi-gen=true
 type GrafanaSpec struct {
-	Config                 GrafanaConfig            `json:"config"`
-	Containers             []v1.Container           `json:"containers,omitempty"`
-	DashboardLabelSelector []*metav1.LabelSelector  `json:"dashboardLabelSelector,omitempty"`
-	Ingress                *GrafanaIngress          `json:"ingress,omitempty"`
-	Secrets                []string                 `json:"secrets,omitempty"`
-	ConfigMaps             []string                 `json:"configMaps,omitempty"`
-	Service                *GrafanaService          `json:"service,omitempty"`
-	Deployment             *GrafanaDeployment       `json:"deployment,omitempty"`
-	Resources              *v1.ResourceRequirements `json:"resources,omitempty"`
-	ServiceAccount         *GrafanaServiceAccount   `json:"serviceAccount,omitempty"`
-	Client                 *GrafanaClient           `json:"client,omitempty"`
-	Compat                 *GrafanaCompat           `json:"compat"`
+	Config                     GrafanaConfig            `json:"config"`
+	Containers                 []v1.Container           `json:"containers,omitempty"`
+	DashboardLabelSelector     []*metav1.LabelSelector  `json:"dashboardLabelSelector,omitempty"`
+	Ingress                    *GrafanaIngress          `json:"ingress,omitempty"`
+	Secrets                    []string                 `json:"secrets,omitempty"`
+	ConfigMaps                 []string                 `json:"configMaps,omitempty"`
+	Service                    *GrafanaService          `json:"service,omitempty"`
+	Deployment                 *GrafanaDeployment       `json:"deployment,omitempty"`
+	Resources                  *v1.ResourceRequirements `json:"resources,omitempty"`
+	ServiceAccount             *GrafanaServiceAccount   `json:"serviceAccount,omitempty"`
+	Client                     *GrafanaClient           `json:"client,omitempty"`
+	Compat                     *GrafanaCompat           `json:"compat"`
+	DashboardNamespaceSelector *metav1.LabelSelector    `json:"dashboardNamespaceSelector,omitempty"`
+	DataStorage                *GrafanaDataStorage      `json:"dataStorage,omitempty"`
 }
 
 // Backwards compatibility switches
@@ -51,6 +54,15 @@ type GrafanaService struct {
 	Ports       []v1.ServicePort  `json:"ports,omitempty"`
 }
 
+// GrafanaDataStorage provides a means to configure the grafana data storage
+type GrafanaDataStorage struct {
+	Annotations map[string]string               `json:"annotations,omitempty"`
+	Labels      map[string]string               `json:"labels,omitempty"`
+	AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes,omitempty"`
+	Size        resource.Quantity               `json:"size"`
+	Class       string                          `json:"class"`
+}
+
 type GrafanaServiceAccount struct {
 	Annotations map[string]string `json:"annotations,omitempty"`
 	Labels      map[string]string `json:"labels,omitempty"`
@@ -58,9 +70,15 @@ type GrafanaServiceAccount struct {
 
 // GrafanaDeployment provides a means to configure the deployment
 type GrafanaDeployment struct {
-	Annotations map[string]string `json:"annotations,omitempty"`
-	Labels      map[string]string `json:"labels,omitempty"`
-	Replicas    int32             `json:"replicas"`
+	Annotations                   map[string]string      `json:"annotations,omitempty"`
+	Labels                        map[string]string      `json:"labels,omitempty"`
+	Replicas                      int32                  `json:"replicas"`
+	NodeSelector                  map[string]string      `json:"nodeSelector,omitempty"`
+	Tolerations                   []v1.Toleration        `json:"tolerations,omitempty"`
+	Affinity                      *v1.Affinity           `json:"affinity,omitempty"`
+	SecurityContext               *v1.PodSecurityContext `json:"securityContext,omitempty"`
+	ContainerSecurityContext      *v1.SecurityContext    `json:"containerSecurityContext,omitempty"`
+	TerminationGracePeriodSeconds int64                  `json:"terminationGracePeriodSeconds"`
 }
 
 // GrafanaIngress provides a means to configure the ingress created
@@ -89,6 +107,7 @@ type GrafanaConfig struct {
 	AuthAnonymous                 *GrafanaConfigAuthAnonymous                 `json:"auth.anonymous,omitempty" ini:"auth.anonymous,omitempty"`
 	AuthGoogle                    *GrafanaConfigAuthGoogle                    `json:"auth.google,omitempty" ini:"auth.google,omitempty"`
 	AuthGithub                    *GrafanaConfigAuthGithub                    `json:"auth.github,omitempty" ini:"auth.github,omitempty"`
+	AuthGitlab                    *GrafanaConfigAuthGitlab                    `json:"auth.gitlab,omitempty" ini:"auth.gitlab,omitempty"`
 	AuthGenericOauth              *GrafanaConfigAuthGenericOauth              `json:"auth.generic_oauth,omitempty" ini:"auth.generic_oauth,omitempty"`
 	AuthLdap                      *GrafanaConfigAuthLdap                      `json:"auth.ldap,omitempty" ini:"auth.ldap,omitempty"`
 	AuthProxy                     *GrafanaConfigAuthProxy                     `json:"auth.proxy,omitempty" ini:"auth.proxy,omitempty"`
@@ -243,15 +262,17 @@ type GrafanaConfigAuthGitlab struct {
 }
 
 type GrafanaConfigAuthGenericOauth struct {
-	Enabled        *bool  `json:"enabled,omitempty" ini:"enabled"`
-	AllowSignUp    *bool  `json:"allow_sign_up,omitempty" ini:"allow_sign_up"`
-	ClientId       string `json:"client_id,omitempty" ini:"client_id,omitempty"`
-	ClientSecret   string `json:"client_secret,omitempty" ini:"client_secret,omitempty"`
-	Scopes         string `json:"scopes,omitempty" ini:"scopes,omitempty"`
-	AuthUrl        string `json:"auth_url,omitempty" ini:"auth_url,omitempty"`
-	TokenUrl       string `json:"token_url,omitempty" ini:"token_url,omitempty"`
-	ApiUrl         string `json:"api_url,omitempty" ini:"api_url,omitempty"`
-	AllowedDomains string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"`
+	Enabled            *bool  `json:"enabled,omitempty" ini:"enabled"`
+	AllowSignUp        *bool  `json:"allow_sign_up,omitempty" ini:"allow_sign_up"`
+	ClientId           string `json:"client_id,omitempty" ini:"client_id,omitempty"`
+	ClientSecret       string `json:"client_secret,omitempty" ini:"client_secret,omitempty"`
+	Scopes             string `json:"scopes,omitempty" ini:"scopes,omitempty"`
+	AuthUrl            string `json:"auth_url,omitempty" ini:"auth_url,omitempty"`
+	TokenUrl           string `json:"token_url,omitempty" ini:"token_url,omitempty"`
+	ApiUrl             string `json:"api_url,omitempty" ini:"api_url,omitempty"`
+	AllowedDomains     string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"`
+	RoleAttributePath  string `json:"role_attribute_path,omitempty" ini:"role_attribute_path,omitempty"`
+	EmailAttributePath string `json:"email_attribute_path,omitempty" ini:"email_attribute_path,omitempty"`
 }
 
 type GrafanaConfigAuthLdap struct {
diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadashboard_types.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadashboard_types.go
index a03775aae0f0289b3895b70d99cf0f59ed01497c..4a48f6936237d6528cb86b70cca198621f77d5a2 100644
--- a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadashboard_types.go
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadashboard_types.go
@@ -1,6 +1,7 @@
 package v1alpha1
 
 import (
+	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
@@ -13,11 +14,12 @@ const GrafanaDashboardKind = "GrafanaDashboard"
 type GrafanaDashboardSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 	// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
-	Json        string                       `json:"json"`
-	Name        string                       `json:"name"`
-	Plugins     PluginList                   `json:"plugins,omitempty"`
-	Url         string                       `json:"url,omitempty"`
-	Datasources []GrafanaDashboardDatasource `json:"datasources,omitempty"`
+	Json         string                       `json:"json"`
+	Name         string                       `json:"name"`
+	Plugins      PluginList                   `json:"plugins,omitempty"`
+	Url          string                       `json:"url,omitempty"`
+	ConfigMapRef *corev1.ConfigMapKeySelector `json:"configMapRef,omitempty"`
+	Datasources  []GrafanaDashboardDatasource `json:"datasources,omitempty"`
 }
 
 type GrafanaDashboardDatasource struct {
diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadatasource_types.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadatasource_types.go
index fdc88a87de82b504214e33e84219c5e61c981e90..93a344506451c63425444d27ced0759e7a3a8f91 100644
--- a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadatasource_types.go
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/grafanadatasource_types.go
@@ -95,6 +95,26 @@ type GrafanaDataSourceJsonData struct {
 	MaxOpenConns            int    `json:"maxOpenConns,omitempty"`
 	MaxIdleConns            int    `json:"maxIdleConns,omitempty"`
 	ConnMaxLifetime         int    `json:"connMaxLifetime,omitempty"`
+	//  Usefull fields for clickhouse datasource
+	//  See https://github.com/Vertamedia/clickhouse-grafana/tree/master/dist/README.md#configure-the-datasource-with-provisioning
+	//  See https://github.com/Vertamedia/clickhouse-grafana/tree/master/src/datasource.ts#L44
+	AddCorsHeader               bool   `json:"addCorsHeader,omitempty"`
+	DefaultDatabase             string `json:"defaultDatabase,omitempty"`
+	UsePOST                     bool   `json:"usePOST,omitempty"`
+	UseYandexCloudAuthorization bool   `json:"useYandexCloudAuthorization,omitempty"`
+	XHeaderUser                 string `json:"xHeaderUser,omitempty"`
+	XHeaderKey                  string `json:"xHeaderKey,omitempty"`
+	// Custom HTTP headers for datasources
+	// See https://grafana.com/docs/grafana/latest/administration/provisioning/#datasources
+	HTTPHeaderName1 string `json:"httpHeaderName1,omitempty"`
+	HTTPHeaderName2 string `json:"httpHeaderName2,omitempty"`
+	HTTPHeaderName3 string `json:"httpHeaderName3,omitempty"`
+	HTTPHeaderName4 string `json:"httpHeaderName4,omitempty"`
+	HTTPHeaderName5 string `json:"httpHeaderName5,omitempty"`
+	HTTPHeaderName6 string `json:"httpHeaderName6,omitempty"`
+	HTTPHeaderName7 string `json:"httpHeaderName7,omitempty"`
+	HTTPHeaderName8 string `json:"httpHeaderName8,omitempty"`
+	HTTPHeaderName9 string `json:"httpHeaderName9,omitempty"`
 }
 
 // The most common secure json options
@@ -107,6 +127,17 @@ type GrafanaDataSourceSecureJsonData struct {
 	BasicAuthPassword string `json:"basicAuthPassword,omitempty"`
 	AccessKey         string `json:"accessKey,omitempty"`
 	SecretKey         string `json:"secretKey,omitempty"`
+	// Custom HTTP headers for datasources
+	// See https://grafana.com/docs/grafana/latest/administration/provisioning/#datasources
+	HTTPHeaderValue1 string `json:"httpHeaderValue1,omitempty"`
+	HTTPHeaderValue2 string `json:"httpHeaderValue2,omitempty"`
+	HTTPHeaderValue3 string `json:"httpHeaderValue3,omitempty"`
+	HTTPHeaderValue4 string `json:"httpHeaderValue4,omitempty"`
+	HTTPHeaderValue5 string `json:"httpHeaderValue5,omitempty"`
+	HTTPHeaderValue6 string `json:"httpHeaderValue6,omitempty"`
+	HTTPHeaderValue7 string `json:"httpHeaderValue7,omitempty"`
+	HTTPHeaderValue8 string `json:"httpHeaderValue8,omitempty"`
+	HTTPHeaderValue9 string `json:"httpHeaderValue9,omitempty"`
 }
 
 func init() {
diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/helper.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/helper.go
new file mode 100644
index 0000000000000000000000000000000000000000..40a27709d860681b8875f5dcd8c43a1f8ff41930
--- /dev/null
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/helper.go
@@ -0,0 +1,5 @@
+package v1alpha1
+
+func (g *Grafana) UsedPersistentVolume() bool {
+	return g.Spec.DataStorage != nil
+}
diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.deepcopy.go
index 65923aca481652ec97f2059c33dd17292cc83214..e857f8268c50e8cd04c0d080030c69595c53f498 100644
--- a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.deepcopy.go
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.deepcopy.go
@@ -133,6 +133,11 @@ func (in *GrafanaConfig) DeepCopyInto(out *GrafanaConfig) {
 		*out = new(GrafanaConfigAuthGithub)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.AuthGitlab != nil {
+		in, out := &in.AuthGitlab, &out.AuthGitlab
+		*out = new(GrafanaConfigAuthGitlab)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.AuthGenericOauth != nil {
 		in, out := &in.AuthGenericOauth, &out.AuthGenericOauth
 		*out = new(GrafanaConfigAuthGenericOauth)
@@ -1158,6 +1163,11 @@ func (in *GrafanaDashboardSpec) DeepCopyInto(out *GrafanaDashboardSpec) {
 		*out = make(PluginList, len(*in))
 		copy(*out, *in)
 	}
+	if in.ConfigMapRef != nil {
+		in, out := &in.ConfigMapRef, &out.ConfigMapRef
+		*out = new(v1.ConfigMapKeySelector)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Datasources != nil {
 		in, out := &in.Datasources, &out.Datasources
 		*out = make([]GrafanaDashboardDatasource, len(*in))
@@ -1356,6 +1366,42 @@ func (in *GrafanaDataSourceStatus) DeepCopy() *GrafanaDataSourceStatus {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GrafanaDataStorage) DeepCopyInto(out *GrafanaDataStorage) {
+	*out = *in
+	if in.Annotations != nil {
+		in, out := &in.Annotations, &out.Annotations
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.AccessModes != nil {
+		in, out := &in.AccessModes, &out.AccessModes
+		*out = make([]v1.PersistentVolumeAccessMode, len(*in))
+		copy(*out, *in)
+	}
+	out.Size = in.Size.DeepCopy()
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataStorage.
+func (in *GrafanaDataStorage) DeepCopy() *GrafanaDataStorage {
+	if in == nil {
+		return nil
+	}
+	out := new(GrafanaDataStorage)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *GrafanaDeployment) DeepCopyInto(out *GrafanaDeployment) {
 	*out = *in
@@ -1373,6 +1419,35 @@ func (in *GrafanaDeployment) DeepCopyInto(out *GrafanaDeployment) {
 			(*out)[key] = val
 		}
 	}
+	if in.NodeSelector != nil {
+		in, out := &in.NodeSelector, &out.NodeSelector
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Tolerations != nil {
+		in, out := &in.Tolerations, &out.Tolerations
+		*out = make([]v1.Toleration, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Affinity != nil {
+		in, out := &in.Affinity, &out.Affinity
+		*out = new(v1.Affinity)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.SecurityContext != nil {
+		in, out := &in.SecurityContext, &out.SecurityContext
+		*out = new(v1.PodSecurityContext)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ContainerSecurityContext != nil {
+		in, out := &in.ContainerSecurityContext, &out.ContainerSecurityContext
+		*out = new(v1.SecurityContext)
+		(*in).DeepCopyInto(*out)
+	}
 	return
 }
 
@@ -1597,6 +1672,16 @@ func (in *GrafanaSpec) DeepCopyInto(out *GrafanaSpec) {
 		*out = new(GrafanaCompat)
 		**out = **in
 	}
+	if in.DashboardNamespaceSelector != nil {
+		in, out := &in.DashboardNamespaceSelector, &out.DashboardNamespaceSelector
+		*out = new(metav1.LabelSelector)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.DataStorage != nil {
+		in, out := &in.DataStorage, &out.DataStorage
+		*out = new(GrafanaDataStorage)
+		(*in).DeepCopyInto(*out)
+	}
 	return
 }
 
diff --git a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.openapi.go b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.openapi.go
index 283d1d5091dae4b663a87a7bc6c089681e1d24cf..6f73bc1e44733067ddf180b997207a10b1fcc750 100644
--- a/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.openapi.go
+++ b/vendor/github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1/zz_generated.openapi.go
@@ -30,14 +30,14 @@ func schema_pkg_apis_integreatly_v1alpha1_Grafana(ref common.ReferenceCallback)
 				Properties: map[string]spec.Schema{
 					"kind": {
 						SchemaProps: spec.SchemaProps{
-							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
+							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
 							Type:        []string{"string"},
 							Format:      "",
 						},
 					},
 					"apiVersion": {
 						SchemaProps: spec.SchemaProps{
-							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
+							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -74,14 +74,14 @@ func schema_pkg_apis_integreatly_v1alpha1_GrafanaDashboard(ref common.ReferenceC
 				Properties: map[string]spec.Schema{
 					"kind": {
 						SchemaProps: spec.SchemaProps{
-							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
+							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
 							Type:        []string{"string"},
 							Format:      "",
 						},
 					},
 					"apiVersion": {
 						SchemaProps: spec.SchemaProps{
-							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
+							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -118,14 +118,14 @@ func schema_pkg_apis_integreatly_v1alpha1_GrafanaDataSource(ref common.Reference
 				Properties: map[string]spec.Schema{
 					"kind": {
 						SchemaProps: spec.SchemaProps{
-							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
+							Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
 							Type:        []string{"string"},
 							Format:      "",
 						},
 					},
 					"apiVersion": {
 						SchemaProps: spec.SchemaProps{
-							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
+							Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -306,12 +306,22 @@ func schema_pkg_apis_integreatly_v1alpha1_GrafanaSpec(ref common.ReferenceCallba
 							Ref: ref("./pkg/apis/integreatly/v1alpha1.GrafanaClient"),
 						},
 					},
+					"compat": {
+						SchemaProps: spec.SchemaProps{
+							Ref: ref("./pkg/apis/integreatly/v1alpha1.GrafanaCompat"),
+						},
+					},
+					"dashboardNamespaceSelector": {
+						SchemaProps: spec.SchemaProps{
+							Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
+						},
+					},
 				},
-				Required: []string{"config"},
+				Required: []string{"config", "compat"},
 			},
 		},
 		Dependencies: []string{
-			"./pkg/apis/integreatly/v1alpha1.GrafanaClient", "./pkg/apis/integreatly/v1alpha1.GrafanaConfig", "./pkg/apis/integreatly/v1alpha1.GrafanaDeployment", "./pkg/apis/integreatly/v1alpha1.GrafanaIngress", "./pkg/apis/integreatly/v1alpha1.GrafanaService", "./pkg/apis/integreatly/v1alpha1.GrafanaServiceAccount", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
+			"./pkg/apis/integreatly/v1alpha1.GrafanaClient", "./pkg/apis/integreatly/v1alpha1.GrafanaCompat", "./pkg/apis/integreatly/v1alpha1.GrafanaConfig", "./pkg/apis/integreatly/v1alpha1.GrafanaDeployment", "./pkg/apis/integreatly/v1alpha1.GrafanaIngress", "./pkg/apis/integreatly/v1alpha1.GrafanaService", "./pkg/apis/integreatly/v1alpha1.GrafanaServiceAccount", "k8s.io/api/core/v1.Container", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
 	}
 }
 
@@ -378,20 +388,8 @@ func schema_pkg_apis_integreatly_v1alpha1_GrafanaStatus(ref common.ReferenceCall
 							},
 						},
 					},
-					"adminUser": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
-					"adminPassword": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
 				},
-				Required: []string{"phase", "message", "dashboards", "installedPlugins", "failedPlugins", "adminUser", "adminPassword"},
+				Required: []string{"phase", "message", "dashboards", "installedPlugins", "failedPlugins"},
 			},
 		},
 		Dependencies: []string{
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/cmd.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/cmd.go
index 1ac00b13d20cfa6ac611956eeed46d2c005b1651..794ea282eebf28aca1229a16d90101de41abfd0a 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/cmd.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/cmd.go
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+//nolint:lll
 package scaffold
 
 import (
@@ -43,6 +44,7 @@ import (
 	"fmt"
 	"os"
 	"runtime"
+	"strings"
 
 	// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
 	_ "k8s.io/client-go/plugin/pkg/client/auth"
@@ -61,6 +63,7 @@ import (
 	"github.com/spf13/pflag"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
+	"sigs.k8s.io/controller-runtime/pkg/cache"
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -126,11 +129,23 @@ func main() {
 		os.Exit(1)
 	}
 
-	// Create a new Cmd to provide shared dependencies and start components
-	mgr, err := manager.New(cfg, manager.Options{
+	// Set default manager options
+	options := manager.Options{
 		Namespace:          namespace,
 		MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
-	})
+	}
+
+	// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
+	// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate 
+	// Also note that you may face performance issues when using this with a high number of namespaces.
+	// More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
+	if strings.Contains(namespace, ",") {
+		options.Namespace = ""
+		options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
+	}
+
+	// Create a new manager to provide shared dependencies and start components
+	mgr, err := manager.New(cfg, options)
 	if err != nil {
 		log.Error(err, "")
 		os.Exit(1)
@@ -151,7 +166,7 @@ func main() {
 	}
 
 	// Add the Metrics Service
-	addMetrics(ctx, cfg, namespace)
+	addMetrics(ctx, cfg)
 
 	log.Info("Starting the Cmd.")
 
@@ -164,12 +179,17 @@ func main() {
 
 // addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
 // the Prometheus operator
-func addMetrics(ctx context.Context, cfg *rest.Config, namespace string) {
-	if err := serveCRMetrics(cfg); err != nil {
+func addMetrics(ctx context.Context, cfg *rest.Config) {
+	// Get the namespace the operator is currently deployed in.
+	operatorNs, err := k8sutil.GetOperatorNamespace()
+	if err != nil {
 		if errors.Is(err, k8sutil.ErrRunLocal) {
 			log.Info("Skipping CR metrics server creation; not running in a cluster.")
 			return
 		}
+	}
+
+	if err := serveCRMetrics(cfg, operatorNs); err != nil {
 		log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
 	}
 
@@ -188,7 +208,9 @@ func addMetrics(ctx context.Context, cfg *rest.Config, namespace string) {
 	// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
 	// necessary to configure Prometheus to scrape metrics from this operator.
 	services := []*v1.Service{service}
-	_, err = metrics.CreateServiceMonitors(cfg, namespace, services)
+
+	// The ServiceMonitor is created in the same namespace where the operator is deployed
+	_, err = metrics.CreateServiceMonitors(cfg, operatorNs, services)
 	if err != nil {
 		log.Info("Could not create ServiceMonitor object", "error", err.Error())
 		// If this operator is deployed to a cluster without the prometheus-operator running, it will return
@@ -201,24 +223,26 @@ func addMetrics(ctx context.Context, cfg *rest.Config, namespace string) {
 
 // serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
 // It serves those metrics on "http://metricsHost:operatorMetricsPort".
-func serveCRMetrics(cfg *rest.Config) error {
-	// Below function returns filtered operator/CustomResource specific GVKs.
-	// For more control override the below GVK list with your own custom logic.
+func serveCRMetrics(cfg *rest.Config, operatorNs string) error {
+	// The function below returns a list of filtered operator/CR specific GVKs. For more control, override the GVK list below
+	// with your own custom logic. Note that if you are adding third party API schemas, probably you will need to
+	// customize this implementation to avoid permissions issues.
 	filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
 	if err != nil {
-	    return err
+		return err
 	}
-	// Get the namespace the operator is currently deployed in.
-	operatorNs, err := k8sutil.GetOperatorNamespace()
+
+	// The metrics will be generated from the namespaces which are returned here.
+	// NOTE that passing nil or an empty list of namespaces in GenerateAndServeCRMetrics will result in an error.
+	ns, err := kubemetrics.GetNamespacesForMetrics(operatorNs)
 	if err != nil {
 		return err
 	}
-	// To generate metrics in other namespaces, add the values below.
-	ns := []string{operatorNs}
+
 	// Generate and serve custom resource specific metrics.
 	err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
 	if err != nil {
-	    return err
+		return err
 	}
 	return nil
 }
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/controller_kind.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/controller_kind.go
index a5b26c54b60a9e1281969069d857f2e69337bfc7..260c0d07d06e48b7f9dcee921ab7af911a63b848 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/controller_kind.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/controller_kind.go
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+//nolint:lll
 package scaffold
 
 import (
@@ -98,7 +99,8 @@ func getCustomAPIImportPathAndIdent(m string) (p string, id string, err error) {
 	}
 	if id == "" {
 		if len(sm) == 2 {
-			return "", "", fmt.Errorf(`custom import "%s" identifier is empty, remove "=" from passed string`, m)
+			return "", "",
+				fmt.Errorf(`custom import "%s" identifier is empty, remove "=" from passed string`, m)
 		}
 		sp := strings.Split(p, "/")
 		if len(sp) > 1 {
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/doc.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/doc.go
index a5abe08457f025a7b17a2ffcd1a8bf5f1fec68c7..da76ed604da2a0cf5eda0f4987efa6010a10d821 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/doc.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/doc.go
@@ -43,6 +43,7 @@ func (s *Doc) GetInput() (input.Input, error) {
 	return s.Input, nil
 }
 
+//nolint:lll
 const docTemplate = `// Package {{.Resource.Version}} contains API Schema definitions for the {{ .Resource.Group }} {{.Resource.Version}} API group
 // +k8s:deepcopy-gen=package,register
 // +groupName={{ .Resource.FullGroup }}
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/entrypoint.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/entrypoint.go
index c5ad6eab7d24e5b3b2a42fd901a8e4a400f2a197..6afb4905ebe6f610137160bf88557dfcbd1d76a2 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/entrypoint.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/entrypoint.go
@@ -36,16 +36,8 @@ func (e *Entrypoint) GetInput() (input.Input, error) {
 	return e.Input, nil
 }
 
+//nolint:lll //affects the template fi the line is trimmed
 const entrypointTmpl = `#!/bin/sh -e
 
-# This is documented here:
-# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines
-
-if ! whoami &>/dev/null; then
-  if [ -w /etc/passwd ]; then
-    echo "${USER_NAME:-{{.ProjectName}}}:x:$(id -u):$(id -g):${USER_NAME:-{{.ProjectName}}} user:${HOME}:/sbin/nologin" >> /etc/passwd
-  fi
-fi
-
 exec ${OPERATOR} $@
 `
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/go_mod.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/go_mod.go
index 841fe1dff9cfb2b77a853222a496ec94ba0106bf..72b231e52ef27a2f4a287f2920c70963519c8f2c 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/go_mod.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/go_mod.go
@@ -35,12 +35,13 @@ func (s *GoMod) GetInput() (input.Input, error) {
 	return s.Input, nil
 }
 
+//nolint:lll
 const goModTmpl = `module {{ .Repo }}
 
 go 1.13
 
 require (
-	github.com/operator-framework/operator-sdk v0.15.1
+	github.com/operator-framework/operator-sdk v0.16.0
 	sigs.k8s.io/controller-runtime v0.4.0
 )
 
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/register.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/register.go
index bd593004b388e42d27d1d486cd605db9473c8590..1065dc834a20623fb5eea58a347d528abcef7f40 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/register.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/register.go
@@ -44,6 +44,7 @@ func (s *Register) GetInput() (input.Input, error) {
 	return s.Input, nil
 }
 
+//nolint:lll
 const registerTemplate = `// NOTE: Boilerplate only.  Ignore this file.
 
 // Package {{.Resource.Version}} contains API Schema definitions for the {{ .Resource.Group }} {{.Resource.Version}} API group
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/role.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/role.go
index 7cf951d9a26d14780a8af1ada4075d2d6ab2a285..032a0c10b2ef5c15a5b42be92fbfbc88b45f4b8e 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/role.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/role.go
@@ -48,6 +48,7 @@ func (s *Role) GetInput() (input.Input, error) {
 	return s.Input, nil
 }
 
+//nolint:lll //references are not to be sliced
 func UpdateRoleForResource(r *Resource, absProjectPath string) error {
 	// append rbac rule to deploy/role.yaml
 	roleFilePath := filepath.Join(absProjectPath, DeployDir, RoleYamlFile)
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/scaffold.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/scaffold.go
index e745a1b7ff49504b8c7b364cdeb564309b982fa6..d9a486fe7c4592cb5e38104a807615b1960ea48e 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/scaffold.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/scaffold.go
@@ -98,7 +98,7 @@ func validateBoilerplateBytes(b []byte) error {
 	}
 	var tb []byte
 	tb, cb = bytes.TrimSpace(b), bytes.TrimSpace(cb)
-	if bytes.Compare(tb, cb) != 0 {
+	if !bytes.Equal(tb, cb) {
 		return fmt.Errorf(`boilerplate contains text other than comments:\n"%s"\n`, tb)
 	}
 	return nil
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/usersetup.go b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/usersetup.go
index 200015e2913fc68f11ace9ca7ef9a4e50be6b3ae..662be31ad1ff34f849a0e3a27384ba2d65a698e7 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/usersetup.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/scaffold/usersetup.go
@@ -40,13 +40,11 @@ const userSetupTmpl = `#!/bin/sh
 set -x
 
 # ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
+echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd
 mkdir -p ${HOME}
 chown ${USER_UID}:0 ${HOME}
 chmod ug+rwx ${HOME}
 
-# runtime user will need to be able to self-insert in /etc/passwd
-chmod g+rw /etc/passwd
-
 # no need for this script to remain in the image after running
 rm $0
 `
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/util/k8sutil/k8sutil.go b/vendor/github.com/operator-framework/operator-sdk/internal/util/k8sutil/k8sutil.go
index fce88ea2545b4f93da5fdc00ec8b9248e08c5b70..4fad74a28876d2f0865134531d38e77c62737425 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/util/k8sutil/k8sutil.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/util/k8sutil/k8sutil.go
@@ -87,7 +87,8 @@ func GetDisplayName(name string) string {
 		for j, r := range word {
 			if unicode.IsUpper(r) {
 				if j > 0 && !unicode.IsUpper(rune(word[j-1])) {
-					temp = temp[0:j+o] + " " + temp[j+o:len(temp)]
+					index := j + o
+					temp = temp[0:index] + " " + temp[index:]
 					o++
 				}
 			}
diff --git a/vendor/github.com/operator-framework/operator-sdk/internal/util/projutil/project_util.go b/vendor/github.com/operator-framework/operator-sdk/internal/util/projutil/project_util.go
index a7a490c5a2f682d0838d460eef3c3e9e10fc573b..3b47d0dbc949662180e862b39e0cae99c0afd0ba 100644
--- a/vendor/github.com/operator-framework/operator-sdk/internal/util/projutil/project_util.go
+++ b/vendor/github.com/operator-framework/operator-sdk/internal/util/projutil/project_util.go
@@ -82,7 +82,8 @@ func CheckProjectRoot() error {
 	// we are at the project root.
 	if _, err := os.Stat(buildDockerfile); err != nil {
 		if os.IsNotExist(err) {
-			return fmt.Errorf("must run command in project root dir: project structure requires %s", buildDockerfile)
+			return fmt.Errorf("must run command in project root dir: project structure requires %s",
+				buildDockerfile)
 		}
 		return fmt.Errorf("error while checking if current directory is the project root: %v", err)
 	}
@@ -150,7 +151,8 @@ func GetGoPkg() string {
 		goPath = MustSetWdGopath(goPath)
 	}
 	if !strings.HasPrefix(MustGetwd(), goPath) {
-		log.Fatal("Could not determine project repository path: $GOPATH not set, wd in default $HOME/go/src, or wd does not contain a go.mod")
+		log.Fatal("Could not determine project repository path: $GOPATH not set, wd in default $HOME/go/src," +
+			" or wd does not contain a go.mod")
 	}
 	return parseGoPkg(goPath)
 }
@@ -251,7 +253,8 @@ func CheckRepo(repo string) error {
 		return err
 	}
 	if !inGopathSrc && repo == "" {
-		return fmt.Errorf(`flag --repo must be set if the working directory is not in $GOPATH/src. See "operator-sdk new -h"`)
+		return fmt.Errorf(`flag --repo must be set if the working directory is not in $GOPATH/src.
+		See "operator-sdk new -h"`)
 	}
 	return nil
 }
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/k8sutil/k8sutil.go b/vendor/github.com/operator-framework/operator-sdk/pkg/k8sutil/k8sutil.go
index 563e485290f9975301ca65f357a621732a75c283..00a3debc3b443ecfe32598bdffd6ac58a857225a 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/k8sutil/k8sutil.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/k8sutil/k8sutil.go
@@ -91,7 +91,8 @@ func GetOperatorName() (string, error) {
 // ResourceExists returns true if the given resource kind exists
 // in the given api groupversion
 func ResourceExists(dc discovery.DiscoveryInterface, apiGroupVersion, kind string) (bool, error) {
-	apiLists, err := dc.ServerResources()
+
+	_, apiLists, err := dc.ServerGroupsAndResources()
 	if err != nil {
 		return false, err
 	}
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/metrics.go b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/metrics.go
index 4c8a750330686f7975f49e73e60a9991fbe7d55c..d4675b3dc2efb773bebf28a2ad3ef9bf6398ad1a 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/metrics.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/metrics.go
@@ -19,6 +19,8 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/operator-framework/operator-sdk/pkg/k8sutil"
+
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/rest"
@@ -39,7 +41,8 @@ func GenerateAndServeCRMetrics(cfg *rest.Config,
 	host string, port int32) error {
 	// We have to have at least one namespace.
 	if len(ns) < 1 {
-		return errors.New("namespaces were empty; pass at least one namespace to generate custom resource metrics")
+		return errors.New(
+			"namespaces were empty; pass at least one namespace to generate custom resource metrics")
 	}
 	// Create new unstructured client.
 	var allStores [][]*metricsstore.MetricsStore
@@ -91,3 +94,20 @@ func generateMetricFamilies(kind string) []ksmetric.FamilyGenerator {
 		},
 	}
 }
+
+// GetNamespacesForMetrics wil return all namespaces which will be used to export the metrics
+func GetNamespacesForMetrics(operatorNs string) ([]string, error) {
+	ns := []string{operatorNs}
+
+	// Get the value from WATCH_NAMESPACES
+	watchNamespace, err := k8sutil.GetWatchNamespace()
+	if err != nil {
+		return nil, err
+	}
+
+	// Generate metrics from the WATCH_NAMESPACES value if it contains multiple namespaces
+	if strings.Contains(watchNamespace, ",") {
+		ns = strings.Split(watchNamespace, ",")
+	}
+	return ns, nil
+}
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/store.go b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/store.go
index c0e270cc34adfcc09c6a97c6823f9ac2ebd13929..92555cf7454aced531c10db70ca28c13eb37456c 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/store.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/store.go
@@ -29,7 +29,8 @@ import (
 
 // NewMetricsStores returns collections of metrics in the namespaces provided, per the api/kind resource.
 // The metrics are registered in the custom metrics.FamilyGenerator that needs to be defined.
-func NewMetricsStores(dclient dynamic.NamespaceableResourceInterface, namespaces []string, api string, kind string, metricFamily []metric.FamilyGenerator) []*metricsstore.MetricsStore {
+func NewMetricsStores(dclient dynamic.NamespaceableResourceInterface, namespaces []string, api string, kind string,
+	metricFamily []metric.FamilyGenerator) []*metricsstore.MetricsStore {
 	namespaces = deduplicateNamespaces(namespaces)
 	var stores []*metricsstore.MetricsStore
 	// Generate collector per namespace.
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/uclient.go b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/uclient.go
index cef5e4a070b3a092ef965ddd2c4d5d50666ff5f2..3a260d986955ec5761860d58fcf5e897b9abe6e6 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/uclient.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/kube-metrics/uclient.go
@@ -57,7 +57,7 @@ func getAPIResource(cfg *rest.Config, apiVersion, kind string) (*metav1.APIResou
 		return nil, nil, err
 	}
 
-	apiResourceLists, err := kclient.Discovery().ServerResources()
+	_, apiResourceLists, err := kclient.Discovery().ServerGroupsAndResources()
 	if err != nil {
 		return nil, nil, err
 	}
@@ -72,7 +72,8 @@ func getAPIResource(cfg *rest.Config, apiVersion, kind string) (*metav1.APIResou
 		}
 	}
 
-	return nil, nil, fmt.Errorf("apiVersion %s and kind %s not found available in Kubernetes cluster", apiVersion, kind)
+	return nil, nil, fmt.Errorf("apiVersion %s and kind %s not found available in Kubernetes cluster",
+		apiVersion, kind)
 }
 
 func newForConfig(c *rest.Config, groupVersion string) (dynamic.Interface, error) {
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/flags.go b/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/flags.go
index f8449479ac0128d345f506c9915f557bd813c017..b44ac6b6a6ebe1bf5b0db08224da12cbbfb3e52e 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/flags.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/flags.go
@@ -34,15 +34,21 @@ var (
 	levelVal        levelValue
 	sampleVal       sampleValue
 	timeEncodingVal timeEncodingValue
+	stacktraceLevel stackLevelValue
 )
 
 func init() {
 	zapFlagSet = pflag.NewFlagSet("zap", pflag.ExitOnError)
-	zapFlagSet.BoolVar(&development, "zap-devel", false, "Enable zap development mode (changes defaults to console encoder, debug log level, and disables sampling)")
+	zapFlagSet.BoolVar(&development, "zap-devel", false, "Enable zap development mode"+
+		" (changes defaults to console encoder, debug log level, disables sampling and stacktrace from 'warning' level)")
 	zapFlagSet.Var(&encoderVal, "zap-encoder", "Zap log encoding ('json' or 'console')")
 	zapFlagSet.Var(&levelVal, "zap-level", "Zap log level (one of 'debug', 'info', 'error' or any integer value > 0)")
-	zapFlagSet.Var(&sampleVal, "zap-sample", "Enable zap log sampling. Sampling will be disabled for integer log levels > 1")
-	zapFlagSet.Var(&timeEncodingVal, "zap-time-encoding", "Sets the zap time format ('epoch', 'millis', 'nano', or 'iso8601')")
+	zapFlagSet.Var(&sampleVal, "zap-sample",
+		"Enable zap log sampling. Sampling will be disabled for integer log levels > 1")
+	zapFlagSet.Var(&timeEncodingVal, "zap-time-encoding",
+		"Sets the zap time format ('epoch', 'millis', 'nano', or 'iso8601')")
+	zapFlagSet.Var(&stacktraceLevel, "zap-stacktrace-level",
+		"Set the minimum log level that triggers stacktrace generation")
 }
 
 // FlagSet - The zap logging flagset.
@@ -103,27 +109,11 @@ type levelValue struct {
 
 func (v *levelValue) Set(l string) error {
 	v.set = true
-	lower := strings.ToLower(l)
-	var lvl int
-	switch lower {
-	case "debug":
-		lvl = -1
-	case "info":
-		lvl = 0
-	case "error":
-		lvl = 2
-	default:
-		i, err := strconv.Atoi(lower)
-		if err != nil {
-			return fmt.Errorf("invalid log level \"%s\"", l)
-		}
-
-		if i > 0 {
-			lvl = -1 * i
-		} else {
-			return fmt.Errorf("invalid log level \"%s\"", l)
-		}
+	lvl, err := intLogLevel(l)
+	if err != nil {
+		return err
 	}
+
 	v.level = zapcore.Level(int8(lvl))
 	// If log level is greater than debug, set glog/klog level to that level.
 	if lvl < -3 {
@@ -145,6 +135,59 @@ func (v levelValue) Type() string {
 	return "level"
 }
 
+type stackLevelValue struct {
+	set   bool
+	level zapcore.Level
+}
+
+func (v *stackLevelValue) Set(l string) error {
+	v.set = true
+	lvl, err := intLogLevel(l)
+	if err != nil {
+		return err
+	}
+
+	v.level = zapcore.Level(int8(lvl))
+	return nil
+}
+
+func (v stackLevelValue) String() string {
+	if v.set {
+		return v.level.String()
+	}
+
+	return "error"
+}
+
+func (v stackLevelValue) Type() string {
+	return "level"
+}
+
+func intLogLevel(l string) (int, error) {
+	lower := strings.ToLower(l)
+	var lvl int
+	switch lower {
+	case "debug":
+		lvl = -1
+	case "info":
+		lvl = 0
+	case "error":
+		lvl = 2
+	default:
+		i, err := strconv.Atoi(lower)
+		if err != nil {
+			return lvl, fmt.Errorf("invalid log level \"%s\"", l)
+		}
+
+		if i > 0 {
+			lvl = -1 * i
+		} else {
+			return lvl, fmt.Errorf("invalid log level \"%s\"", l)
+		}
+	}
+	return lvl, nil
+}
+
 type sampleValue struct {
 	set    bool
 	sample bool
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/logger.go b/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/logger.go
index cf9915343ecbed9266a2f560d2a6b16a03c83196..f8de2450b90aba6886aedfdd49131ef76c2b399e 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/logger.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/log/zap/logger.go
@@ -51,10 +51,11 @@ func createLogger(conf config, destWriter io.Writer) logr.Logger {
 }
 
 type config struct {
-	encoder zapcore.Encoder
-	level   zap.AtomicLevel
-	sample  bool
-	opts    []zap.Option
+	encoder         zapcore.Encoder
+	level           zap.AtomicLevel
+	opts            []zap.Option
+	stackTraceLevel zapcore.Level
+	sample          bool
 }
 
 func getConfig() config {
@@ -66,16 +67,22 @@ func getConfig() config {
 	if development {
 		newEncoder = newConsoleEncoder
 		c.level = zap.NewAtomicLevelAt(zap.DebugLevel)
-		c.opts = append(c.opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel))
+		c.opts = append(c.opts, zap.Development())
 		c.sample = false
+		c.stackTraceLevel = zap.WarnLevel
 	} else {
 		newEncoder = newJSONEncoder
 		c.level = zap.NewAtomicLevelAt(zap.InfoLevel)
-		c.opts = append(c.opts, zap.AddStacktrace(zap.WarnLevel))
 		c.sample = true
+		c.stackTraceLevel = zap.ErrorLevel
 	}
 
 	// Override the defaults if the flags were set explicitly on the command line
+	if stacktraceLevel.set {
+		c.stackTraceLevel = stacktraceLevel.level
+	}
+	c.opts = append(c.opts, zap.AddStacktrace(c.stackTraceLevel))
+
 	var ecfs []encoderConfigFunc
 	if encoderVal.set {
 		newEncoder = encoderVal.newEncoder
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/metrics.go b/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/metrics.go
index 5ef0fd9d40839e3a0d57bcd8346370ca8c23b464..243c3d9a0f9c04e52fae1b96865507df166f1137 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/metrics.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/metrics.go
@@ -89,11 +89,13 @@ func createOrUpdateService(ctx context.Context, client crclient.Client, s *v1.Se
 		if err != nil {
 			return nil, err
 		}
-		log.Info("Metrics Service object updated", "Service.Name", s.Name, "Service.Namespace", s.Namespace)
+		log.Info("Metrics Service object updated", "Service.Name",
+			s.Name, "Service.Namespace", s.Namespace)
 		return s, nil
 	}
 
-	log.Info("Metrics Service object created", "Service.Name", s.Name, "Service.Namespace", s.Namespace)
+	log.Info("Metrics Service object created", "Service.Name",
+		s.Name, "Service.Namespace", s.Namespace)
 	return s, nil
 }
 
@@ -152,7 +154,8 @@ func getPodOwnerRef(ctx context.Context, client crclient.Client, ns string) (*me
 }
 
 // findFinalOwnerRef tries to locate the final controller/owner based on the owner reference provided.
-func findFinalOwnerRef(ctx context.Context, client crclient.Client, ns string, ownerRef *metav1.OwnerReference) (*metav1.OwnerReference, error) {
+func findFinalOwnerRef(ctx context.Context, client crclient.Client, ns string,
+	ownerRef *metav1.OwnerReference) (*metav1.OwnerReference, error) {
 	if ownerRef == nil {
 		return nil, nil
 	}
@@ -169,6 +172,7 @@ func findFinalOwnerRef(ctx context.Context, client crclient.Client, ns string, o
 		return findFinalOwnerRef(ctx, client, ns, newOwnerRef)
 	}
 
-	log.V(1).Info("Pods owner found", "Kind", ownerRef.Kind, "Name", ownerRef.Name, "Namespace", ns)
+	log.V(1).Info("Pods owner found", "Kind", ownerRef.Kind, "Name",
+		ownerRef.Name, "Namespace", ns)
 	return ownerRef, nil
 }
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/service-monitor.go b/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/service-monitor.go
index fb2511c376e8640853cf58463fa74130281f4d14..dd18bd46d7492c3fbb83a4f51bffd678e922ebf6 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/service-monitor.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/metrics/service-monitor.go
@@ -32,7 +32,8 @@ type ServiceMonitorUpdater func(*monitoringv1.ServiceMonitor) error
 
 // CreateServiceMonitors creates ServiceMonitors objects based on an array of Service objects.
 // If CR ServiceMonitor is not registered in the Cluster it will not attempt at creating resources.
-func CreateServiceMonitors(config *rest.Config, ns string, services []*v1.Service, updaters ...ServiceMonitorUpdater) ([]*monitoringv1.ServiceMonitor, error) {
+func CreateServiceMonitors(config *rest.Config, ns string, services []*v1.Service,
+	updaters ...ServiceMonitorUpdater) ([]*monitoringv1.ServiceMonitor, error) {
 	// check if we can even create ServiceMonitors
 	exists, err := hasServiceMonitor(config)
 	if err != nil {
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/test/client.go b/vendor/github.com/operator-framework/operator-sdk/pkg/test/client.go
index 7f1705b932f055b7c089776c72d1dfc4854df4c9..0f2c98d4a0a484bef89c86517efbc77cadeccc59 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/test/client.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/test/client.go
@@ -59,7 +59,8 @@ func (f *frameworkClient) Create(gCtx goctx.Context, obj runtime.Object, cleanup
 	key, err := dynclient.ObjectKeyFromObject(objCopy)
 	// this function fails silently if t is nil
 	if cleanupOptions.TestContext.t != nil {
-		cleanupOptions.TestContext.t.Logf("resource type %+v with namespace/name (%+v) created\n", objCopy.GetObjectKind().GroupVersionKind().Kind, key)
+		cleanupOptions.TestContext.t.Logf("resource type %+v with namespace/name (%+v) created\n",
+			objCopy.GetObjectKind().GroupVersionKind().Kind, key)
 	}
 	cleanupOptions.TestContext.AddCleanupFn(func() error {
 		err = retry.OnError(retry.DefaultRetry, retryOnAnyError, func() error {
@@ -79,14 +80,17 @@ func (f *frameworkClient) Create(gCtx goctx.Context, obj runtime.Object, cleanup
 				if err != nil {
 					if apierrors.IsNotFound(err) {
 						if cleanupOptions.TestContext.t != nil {
-							cleanupOptions.TestContext.t.Logf("resource type %+v with namespace/name (%+v) successfully deleted\n", objCopy.GetObjectKind().GroupVersionKind().Kind, key)
+							cleanupOptions.TestContext.t.Logf("resource type %+v with namespace/name (%+v)"+
+								" successfully deleted\n", objCopy.GetObjectKind().GroupVersionKind().Kind, key)
 						}
 						return true, nil
 					}
-					return false, fmt.Errorf("error encountered during deletion of resource type %v with namespace/name (%+v): %w", objCopy.GetObjectKind().GroupVersionKind().Kind, key, err)
+					return false, fmt.Errorf("error encountered during deletion of resource type %v with"+
+						" namespace/name (%+v): %v", objCopy.GetObjectKind().GroupVersionKind().Kind, key, err)
 				}
 				if cleanupOptions.TestContext.t != nil {
-					cleanupOptions.TestContext.t.Logf("waiting for deletion of resource type %+v with namespace/name (%+v)\n", objCopy.GetObjectKind().GroupVersionKind().Kind, key)
+					cleanupOptions.TestContext.t.Logf("waiting for deletion of resource type %+v with"+
+						" namespace/name (%+v)\n", objCopy.GetObjectKind().GroupVersionKind().Kind, key)
 				}
 				return false, nil
 			})
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/test/context.go b/vendor/github.com/operator-framework/operator-sdk/pkg/test/context.go
index 6ce9a6906176a97c964b8e966cc27f680f3cd5aa..9721642cd691df17b5e4353f6ef4dda1d34effbd 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/test/context.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/test/context.go
@@ -24,56 +24,76 @@ import (
 	"k8s.io/client-go/restmapper"
 )
 
-type TestCtx struct { //nolint:golint
-	// todo(camilamacedo86): The no lint here is for type name will be used as test.TestCtx by other packages, and that stutters; consider calling this Ctx (golint)
-	// However, was decided to not move forward with it now in order to not introduce breakchanges with the task to add the linter. We should to do it after.
+type Context struct {
 	id         string
 	cleanupFns []cleanupFn
 	namespace  string
 	t          *testing.T
 
-	namespacedManPath string
-	client            *frameworkClient
-	kubeclient        kubernetes.Interface
-	restMapper        *restmapper.DeferredDiscoveryRESTMapper
+	namespacedManPath  string
+	client             *frameworkClient
+	kubeclient         kubernetes.Interface
+	restMapper         *restmapper.DeferredDiscoveryRESTMapper
+	skipCleanupOnError bool
 }
 
+// todo(camilamacedo86): Remove the following line just added for we are able to deprecated TestCtx
+// need to be done before: 1.0.0
+
+// Deprecated: TestCtx exists for historical compatibility. Use Context instead.
+type TestCtx = Context //nolint:golint
+
 type CleanupOptions struct {
-	TestContext   *TestCtx
+	TestContext   *Context
 	Timeout       time.Duration
 	RetryInterval time.Duration
 }
 
 type cleanupFn func() error
 
-func (f *Framework) newTestCtx(t *testing.T) *TestCtx {
-	// TestCtx is used among others for namespace names where '/' is forbidden and must be 63 characters or less
+func (f *Framework) newContext(t *testing.T) *Context {
+
+	// Context is used among others for namespace names where '/' is forbidden and must be 63 characters or less
 	id := "osdk-e2e-" + uuid.New()
 
 	var namespace string
 	if f.singleNamespaceMode {
 		namespace = f.Namespace
 	}
-	return &TestCtx{
-		id:                id,
-		t:                 t,
-		namespace:         namespace,
-		namespacedManPath: *f.NamespacedManPath,
-		client:            f.Client,
-		kubeclient:        f.KubeClient,
-		restMapper:        f.restMapper,
+	return &Context{
+		id:                 id,
+		t:                  t,
+		namespace:          namespace,
+		namespacedManPath:  *f.NamespacedManPath,
+		client:             f.Client,
+		kubeclient:         f.KubeClient,
+		restMapper:         f.restMapper,
+		skipCleanupOnError: f.skipCleanupOnError,
 	}
 }
 
+// Deprecated: NewTestCtx exists for historical compatibility. Use NewContext instead.
 func NewTestCtx(t *testing.T) *TestCtx {
-	return Global.newTestCtx(t)
+	return Global.newContext(t)
 }
 
-func (ctx *TestCtx) GetID() string {
+func NewContext(t *testing.T) *Context {
+	return Global.newContext(t)
+}
+
+func (ctx *Context) GetID() string {
 	return ctx.id
 }
 
-func (ctx *TestCtx) Cleanup() {
+func (ctx *Context) Cleanup() {
+	if ctx.t != nil {
+		// The cleanup function will be skipped
+		if ctx.t.Failed() && ctx.skipCleanupOnError {
+			// Also, could we log the error here?
+			log.Info("Skipping cleanup function since --skip-cleanup-error is true")
+			return
+		}
+	}
 	failed := false
 	for i := len(ctx.cleanupFns) - 1; i >= 0; i-- {
 		err := ctx.cleanupFns[i]()
@@ -91,6 +111,6 @@ func (ctx *TestCtx) Cleanup() {
 	}
 }
 
-func (ctx *TestCtx) AddCleanupFn(fn cleanupFn) {
+func (ctx *Context) AddCleanupFn(fn cleanupFn) {
 	ctx.cleanupFns = append(ctx.cleanupFns, fn)
 }
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/test/e2eutil/wait_util.go b/vendor/github.com/operator-framework/operator-sdk/pkg/test/e2eutil/wait_util.go
index fdcf7bc1323406b99678fed2215b04b80c0d4954..4f2850439926d7449c622583562f48354387d712 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/test/e2eutil/wait_util.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/test/e2eutil/wait_util.go
@@ -29,21 +29,24 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-// WaitForDeployment checks to see if a given deployment has a certain number of available replicas after a specified amount of time
-// If the deployment does not have the required number of replicas after 5 * retries seconds, the function returns an error
-// This can be used in multiple ways, like verifying that a required resource is ready before trying to use it, or to test
-// failure handling, like simulated in SimulatePodFail.
-func WaitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration) error {
+// WaitForDeployment checks to see if a given deployment has a certain number of available replicas after a specified
+// amount of time. If the deployment does not have the required number of replicas after 5 * retries seconds,
+// the function returns an error. This can be used in multiple ways, like verifying that a required resource is ready
+// before trying to use it, or to test. Failure handling, like simulated in SimulatePodFail.
+func WaitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int,
+	retryInterval, timeout time.Duration) error {
 	return waitForDeployment(t, kubeclient, namespace, name, replicas, retryInterval, timeout, false)
 }
 
 // WaitForOperatorDeployment has the same functionality as WaitForDeployment but will no wait for the deployment if the
 // test was run with a locally run operator (--up-local flag)
-func WaitForOperatorDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration) error {
+func WaitForOperatorDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int,
+	retryInterval, timeout time.Duration) error {
 	return waitForDeployment(t, kubeclient, namespace, name, replicas, retryInterval, timeout, true)
 }
 
-func waitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration, isOperator bool) error {
+func waitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int,
+	retryInterval, timeout time.Duration, isOperator bool) error {
 	if isOperator && test.Global.LocalOperator {
 		t.Log("Operator is running locally; skip waitForDeployment")
 		return nil
@@ -61,7 +64,8 @@ func waitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace,
 		if int(deployment.Status.AvailableReplicas) >= replicas {
 			return true, nil
 		}
-		t.Logf("Waiting for full availability of %s deployment (%d/%d)\n", name, deployment.Status.AvailableReplicas, replicas)
+		t.Logf("Waiting for full availability of %s deployment (%d/%d)\n", name,
+			deployment.Status.AvailableReplicas, replicas)
 		return false, nil
 	})
 	if err != nil {
@@ -71,7 +75,8 @@ func waitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace,
 	return nil
 }
 
-func WaitForDeletion(t *testing.T, dynclient client.Client, obj runtime.Object, retryInterval, timeout time.Duration) error {
+func WaitForDeletion(t *testing.T, dynclient client.Client, obj runtime.Object, retryInterval,
+	timeout time.Duration) error {
 	key, err := client.ObjectKeyFromObject(obj)
 	if err != nil {
 		return err
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/test/framework.go b/vendor/github.com/operator-framework/operator-sdk/pkg/test/framework.go
index f69efde3d5d7c7c1b3ccd6726a937b6cc8b05118..851972c69596decef93bba314c995bc63aac05ff 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/test/framework.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/test/framework.go
@@ -71,6 +71,7 @@ type Framework struct {
 	schemeMutex         sync.Mutex
 	LocalOperator       bool
 	singleNamespaceMode bool
+	skipCleanupOnError  bool
 }
 
 type frameworkOpts struct {
@@ -78,19 +79,21 @@ type frameworkOpts struct {
 	kubeconfigPath      string
 	globalManPath       string
 	namespacedManPath   string
+	localOperatorArgs   string
 	singleNamespaceMode bool
 	isLocalOperator     bool
-	localOperatorArgs   string
+	skipCleanupOnError  bool
 }
 
 const (
-	ProjRootFlag          = "root"
-	KubeConfigFlag        = "kubeconfig"
-	NamespacedManPathFlag = "namespacedMan"
-	GlobalManPathFlag     = "globalMan"
-	SingleNamespaceFlag   = "singleNamespace"
-	LocalOperatorFlag     = "localOperator"
-	LocalOperatorArgs     = "localOperatorArgs"
+	ProjRootFlag           = "root"
+	KubeConfigFlag         = "kubeconfig"
+	NamespacedManPathFlag  = "namespacedMan"
+	GlobalManPathFlag      = "globalMan"
+	SingleNamespaceFlag    = "singleNamespace"
+	LocalOperatorFlag      = "localOperator"
+	LocalOperatorArgs      = "localOperatorArgs"
+	SkipCleanupOnErrorFlag = "skipCleanupOnError"
 
 	TestNamespaceEnv = "TEST_NAMESPACE"
 )
@@ -98,11 +101,16 @@ const (
 func (opts *frameworkOpts) addToFlagSet(flagset *flag.FlagSet) {
 	flagset.StringVar(&opts.projectRoot, ProjRootFlag, "", "path to project root")
 	flagset.StringVar(&opts.namespacedManPath, NamespacedManPathFlag, "", "path to rbac manifest")
-	flagset.BoolVar(&opts.isLocalOperator, LocalOperatorFlag, false, "enable if operator is running locally (not in cluster)")
+	flagset.BoolVar(&opts.isLocalOperator, LocalOperatorFlag, false,
+		"enable if operator is running locally (not in cluster)")
 	flagset.StringVar(&opts.kubeconfigPath, KubeConfigFlag, "", "path to kubeconfig")
 	flagset.StringVar(&opts.globalManPath, GlobalManPathFlag, "", "path to operator manifest")
 	flagset.BoolVar(&opts.singleNamespaceMode, SingleNamespaceFlag, false, "enable single namespace mode")
-	flagset.StringVar(&opts.localOperatorArgs, LocalOperatorArgs, "", "flags that the operator needs (while using --up-local). example: \"--flag1 value1 --flag2=value2\"")
+	flagset.StringVar(&opts.localOperatorArgs, LocalOperatorArgs, "",
+		"flags that the operator needs (while using --up-local). example: \"--flag1 value1 --flag2=value2\"")
+	flagset.BoolVar(&opts.skipCleanupOnError, SkipCleanupOnErrorFlag, false,
+		"If set as true, the cleanup function responsible to remove all artifacts "+
+			"will be skipped if an error is faced.")
 }
 
 func newFramework(opts *frameworkOpts) (*Framework, error) {
@@ -155,6 +163,7 @@ func newFramework(opts *frameworkOpts) (*Framework, error) {
 		localOperatorArgs:   opts.localOperatorArgs,
 		kubeconfigPath:      opts.kubeconfigPath,
 		restMapper:          restMapper,
+		skipCleanupOnError:  opts.skipCleanupOnError,
 	}
 	return framework, nil
 }
@@ -208,7 +217,7 @@ func (f *Framework) addToScheme(addToScheme addToSchemeFunc, obj runtime.Object)
 
 func (f *Framework) runM(m *testing.M) (int, error) {
 	// setup context to use when setting up crd
-	ctx := f.newTestCtx(nil)
+	ctx := f.newContext(nil)
 	defer ctx.Cleanup()
 
 	// go test always runs from the test directory; change to project root
@@ -281,7 +290,8 @@ func (f *Framework) setupLocalCommand() (*exec.Cmd, error) {
 	} else {
 		// we can hardcode index 0 as that is the highest priority kubeconfig to be loaded and will always
 		// be populated by NewDefaultClientConfigLoadingRules()
-		localCmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", k8sutil.KubeConfigEnvVar, clientcmd.NewDefaultClientConfigLoadingRules().Precedence[0]))
+		localCmd.Env = append(os.Environ(), fmt.Sprintf("%v=%v", k8sutil.KubeConfigEnvVar,
+			clientcmd.NewDefaultClientConfigLoadingRules().Precedence[0]))
 	}
 	localCmd.Env = append(localCmd.Env, fmt.Sprintf("%v=%v", k8sutil.WatchNamespaceEnvVar, f.Namespace))
 	return localCmd, nil
diff --git a/vendor/github.com/operator-framework/operator-sdk/pkg/test/resource_creator.go b/vendor/github.com/operator-framework/operator-sdk/pkg/test/resource_creator.go
index ee578a49b295ff4df7cae36f99c658380796a74a..3b6877a8756a6d5ae485a3867df1eccdb80e8586 100644
--- a/vendor/github.com/operator-framework/operator-sdk/pkg/test/resource_creator.go
+++ b/vendor/github.com/operator-framework/operator-sdk/pkg/test/resource_creator.go
@@ -29,7 +29,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/wait"
 )
 
-func (ctx *TestCtx) GetNamespace() (string, error) {
+func (ctx *Context) GetNamespace() (string, error) {
 	if ctx.namespace != "" {
 		return ctx.namespace, nil
 	}
@@ -48,7 +48,7 @@ func (ctx *TestCtx) GetNamespace() (string, error) {
 	return ctx.namespace, nil
 }
 
-func (ctx *TestCtx) createFromYAML(yamlFile []byte, skipIfExists bool, cleanupOptions *CleanupOptions) error {
+func (ctx *Context) createFromYAML(yamlFile []byte, skipIfExists bool, cleanupOptions *CleanupOptions) error {
 	namespace, err := ctx.GetNamespace()
 	if err != nil {
 		return err
@@ -101,7 +101,7 @@ func (ctx *TestCtx) createFromYAML(yamlFile []byte, skipIfExists bool, cleanupOp
 	return nil
 }
 
-func (ctx *TestCtx) InitializeClusterResources(cleanupOptions *CleanupOptions) error {
+func (ctx *Context) InitializeClusterResources(cleanupOptions *CleanupOptions) error {
 	// create namespaced resources
 	namespacedYAML, err := ioutil.ReadFile(ctx.namespacedManPath)
 	if err != nil {
diff --git a/vendor/github.com/operator-framework/operator-sdk/version/version.go b/vendor/github.com/operator-framework/operator-sdk/version/version.go
index 4b79e821816dd5e238a1ebd02e7eeb243b389a7e..a645239f1550fed0ad03571283b6bac0fc56514b 100644
--- a/vendor/github.com/operator-framework/operator-sdk/version/version.go
+++ b/vendor/github.com/operator-framework/operator-sdk/version/version.go
@@ -20,7 +20,7 @@ import (
 )
 
 var (
-	Version    = "v0.15.1"
+	Version    = "v0.16.0"
 	GitVersion = "unknown"
 	GitCommit  = "unknown"
 	GoVersion  = fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index cdbe04f05624d06ef4cdff5780e422bab490028c..869ccd43591dea72ddaee986c0271ff13f69a169 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -91,7 +91,7 @@ github.com/hashicorp/golang-lru/simplelru
 github.com/imdario/mergo
 # github.com/inconshreveable/mousetrap v1.0.0
 github.com/inconshreveable/mousetrap
-# github.com/integr8ly/grafana-operator/v3 v3.0.2-0.20200103111057-03d7fa884db4
+# github.com/integr8ly/grafana-operator/v3 v3.4.0
 github.com/integr8ly/grafana-operator/v3/pkg/apis/integreatly/v1alpha1
 # github.com/joho/godotenv v1.3.0
 github.com/joho/godotenv
@@ -115,7 +115,7 @@ github.com/modern-go/concurrent
 github.com/modern-go/reflect2
 # github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible => github.com/openshift/api v0.0.0-20190924102528-32369d4db2ad
 github.com/openshift/api/route/v1
-# github.com/operator-framework/operator-sdk v0.15.1
+# github.com/operator-framework/operator-sdk v0.16.0
 github.com/operator-framework/operator-sdk/internal/scaffold
 github.com/operator-framework/operator-sdk/internal/scaffold/input
 github.com/operator-framework/operator-sdk/internal/scaffold/internal/deps