Repository: Azure/ARO-RP
Pull request #2079 (2022-04-21 15:11:10)

Small updates to shared rp docs from working sessions
Minor documentation updates to settings up the shared RP env from our working sessions. @karanmagdani 


Patch:
diff --git a/.github/workflows/golint.yml b/.github/workflows/golint.yml
new file mode 100644
index 000000000..c73e98cce
--- /dev/null
+++ b/.github/workflows/golint.yml
@@ -0,0 +1,49 @@
+name: golangci-lint
+on:
+  push:
+    tags:
+      - v*
+    branches:
+      - master
+      - main
+  pull_request:
+permissions:
+  contents: read
+  # Optional: allow read access to pull request. Use with `only-new-issues` option.
+  # pull-requests: read
+jobs:
+  golangci:
+    name: lint
+    runs-on: ubuntu-latest
+    steps:
+      - run: | 
+          sudo apt-get update 
+          sudo apt-get install libgpgme-dev libgpgme11
+      - uses: actions/setup-go@v3
+        with:
+          go-version: 1.17
+      - uses: actions/checkout@v3
+      - name: golangci-lint
+        uses: golangci/golangci-lint-action@v3
+        with:
+          # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
+          version: v1.45.2
+
+          # Optional: working directory, useful for monorepos
+          #working-directory: pkg
+
+          # Optional: golangci-lint command line arguments.
+          #args: -c .golangci.yml
+
+          # Optional: show only new issues if it's a pull request. The default value is `false`.
+          # only-new-issues: true
+
+          # Optional: if set to true then the all caching functionality will be complete disabled,
+          #           takes precedence over all other caching options.
+          # skip-cache: true
+
+          # Optional: if set to true then the action don't cache or restore ~/go/pkg.
+          # skip-pkg-cache: true
+
+          # Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
+          # skip-build-cache: true
diff --git a/.golangci.yml b/.golangci.yml
index 682ae7a6d..8c8b3f88d 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -16,7 +16,10 @@ linters-settings:
   stylecheck:
     # added additional checks for comments in Go.
     # Refer https://staticcheck.io/docs/options#checks for details
-    checks: ["all", "-ST1000", "ST1020", "ST1021", "ST1022"]
+    checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
+    dot-import-whitelist:
+      - github.com/onsi/ginkgo
+      - github.com/onsi/gomega
 
 
 linters:
@@ -28,6 +31,5 @@ linters:
     - gosimple
     - govet
     - staticcheck
-    # TODO: Enable the stylecheck linter in a follow-up PR as it requires changes in a lot of files
-    # - stylecheck
     - whitespace
+    - stylecheck
diff --git a/.pipelines/ci.yml b/.pipelines/ci.yml
index 6252ba13d..46dce116b 100644
--- a/.pipelines/ci.yml
+++ b/.pipelines/ci.yml
@@ -52,12 +52,6 @@ jobs:
       [[ -z "$(git status -s)" ]]
     displayName: 🕵️ Validate Golang code
 
-  - script: |
-      set -xe
-      make lint-go
-      [[ -z "$(git status -s)" ]]
-    displayName: 🕵️ Lint Golang code
-
   - script: |
       set -xe
       make build-all
diff --git a/docs/prepare-a-shared-rp-development-environment.md b/docs/prepare-a-shared-rp-development-environment.md
index 15a4988ab..3f2a24c23 100644
--- a/docs/prepare-a-shared-rp-development-environment.md
+++ b/docs/prepare-a-shared-rp-development-environment.md
@@ -88,9 +88,9 @@ locations.
    ```
 
    ```bash
+   > __NOTE:__: for macos change the -w0 option for base64 to -b0
    AZURE_ARM_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-arm-shared \
-     --identifier-uris "https://$(uuidgen)/" \
      --query appId \
      -o tsv)"
    az ad app credential reset \
@@ -117,9 +117,9 @@ locations.
    Now create the application:
 
    ```bash
+   > __NOTE:__: for macos change the -w0 option for base64 to -b0
    AZURE_FP_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-fp-shared \
-     --identifier-uris "https://$(uuidgen)/" \
      --query appId \
      -o tsv)"
    az ad app credential reset \
@@ -141,7 +141,6 @@ locations.
    AZURE_RP_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-rp-shared \
      --end-date '2299-12-31T11:59:59+00:00' \
-     --identifier-uris "https://$(uuidgen)/" \
      --key-type password \
      --password "$AZURE_RP_CLIENT_SECRET" \
      --query appId \
@@ -162,7 +161,6 @@ locations.
    AZURE_GATEWAY_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-gateway-shared \
      --end-date '2299-12-31T11:59:59+00:00' \
-     --identifier-uris "https://$(uuidgen)/" \
      --key-type password \
      --password "$AZURE_GATEWAY_CLIENT_SECRET" \
      --query appId \
@@ -177,7 +175,6 @@ locations.
    AZURE_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-tooling-shared \
      --end-date '2299-12-31T11:59:59+00:00' \
-     --identifier-uris "https://$(uuidgen)/" \
      --key-type password \
      --password "$AZURE_CLIENT_SECRET" \
      --query appId \
@@ -194,26 +191,26 @@ locations.
 
    * Go into the Azure Portal
    * Go to Azure Active Directory
-   * Navigate to the `aro-v4-tooling-shared` app page
+   * Navigate to the `aro-v4-tooling-shared` app registration page
    * Click 'API permissions' in the left side pane
-   * Click 'Microsoft Graph'
    * Click 'Add a permission'.
+   * Click 'Microsoft Graph'
    * Select 'Application permissions'
    * Search for 'Application' and select `Application.ReadWrite.OwnedBy`
    * Click 'Add permissions'
    * This request will need to be approved by a tenant administrator. If you are one, you can click the `Grant admin consent for <name>` button to the right of the `Add a permission` button on the app page
 
-1. Set up the RP role definitions and subscription role assignments in your
-   Azure subscription. This mimics the RBAC that ARM sets up.  With at least
-   `User Access Administrator` permissions on your subscription, do:
+1. Set up the RP role definitions and subscription role assignments in your Azure subscription. The usage of "uuidgen" for fpRoleDefinitionId is simply there to keep from interfering with any linked resources and to create the role net new. This mimics the RBAC that ARM sets up. With at least `User Access Administrator` permissions on your subscription, do:
 
    ```bash
