Repository: Azure/ARO-RP
Pull request #2025 (2022-03-24 23:37:17)

Enable Managed Upgrade Operator on new clusters
### Which issue this PR addresses:

Fixes https://msazure.visualstudio.com/AzureRedHatOpenShift/_workitems/edit/13776942

### What this PR does / why we need it:

Enables MUO on new clusters with a default pullspec.

### Test plan for issue:

Unit tests + an E2E test

### Is there any documentation that needs to be updated for this PR?

N/A



Patch:
diff --git a/pkg/api/defaults.go b/pkg/api/defaults.go
index c468f4bff..7adae0932 100644
--- a/pkg/api/defaults.go
+++ b/pkg/api/defaults.go
@@ -77,5 +77,7 @@ func DefaultOperatorFlags() OperatorFlags {
 		"aro.storageaccounts.enabled":              flagTrue,
 		"aro.workaround.enabled":                   flagTrue,
 		"aro.autosizednodes.enable":                flagFalse,
+		"rh.srep.muo.enabled":                      flagTrue,
+		"rh.srep.muo.managed":                      flagTrue,
 	}
 }
diff --git a/pkg/operator/controllers/muo/muo_controller.go b/pkg/operator/controllers/muo/muo_controller.go
index c3190f73c..61d2ccb8b 100644
--- a/pkg/operator/controllers/muo/muo_controller.go
+++ b/pkg/operator/controllers/muo/muo_controller.go
@@ -5,7 +5,6 @@ package muo
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"strings"
 	"time"
@@ -26,6 +25,7 @@ import (
 	"github.com/Azure/ARO-RP/pkg/operator/controllers/muo/config"
 	"github.com/Azure/ARO-RP/pkg/util/dynamichelper"
 	"github.com/Azure/ARO-RP/pkg/util/pullsecret"
+	"github.com/Azure/ARO-RP/pkg/util/version"
 )
 
 const (
@@ -86,13 +86,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.
 	// If enabled and managed=false, remove the MUO deployment
 	// If enabled and managed is missing, do nothing
 	if strings.EqualFold(managed, "true") {
-		imagePullspec, ext := instance.Spec.OperatorFlags[controllerPullSpec]
-		if !ext {
-			return reconcile.Result{}, errors.New("missing pullspec")
+		// apply the default pullspec if the flag is empty or missing
+		pullSpec := instance.Spec.OperatorFlags.GetWithDefault(controllerPullSpec, "")
+		if pullSpec == "" {
+			pullSpec = version.MUOImage(instance.Spec.ACRDomain)
 		}
 
 		config := &config.MUODeploymentConfig{
-			Pullspec: imagePullspec,
+			Pullspec: pullSpec,
 		}
 
 		allowOCM := instance.Spec.OperatorFlags.GetSimpleBoolean(controllerAllowOCM)
diff --git a/pkg/util/version/const.go b/pkg/util/version/const.go
index acd892cb1..54f239217 100644
--- a/pkg/util/version/const.go
+++ b/pkg/util/version/const.go
@@ -84,3 +84,8 @@ func MdsdImage(acrDomain string) string {
 
 	return acrDomain + "/genevamdsd:master_20211223.1"
 }
+
+// MUOImage contains the location of the Managed Upgrade Operator container image
+func MUOImage(acrDomain string) string {
+	return acrDomain + "/managed-upgrade-operator:aro-b1"
+}


Test patch:
diff --git a/pkg/operator/controllers/muo/muo_controller_test.go b/pkg/operator/controllers/muo/muo_controller_test.go
index c5e6d07f9..4a3b007db 100644
--- a/pkg/operator/controllers/muo/muo_controller_test.go
+++ b/pkg/operator/controllers/muo/muo_controller_test.go
@@ -55,15 +55,38 @@ func TestMUOReconciler(t *testing.T) {
 			},
 		},
 		{
-			name: "managed, no pullspec",
+			name: "managed, no pullspec (uses default)",
 			flags: arov1alpha1.OperatorFlags{
 				controllerEnabled: "true",
 				controllerManaged: "true",
 			},
-			wantErr: "missing pullspec",
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
+				expectedConfig := &config.MUODeploymentConfig{
+					Pullspec: "acrtest.example.com/managed-upgrade-operator:aro-b1",
+				}
+				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
+			},
+		},
+		{
+			name: "managed, OCM allowed but pull secret entirely missing",
+			flags: arov1alpha1.OperatorFlags{
+				controllerEnabled:  "true",
+				controllerManaged:  "true",
+				controllerAllowOCM: "true",
+				controllerPullSpec: "wonderfulPullspec",
+			},
+			mocks: func(md *mock_muo.MockDeployer, cluster *arov1alpha1.Cluster) {
+				expectedConfig := &config.MUODeploymentConfig{
+					Pullspec:        "wonderfulPullspec",
+					EnableConnected: false,
+				}
+				md.EXPECT().CreateOrUpdate(gomock.Any(), cluster, expectedConfig).Return(nil)
+				md.EXPECT().IsReady(gomock.Any()).Return(true, nil)
+			},
 		},
 		{
-			name: "managed, OCM allowed but no pull secret",
+			name: "managed, OCM allowed but empty pullsecret",
 			flags: arov1alpha1.OperatorFlags{
 				controllerEnabled:  "true",
 				controllerManaged:  "true",
@@ -208,6 +231,7 @@ func TestMUOReconciler(t *testing.T) {
 				},
 				Spec: arov1alpha1.ClusterSpec{
 					OperatorFlags: tt.flags,
+					ACRDomain:     "acrtest.example.com",
 				},
 			}
 			arocli := arofake.NewSimpleClientset(cluster)
diff --git a/test/e2e/operator.go b/test/e2e/operator.go
index c7fb97417..6cd90b4b8 100644
--- a/test/e2e/operator.go
+++ b/test/e2e/operator.go
@@ -417,3 +417,31 @@ var _ = Describe("ARO Operator - Azure Subnet Reconciler", func() {
 		}
 	})
 })
+
+var _ = Describe("ARO Operator - MUO Deployment", func() {
+	ctx := context.Background()
+
+	Specify("MUO should be deployed by default", func() {
+		muoIsDeployed := func() (bool, error) {
+			pods, err := clients.Kubernetes.CoreV1().Pods("openshift-managed-upgrade-operator").List(ctx, metav1.ListOptions{
+				LabelSelector: "name=managed-upgrade-operator",
+			})
+			if err != nil {
+				return false, err
+			}
+			if len(pods.Items) != 1 {
+				return false, fmt.Errorf("%d managed-upgrade-operator pods found", len(pods.Items))
+			}
+			b, err := clients.Kubernetes.CoreV1().Pods("openshift-managed-upgrade-operator").GetLogs(pods.Items[0].Name, &corev1.PodLogOptions{}).DoRaw(ctx)
+			if err != nil {
+				return false, err
+			}
+
+			// check for mandated FIPS
+			return strings.Contains(string(b), `msg="FIPS crypto mandated: true"`), nil
+		}
+
+		err := wait.PollImmediate(30*time.Second, 10*time.Minute, muoIsDeployed)
+		Expect(err).NotTo(HaveOccurred())
+	})
+})