+   LOCATION=<YOUR-REGION>
    az deployment sub create \
      -l $LOCATION \
      --template-file deploy/rbac-development.json \
      --parameters \
        "armServicePrincipalId=$(az ad sp list --filter "appId eq '$AZURE_ARM_CLIENT_ID'" --query '[].objectId' -o tsv)" \
        "fpServicePrincipalId=$(az ad sp list --filter "appId eq '$AZURE_FP_CLIENT_ID'" --query '[].objectId' -o tsv)" \
+       "fpRoleDefinitionId"="$(uuidgen)" \
        "devServicePrincipalId=$(az ad sp list --filter "appId eq '$AZURE_CLIENT_ID'" --query '[].objectId' -o tsv)" \
      >/dev/null
    ```
@@ -230,9 +227,9 @@ locations.
    ```
 
    ```bash
+   > __NOTE:__: for macos change the -w0 option for base64 to -b0
    AZURE_PORTAL_CLIENT_ID="$(az ad app create \
      --display-name aro-v4-portal-shared \
-     --identifier-uris "https://$(uuidgen)/" \
      --reply-urls "https://localhost:8444/callback" \
      --query appId \
      -o tsv)"
@@ -241,8 +238,6 @@ locations.
      --cert "$(base64 -w0 <secrets/portal-client.crt)" >/dev/null
    ```
 
-   TODO: more steps are needed to configure aro-v4-portal-shared.
-
 1. Create an AAD application which will fake up the dbtoken client.
 
    1. Create the application and set `requestedAccessTokenVersion`
@@ -255,6 +250,7 @@ locations.
 
    OBJ_ID="$(az ad app show --id $AZURE_DBTOKEN_CLIENT_ID --query objectId)"
 
+   > __NOTE:__: the graph API requires this to be done from a managed machine
    az rest --method PATCH \
       --uri https://graph.microsoft.com/v1.0/applications/$OBJ_ID/ \
       --body '{"api":{"requestedAccessTokenVersion": 2}}'
@@ -378,7 +374,7 @@ storage account so other people on your team can access it via `make secrets`
 # Environment file
 
 1. Choose the resource group prefix.  The resource group location will be
-   appended to the prefix to make the resource group name.
+   The resource group location will be appended to the prefix to make the resource group name. If a v4-prefixed environment exists in the subscription already, use a unique prefix.
 
    ```bash
    RESOURCEGROUP_PREFIX=v4
@@ -480,7 +476,7 @@ each of the bash functions below.
    import_certs_secrets
    ```
 
-   Note: in production, three additional keys/certificates (rp-mdm, rp-mdsd, and
+   > __NOTE:__: in production, three additional keys/certificates (rp-mdm, rp-mdsd, and
    cluster-mdsd) are also required in the $KEYVAULT_PREFIX-svc key vault.  These
    are client certificates for RP metric and log forwarding (respectively) to
    Geneva.
@@ -512,10 +508,12 @@ each of the bash functions below.
         --file secrets/cluster-logging-int.pem
    ```
 
-   Note: in development, if you don't have valid certs for these, you can just
+   > __NOTE:__: in development, if you don't have valid certs for these, you can just
    upload `localhost.pem` as a placeholder for each of these. This will avoid an
    error stemming from them not existing, but it will result in logging pods
-   crash looping in any clusters you make.
+   crash looping in any clusters you make. Additionally, no gateway resources are 
+   created in development so you should not need to execute the cert import statement
+   for the "-gwy" keyvault.
 
 1. In pre-production (int, e2e) certain certificates are provisioned via keyvault
 integration. These should be rotated and generated in the keyvault itself:
@@ -546,4 +544,4 @@ Development value: secrets/cluster-logging-int.pem
 ## Append Resource Group to Subscription Cleaner DenyList
 
 * We have subscription pruning that takes place routinely and need to add our resource group for the shared rp environment to the `denylist` of the cleaner:
-	* [https://github.com/Azure/ARO-RP/blob/e918d1b87be53a3b3cdf18b674768a6480fb56b8/hack/clean/clean.go#L29](https://github.com/Azure/ARO-RP/blob/e918d1b87be53a3b3cdf18b674768a6480fb56b8/hack/clean/clean.go#L29) 
+   * [https://github.com/Azure/ARO-RP/blob/e918d1b87be53a3b3cdf18b674768a6480fb56b8/hack/clean/clean.go#L29](https://github.com/Azure/ARO-RP/blob/e918d1b87be53a3b3cdf18b674768a6480fb56b8/hack/clean/clean.go#L29) 
diff --git a/hack/validate-imports/validate-imports.go b/hack/validate-imports/validate-imports.go
index 440b29a2f..d799b76f3 100644
--- a/hack/validate-imports/validate-imports.go
+++ b/hack/validate-imports/validate-imports.go
@@ -15,16 +15,6 @@ func isStandardLibrary(path string) bool {
 	return !strings.ContainsRune(strings.SplitN(path, "/", 2)[0], '.')
 }
 
-func validateDotImport(path string) error {
-	switch path {
-	case "github.com/onsi/ginkgo",
-		"github.com/onsi/gomega":
-		return nil
-	}
-
-	return fmt.Errorf("invalid . import %s", path)
-}
-
 func validateUnderscoreImport(path string) error {
 	if regexp.MustCompile(`^github\.com/Azure/ARO-RP/pkg/api/(admin|v[^/]+)$`).MatchString(path) {
 		return nil
@@ -227,10 +217,7 @@ nextImport:
 		value := strings.Trim(imp.Path.Value, `"`)
 
 		if imp.Name != nil && imp.Name.Name == "." {
-			err := validateDotImport(value)
-			if err != nil {
-				errs = append(errs, err)
-			}
+			//accept dotimports because we check them with golangci-lint
 			continue
 		}
 
@@ -279,7 +266,6 @@ nextImport:
 				continue nextImport
 			}
 		}
-
 		errs = append(errs, fmt.Errorf("%s is imported as %q, should be %q", value, imp.Name, names))
 	}
 
diff --git a/pkg/api/admin/openshiftcluster.go b/pkg/api/admin/openshiftcluster.go
index bac3029a4..ad65544d4 100644
--- a/pkg/api/admin/openshiftcluster.go
+++ b/pkg/api/admin/openshiftcluster.go
@@ -119,13 +119,23 @@ const (
 	SoftwareDefinedNetworkOpenShiftSDN  SoftwareDefinedNetwork = "OpenShiftSDN"
 )
 
+// MTUSize represents the MTU size of a cluster (Maximum transmission unit)
+type MTUSize int
+
+// MTUSize constants
+const (
+	MTU1500 MTUSize = 1500
+	MTU3900 MTUSize = 3900
+)
+
 // NetworkProfile represents a network profile.
 type NetworkProfile struct {
 	// The software defined network (SDN) to use when installing the cluster.
 	SoftwareDefinedNetwork SoftwareDefinedNetwork `json:"softwareDefinedNetwork,omitempty"`
 
-	PodCIDR     string `json:"podCidr,omitempty"`
-	ServiceCIDR string `json:"serviceCidr,omitempty"`
+	PodCIDR     string  `json:"podCidr,omitempty"`
+	ServiceCIDR string  `json:"serviceCidr,omitempty"`
+	MTUSize     MTUSize `json:"mtuSize,omitempty"`
 
 	APIServerPrivateEndpointIP string `json:"privateEndpointIp,omitempty"`
 	GatewayPrivateEndpointIP   string `json:"gatewayPrivateEndpointIp,omitempty"`
diff --git a/pkg/api/admin/openshiftcluster_convert.go b/pkg/api/admin/openshiftcluster_convert.go
index bf7844777..0686c060a 100644
--- a/pkg/api/admin/openshiftcluster_convert.go
+++ b/pkg/api/admin/openshiftcluster_convert.go
@@ -50,6 +50,7 @@ func (c *openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfa
 				SoftwareDefinedNetwork:     SoftwareDefinedNetwork(oc.Properties.NetworkProfile.SoftwareDefinedNetwork),
 				PodCIDR:                    oc.Properties.NetworkProfile.PodCIDR,
 				ServiceCIDR:                oc.Properties.NetworkProfile.ServiceCIDR,
+				MTUSize:                    MTUSize(oc.Properties.NetworkProfile.MTUSize),
 				APIServerPrivateEndpointIP: oc.Properties.NetworkProfile.APIServerPrivateEndpointIP,
 				GatewayPrivateEndpointIP:   oc.Properties.NetworkProfile.GatewayPrivateEndpointIP,
 				GatewayPrivateLinkID:       oc.Properties.NetworkProfile.GatewayPrivateLinkID,
@@ -185,6 +186,7 @@ func (c *openShiftClusterConverter) ToInternal(_oc interface{}, out *api.OpenShi
 	out.Properties.ServicePrincipalProfile.SPObjectID = oc.Properties.ServicePrincipalProfile.SPObjectID
 	out.Properties.NetworkProfile.PodCIDR = oc.Properties.NetworkProfile.PodCIDR
 	out.Properties.NetworkProfile.ServiceCIDR = oc.Properties.NetworkProfile.ServiceCIDR
+	out.Properties.NetworkProfile.MTUSize = api.MTUSize(oc.Properties.NetworkProfile.MTUSize)
 	out.Properties.NetworkProfile.SoftwareDefinedNetwork = api.SoftwareDefinedNetwork(oc.Properties.NetworkProfile.SoftwareDefinedNetwork)
 	out.Properties.NetworkProfile.APIServerPrivateEndpointIP = oc.Properties.NetworkProfile.APIServerPrivateEndpointIP
 	out.Properties.NetworkProfile.GatewayPrivateEndpointIP = oc.Properties.NetworkProfile.GatewayPrivateEndpointIP
diff --git a/pkg/api/openshiftcluster.go b/pkg/api/openshiftcluster.go
index 7c8636b3a..5635fae8b 100644
--- a/pkg/api/openshiftcluster.go
+++ b/pkg/api/openshiftcluster.go
@@ -234,6 +234,15 @@ const (
 	SoftwareDefinedNetworkOpenShiftSDN  SoftwareDefinedNetwork = "OpenShiftSDN"
 )
 
+// MTUSize represents the MTU size of a cluster
+type MTUSize int
+
+// MTUSize constants
+const (
+	MTU1500 MTUSize = 1500
+	MTU3900 MTUSize = 3900
+)
+
 // NetworkProfile represents a network profile
 type NetworkProfile struct {
 	MissingFields
@@ -241,6 +250,7 @@ type NetworkProfile struct {
 	PodCIDR                string                 `json:"podCidr,omitempty"`
 	ServiceCIDR            string                 `json:"serviceCidr,omitempty"`
 	SoftwareDefinedNetwork SoftwareDefinedNetwork `json:"softwareDefinedNetwork,omitempty"`
+	MTUSize                MTUSize                `json:"mtuSize,omitempty"`
 
 	APIServerPrivateEndpointIP string `json:"privateEndpointIp,omitempty"`
 	GatewayPrivateEndpointIP   string `json:"gatewayPrivateEndpointIp,omitempty"`
diff --git a/pkg/cluster/deploystorage.go b/pkg/cluster/deploystorage.go
index db14aa07d..cb0e4a923 100644
--- a/pkg/cluster/deploystorage.go
+++ b/pkg/cluster/deploystorage.go
@@ -28,7 +28,6 @@ import (
 	"github.com/Azure/ARO-RP/pkg/cluster/graph"
 	"github.com/Azure/ARO-RP/pkg/env"
 	"github.com/Azure/ARO-RP/pkg/util/arm"
-	"github.com/Azure/ARO-RP/pkg/util/feature"
 	"github.com/Azure/ARO-RP/pkg/util/stringutils"
 	"github.com/Azure/ARO-RP/pkg/util/subnet"
 )
@@ -224,15 +223,14 @@ func (m *manager) ensureGraph(ctx context.Context, installConfig *installconfig.
 	}
 
 	// Handle MTU3900 feature flag
-	subProperties := m.subscriptionDoc.Subscription.Properties
-	if feature.IsRegisteredForFeature(subProperties, api.FeatureFlagMTU3900) {
+	if m.doc.OpenShiftCluster.Properties.NetworkProfile.MTUSize == api.MTU3900 {
 		m.log.Printf("applying feature flag %s", api.FeatureFlagMTU3900)
 		if err = m.overrideEthernetMTU(g); err != nil {
 			return err
 		}
 	}
 
-	// the graph is quite big so we store it in a storage account instead of in cosmosdb
+	// the graph is quite big, so we store it in a storage account instead of in cosmosdb
 	return m.graph.Save(ctx, resourceGroup, clusterStorageAccountName, g)
 }
 
diff --git a/pkg/cluster/install.go b/pkg/cluster/install.go
index e50ad64e0..4eb178d36 100644
--- a/pkg/cluster/install.go
+++ b/pkg/cluster/install.go
@@ -81,6 +81,7 @@ func (m *manager) adminUpdate() []steps.Step {
 			steps.Action(m.configureAPIServerCertificate),
 			steps.Action(m.configureIngressCertificate),
 			steps.Action(m.populateRegistryStorageAccountName),
+			steps.Action(m.ensureMTUSize),
 			steps.Action(m.populateCreatedAt), // TODO(mikalai): Remove after a round of admin updates
 
 		)
@@ -134,6 +135,7 @@ func (m *manager) Install(ctx context.Context) error {
 			steps.AuthorizationRefreshingAction(m.fpAuthorizer, steps.Action(m.validateResources)),
 			steps.Action(m.ensureACRToken),
 			steps.Action(m.generateSSHKey),
+			steps.Action(m.populateMTUSize),
 			steps.Action(func(ctx context.Context) error {
 				var err error
 				installConfig, image, err = m.generateInstallConfig(ctx)
diff --git a/pkg/cluster/networkprofile.go b/pkg/cluster/networkprofile.go
new file mode 100644
index 000000000..9e1878037
--- /dev/null
+++ b/pkg/cluster/networkprofile.go
@@ -0,0 +1,62 @@
+package cluster
+
+// Copyright (c) Microsoft Corporation.
+// Licensed under the Apache License 2.0.
+
+import (
+	"context"
+
+	kerrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	"github.com/Azure/ARO-RP/pkg/api"
+	"github.com/Azure/ARO-RP/pkg/util/feature"
+)
+
+// populateMTUSize ensures that every new cluster object has the MTUSize field defined
+func (m *manager) populateMTUSize(ctx context.Context) error {
+	// Get appropriate MTU size
+	mtuSize := api.MTU1500
+	subProperties := m.subscriptionDoc.Subscription.Properties
+	if feature.IsRegisteredForFeature(subProperties, api.FeatureFlagMTU3900) {
+		mtuSize = api.MTU3900
+	}
+
+	// Patch the cluster object with correct MTU size
+	return patchMTUSize(m, ctx, mtuSize)
+}
+
+// ensureMTUSize ensures that an existing cluster object has the MTUSize field defined
+func (m *manager) ensureMTUSize(ctx context.Context) error {
+	var err error
+	// Cluster needs MTUSize field patched
+	if m.doc.OpenShiftCluster.Properties.NetworkProfile.MTUSize == 0 {
+		// Get appropriate MTU size
+		mtuSize := api.MTU3900
+
+		// If a single MachineConfig is present we know the cluster has a custom MTU
+		_, err = m.mcocli.MachineconfigurationV1().MachineConfigs().Get(ctx, "99-master-mtu", metav1.GetOptions{})
+		if err != nil {
+			// If we can't find a MachineConfig this cluster never had a custom MTU on install, set to default
+			if kerrors.IsNotFound(err) {
+				mtuSize = api.MTU1500
+			} else {
+				return err
+			}
+		}
+
+		// Patch the cluster object with correct MTU size
+		err = patchMTUSize(m, ctx, mtuSize)
+	}
+	return err
+}
+
+func patchMTUSize(m *manager, ctx context.Context, mtuSize api.MTUSize) error {
+	// Patch the cluster object with correct MTU size
+	var err error
+	m.doc, err = m.db.PatchWithLease(ctx, m.doc.Key, func(doc *api.OpenShiftClusterDocument) error {
+		doc.OpenShiftCluster.Properties.NetworkProfile.MTUSize = mtuSize
+		return nil
+	})
+	return err
+}
diff --git a/pkg/deploy/predeploy.go b/pkg/deploy/predeploy.go
index 03b79d7e9..8d11943d2 100644
--- a/pkg/deploy/predeploy.go
+++ b/pkg/deploy/predeploy.go
@@ -25,9 +25,9 @@ import (
 	"github.com/Azure/ARO-RP/pkg/util/keyvault"
 )
 
-// Rotate the secret on every deploy of the RP iff the most recent
-// secret is less than 3 days old
-const rotateSecretAfter = time.Hour * 72
+// Rotate the secret on every deploy of the RP if the most recent
+// secret is greater than 7 days old
+const rotateSecretAfter = time.Hour * 168
 
 // PreDeploy deploys managed identity, NSGs and keyvaults, needed for main
 // deployment
diff --git a/pkg/mirror/graph.go b/pkg/mirror/graph.go
index f02154344..9cfd04717 100644
--- a/pkg/mirror/graph.go
+++ b/pkg/mirror/graph.go
@@ -57,13 +57,7 @@ func AddFromGraph(min *version.Version) ([]Node, error) {
 	}
 
 	releases := make([]Node, 0, len(g.Nodes))
-loop:
 	for _, node := range g.Nodes {
-		switch node.Version {
-		case "4.3.20":
-			continue loop
-		}
-
 		vsn, err := version.ParseVersion(node.Version)
 		if err != nil {
 			return nil, err
diff --git a/pkg/operator/controllers/muo/muo_controller.go b/pkg/operator/controllers/muo/muo_controller.go
index 97a3c9e86..9cef6d5a0 100644
--- a/pkg/operator/controllers/muo/muo_controller.go
+++ b/pkg/operator/controllers/muo/muo_controller.go
@@ -141,7 +141,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.
 			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)
+			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)
diff --git a/pkg/operator/deploy/deploy.go b/pkg/operator/deploy/deploy.go
index 378d16a71..b1b30cf2f 100644
--- a/pkg/operator/deploy/deploy.go
+++ b/pkg/operator/deploy/deploy.go
@@ -322,7 +322,7 @@ func (o *operator) IsReady(ctx context.Context) (bool, error) {
 
 func checkIngressIP(ingressProfiles []api.IngressProfile) (string, error) {
 	if ingressProfiles == nil || len(ingressProfiles) < 1 {
-		return "", errors.New("No Ingress Profiles found")
+		return "", errors.New("no Ingress Profiles found")
 	}
 	ingressIP := ingressProfiles[0].IP
 	if len(ingressProfiles) > 1 {
diff --git a/pkg/portal/cluster/clusteroperators.go b/pkg/portal/cluster/clusteroperators.go
index 89319a172..d293e7e2d 100644
--- a/pkg/portal/cluster/clusteroperators.go
+++ b/pkg/portal/cluster/clusteroperators.go
@@ -25,7 +25,7 @@ func clusterOperatorsInformationFromOperatorList(operators *configv1.ClusterOper
 	}
 
 	for _, co := range operators.Items {
-		var Available configv1.ConditionStatus = configv1.ConditionUnknown
+		var Available = configv1.ConditionUnknown
 
 		for _, cnd := range co.Status.Conditions {
 			if cnd.Type == "Available" {
diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go
index 6669be240..4d2890bb3 100644
--- a/pkg/proxy/proxy.go
+++ b/pkg/proxy/proxy.go
@@ -117,12 +117,12 @@ func (s Server) validateProxyRequest(w http.ResponseWriter, r *http.Request) err
 
 	if r.Method != http.MethodConnect {
 		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
-		return errors.New("Request is not valid, method is not CONNECT")
+		return errors.New("request is not valid, method is not CONNECT")
 	}
 
 	if !s.subnet.Contains(net.ParseIP(ip)) {
 		http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
-		return errors.New("Request is not allowed, the originating IP is not part of the allowed subnet")
+		return errors.New("request is not allowed, the originating IP is not part of the allowed subnet")
 	}
 
 	return nil
diff --git a/pkg/util/cluster/cluster.go b/pkg/util/cluster/cluster.go
index f5aeb329b..a5867ab6f 100644
--- a/pkg/util/cluster/cluster.go
+++ b/pkg/util/cluster/cluster.go
@@ -195,7 +195,7 @@ func (c *Cluster) Create(ctx context.Context, vnetResourceGroup, clusterName str
 		}
 
 		if result.NameAvailable != nil && !*result.NameAvailable {
-			return fmt.Errorf("Could not generate unique key vault name: %v", result.Reason)
+			return fmt.Errorf("could not generate unique key vault name: %v", result.Reason)
 		}
 	}
 
diff --git a/pkg/util/version/const.go b/pkg/util/version/const.go
index 661ff62d5..4d53141b1 100644
--- a/pkg/util/version/const.go
+++ b/pkg/util/version/const.go
@@ -4,8 +4,6 @@ package version
 // Licensed under the Apache License 2.0.
 
 import (
-	"os"
-
 	"github.com/Azure/ARO-RP/pkg/api"
 )
 
@@ -67,21 +65,11 @@ func FluentbitImage(acrDomain string) string {
 
 // MdmImage contains the location of the MDM container image
 func MdmImage(acrDomain string) string {
-	// for the latest version see https://genevamondocs.azurewebsites.net/collect/references/linuxcontainers.html?q=container
-	if os.Getenv("GENEVA_MDM_IMAGE_OVERRIDE") != "" {
-		return os.Getenv("GENEVA_MDM_IMAGE_OVERRIDE")
-	}
-
 	return acrDomain + "/genevamdm:master_20220419.1"
 }
 
 // MdsdImage contains the location of the MDSD container image
 func MdsdImage(acrDomain string) string {
-	// for the latest version see https://genevamondocs.azurewebsites.net/collect/references/linuxcontainers.html?q=container
-	if os.Getenv("GENEVA_MDSD_IMAGE_OVERRIDE") != "" {
-		return os.Getenv("GENEVA_MDSD_IMAGE_OVERRIDE")
-	}
-
 	return acrDomain + "/genevamdsd:master_20220419.1"
 }
 
diff --git a/portal/v2/package-lock.json b/portal/v2/package-lock.json
index d7c7b8648..25f5a2c94 100644
--- a/portal/v2/package-lock.json
+++ b/portal/v2/package-lock.json
@@ -4065,9 +4065,9 @@
       }
     },
     "node_modules/async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
       "dependencies": {
         "lodash": "^4.17.14"
       }
@@ -23582,9 +23582,9 @@
       "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="
     },
     "async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
       "requires": {
         "lodash": "^4.17.14"
       }


Test patch:
diff --git a/pkg/cluster/adminupdate_test.go b/pkg/cluster/adminupdate_test.go
index 52fc01893..2f3fc4212 100644
--- a/pkg/cluster/adminupdate_test.go
+++ b/pkg/cluster/adminupdate_test.go
@@ -85,6 +85,7 @@ func TestAdminUpdateSteps(t *testing.T) {
 				"[Action configureAPIServerCertificate-fm]",
 				"[Action configureIngressCertificate-fm]",
 				"[Action populateRegistryStorageAccountName-fm]",
+				"[Action ensureMTUSize-fm]",
 				"[Action populateCreatedAt-fm]",
 				"[Action ensureAROOperator-fm]",
 				"[Condition aroDeploymentReady-fm, timeout 20m0s]",
@@ -124,6 +125,7 @@ func TestAdminUpdateSteps(t *testing.T) {
 				"[Action configureAPIServerCertificate-fm]",
 				"[Action configureIngressCertificate-fm]",
 				"[Action populateRegistryStorageAccountName-fm]",
+				"[Action ensureMTUSize-fm]",
 				"[Action populateCreatedAt-fm]",
 				"[Action ensureAROOperator-fm]",
 				"[Condition aroDeploymentReady-fm, timeout 20m0s]",
diff --git a/pkg/cluster/networkprofile_test.go b/pkg/cluster/networkprofile_test.go
new file mode 100644
index 000000000..1bfc14ce9
--- /dev/null
+++ b/pkg/cluster/networkprofile_test.go
@@ -0,0 +1,298 @@
+package cluster
+
+// Copyright (c) Microsoft Corporation.
+// Licensed under the Apache License 2.0.
+
+import (
+	"context"
+	"strings"
+	"testing"
+
+	mcv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
+	mcofake "github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/fake"
+	"github.com/stretchr/testify/assert"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	"github.com/Azure/ARO-RP/pkg/api"
+	testdatabase "github.com/Azure/ARO-RP/test/database"
+)
+
+// TestPopulateMTUSize will test our populate MTUSize function
+func TestPopulateMTUSize(t *testing.T) {
+	ctx := context.Background()
+
+	// Define the DB instance we will use to run the PatchWithLease function
+	key := "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/resourceGroup/providers/Microsoft.RedHatOpenShift/openShiftClusters/resourceName"
+
+	// Run tests
+	for _, tt := range []struct {
+		name        string
+		m           manager
+		expectedMTU api.MTUSize
+		expectedErr error
+	}{
+		{
+			name: "No MTU size defined, MTU3900 flag",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+						},
+					},
+				},
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{
+									Name:  api.FeatureFlagMTU3900,
+									State: "Registered",
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU3900,
+			expectedErr: nil,
+		},
+		{
+			name: "No MTU size defined, No MTU flag",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+						},
+					},
+				},
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU1500,
+			expectedErr: nil,
+		},
+		{
+			name: "MTU1500 defined, MTU3900 flag",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+							NetworkProfile: api.NetworkProfile{
+								MTUSize: api.MTU1500,
+							},
+						},
+					},
+				},
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{
+									Name:  api.FeatureFlagMTU3900,
+									State: "Registered",
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU3900,
+			expectedErr: nil,
+		},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			// Create the DB to test the cluster
+			openShiftClustersDatabase, _ := testdatabase.NewFakeOpenShiftClusters()
+			fixture := testdatabase.NewFixture().WithOpenShiftClusters(openShiftClustersDatabase)
+			fixture.AddOpenShiftClusterDocuments(tt.m.doc)
+			err := fixture.Create()
+			if err != nil {
+				t.Fatal(err)
+			}
+			tt.m.db = openShiftClustersDatabase
+
+			// Run populateMTUSize and assert the correct results
+			err = tt.m.populateMTUSize(ctx)
+			assert.Equal(t, tt.expectedErr, err, "Unexpected error exception")
+			assert.Equal(t, tt.expectedMTU, tt.m.doc.OpenShiftCluster.Properties.NetworkProfile.MTUSize, "MTUSize was not updated as expected exception")
+		})
+	}
+}
+
+// TestEnsureMTUSize will test our ensureMTUSize function
+func TestEnsureMTUSize(t *testing.T) {
+	ctx := context.Background()
+
+	// Define the DB instance we will use to run the PatchWithLease function
+	key := "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/resourceGroup/providers/Microsoft.RedHatOpenShift/openShiftClusters/resourceName"
+
+	// Run tests
+	for _, tt := range []struct {
+		name        string
+		m           manager
+		expectedMTU api.MTUSize
+		expectedErr error
+	}{
+		{
+			name: "MTUSize set to 1500",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+							NetworkProfile: api.NetworkProfile{
+								MTUSize: api.MTU1500,
+							},
+						},
+					},
+				},
+				mcocli: mcofake.NewSimpleClientset(
+					&mcv1.MachineConfig{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "master",
+						},
+					}),
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU1500,
+			expectedErr: nil,
+		},
+		{
+			name: "MTUSize set to 3900",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+							NetworkProfile: api.NetworkProfile{
+								MTUSize: api.MTU3900,
+							},
+						},
+					},
+				},
+				mcocli: mcofake.NewSimpleClientset(
+					&mcv1.MachineConfig{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "master",
+						},
+					}),
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU3900,
+			expectedErr: nil,
+		},
+		{
+			name: "No MTUSize & MachineConfig found",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+						},
+					},
+				},
+				mcocli: mcofake.NewSimpleClientset(
+					&mcv1.MachineConfig{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "99-master-mtu",
+						},
+					}),
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU3900,
+			expectedErr: nil,
+		},
+		{
+			name: "No MTUSize & MachineConfig not found",
+			m: manager{
+				doc: &api.OpenShiftClusterDocument{
+					Key: strings.ToLower(key),
+					OpenShiftCluster: &api.OpenShiftCluster{
+						ID: key,
+						Properties: api.OpenShiftClusterProperties{
+							ProvisioningState: api.ProvisioningStateSucceeded,
+						},
+					},
+				},
+				mcocli: mcofake.NewSimpleClientset(
+					&mcv1.MachineConfig{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "master",
+						},
+					}),
+				subscriptionDoc: &api.SubscriptionDocument{
+					Subscription: &api.Subscription{
+						Properties: &api.SubscriptionProperties{
+							RegisteredFeatures: []api.RegisteredFeatureProfile{
+								{},
+							},
+						},
+					},
+				},
+			},
+			expectedMTU: api.MTU1500,
+			expectedErr: nil,
+		},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			// Create the DB to test the cluster
+			openShiftClustersDatabase, _ := testdatabase.NewFakeOpenShiftClusters()
+			fixture := testdatabase.NewFixture().WithOpenShiftClusters(openShiftClustersDatabase)
+			fixture.AddOpenShiftClusterDocuments(tt.m.doc)
+			err := fixture.Create()
+			if err != nil {
+				t.Fatal(err)
+			}
+			tt.m.db = openShiftClustersDatabase
+
+			err = tt.m.ensureMTUSize(ctx)
+
+			assert.Equal(t, tt.expectedErr, err, "Unexpected error exception")
+			assert.Equal(t, tt.expectedMTU, tt.m.doc.OpenShiftCluster.Properties.NetworkProfile.MTUSize, "MTUSize was not updated as expected exception")
+		})
+	}
+}
diff --git a/pkg/operator/controllers/muo/muo_controller_test.go b/pkg/operator/controllers/muo/muo_controller_test.go
index 4a81a405f..e88119496 100644
--- a/pkg/operator/controllers/muo/muo_controller_test.go
+++ b/pkg/operator/controllers/muo/muo_controller_test.go
@@ -174,7 +174,7 @@ func TestMUOReconciler(t *testing.T) {
 				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
 				md.EXPECT().IsReady(gomock.Any()).Return(false, nil)
 			},
-			wantErr: "Managed Upgrade Operator deployment timed out on Ready: timed out waiting for the condition",
+			wantErr: "managed Upgrade Operator deployment timed out on Ready: timed out waiting for the condition",
 		},
 		{
 			name: "managed, CreateOrUpdate() fails",
diff --git a/pkg/operator/deploy/deploy_test.go b/pkg/operator/deploy/deploy_test.go
index 3241a878a..5b1268653 100644
--- a/pkg/operator/deploy/deploy_test.go
+++ b/pkg/operator/deploy/deploy_test.go
@@ -100,7 +100,7 @@ func TestCheckIngressIP(t *testing.T) {
 				}
 			},
 			want:    "",
-			wantErr: errors.New("No Ingress Profiles found"),
+			wantErr: errors.New("no Ingress Profiles found"),
 		},
 		{
 			name: "Nil IngressProfiles, Error",
@@ -108,7 +108,7 @@ func TestCheckIngressIP(t *testing.T) {
 				return &api.OpenShiftClusterProperties{}
 			},
 			want:    "",
-			wantErr: errors.New("No Ingress Profiles found"),
+			wantErr: errors.New("no Ingress Profiles found"),
 		},
 	} {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/util/conditions/condition_test.go b/pkg/util/conditions/condition_test.go
index 4b46e6fd6..98ab56992 100644
--- a/pkg/util/conditions/condition_test.go
+++ b/pkg/util/conditions/condition_test.go
@@ -27,7 +27,7 @@ func TestSetCondition(t *testing.T) {
 	version := "unknown"
 
 	kubeclock = &clock.FakeClock{}
-	var transitionTime metav1.Time = metav1.Time{Time: kubeclock.Now()}
+	var transitionTime = metav1.Time{Time: kubeclock.Now()}
 
 	for _, tt := range []struct {
 		name      string
diff --git a/test/database/openshiftclusters.go b/test/database/openshiftclusters.go
index f3df28b0d..ff5eb4f40 100644
--- a/test/database/openshiftclusters.go
+++ b/test/database/openshiftclusters.go
@@ -177,7 +177,7 @@ func (i *fakeOpenShiftClustersQueueLengthIterator) Next(ctx context.Context, max
 
 func (i *fakeOpenShiftClustersQueueLengthIterator) NextRaw(ctx context.Context, continuation int, out interface{}) error {
 	if i.called {
-		return errors.New("Can't call twice!")
+		return errors.New("can't call twice")
 	}
 	i.called = true
 
diff --git a/test/e2e/adminapi_cluster_update.go b/test/e2e/adminapi_cluster_update.go
index 5d4afcfd3..48d65e24e 100644
--- a/test/e2e/adminapi_cluster_update.go
+++ b/test/e2e/adminapi_cluster_update.go
@@ -21,7 +21,7 @@ var _ = Describe("[Admin API] Cluster admin update action", func() {
 	BeforeEach(skipIfNotInDevelopmentEnv)
 
 	It("should be able to run cluster update operation on a cluster", func() {
-		var oc *admin.OpenShiftCluster = &admin.OpenShiftCluster{}
+		var oc = &admin.OpenShiftCluster{}
 		ctx := context.Background()
 		resourceID := resourceIDFromEnv()
 
diff --git a/test/util/project/project.go b/test/util/project/project.go
index d9f58d61e..dc135028f 100644
--- a/test/util/project/project.go
+++ b/test/util/project/project.go
@@ -60,11 +60,11 @@ func (p Project) Verify(ctx context.Context) error {
 
 	sa, err := p.cli.CoreV1().ServiceAccounts(p.name).Get(ctx, "default", metav1.GetOptions{})
 	if err != nil || kerrors.IsNotFound(err) {
-		return fmt.Errorf("Error retrieving default ServiceAccount")
+		return fmt.Errorf("error retrieving default ServiceAccount")
 	}
 
 	if len(sa.Secrets) == 0 {
-		return fmt.Errorf("Default ServiceAccount does not have secrets")
+		return fmt.Errorf("default ServiceAccount does not have secrets")
 	}
 
 	proj, err := p.projectClient.ProjectV1().Projects().Get(ctx, p.name, metav1.GetOptions{})