github.com/verrazzano/verrazzano@v1.7.1/cluster-operator/controllers/vmc/push_manifest_objects.go (about) 1 // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package vmc 5 6 import ( 7 "context" 8 "fmt" 9 clusterapi "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1" 10 internalcapi "github.com/verrazzano/verrazzano/cluster-operator/internal/capi" 11 constants2 "github.com/verrazzano/verrazzano/pkg/constants" 12 "github.com/verrazzano/verrazzano/pkg/k8sutil" 13 "github.com/verrazzano/verrazzano/pkg/rancherutil" 14 "github.com/verrazzano/verrazzano/platform-operator/constants" 15 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/common" 16 corev1 "k8s.io/api/core/v1" 17 "k8s.io/apimachinery/pkg/api/errors" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 20 "k8s.io/apimachinery/pkg/types" 21 ctrl "sigs.k8s.io/controller-runtime" 22 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 23 ) 24 25 // pushManifestObjects applies the Verrazzano manifest objects to the managed cluster. 26 // To access the managed cluster, we are taking advantage of the Rancher proxy or CAPI based access. 27 func (r *VerrazzanoManagedClusterReconciler) pushManifestObjects(ctx context.Context, rancherEnabled bool, vmc *clusterapi.VerrazzanoManagedCluster) (bool, error) { 28 pushed := false 29 var err error 30 if vmc.Status.ClusterRef != nil { 31 pushed, err = r.pushViaCAPIClient(ctx, vmc, rancherEnabled) 32 if err != nil { 33 return pushed, err 34 } 35 } 36 if !pushed && rancherEnabled { 37 pushed, err = r.pushViaRancherProxy(vmc) 38 if err != nil { 39 return pushed, err 40 } 41 } 42 return pushed, nil 43 } 44 45 func (r *VerrazzanoManagedClusterReconciler) pushViaRancherProxy(vmc *clusterapi.VerrazzanoManagedCluster) (bool, error) { 46 clusterID := vmc.Status.RancherRegistration.ClusterID 47 if len(clusterID) == 0 { 48 r.log.Progressf("Waiting to push manifest objects, Rancher ClusterID not found in the VMC %s/%s status", vmc.GetNamespace(), vmc.GetName()) 49 return false, nil 50 } 51 rc, err := rancherutil.NewVerrazzanoClusterRancherConfig(r.Client, r.RancherIngressHost, r.log) 52 if err != nil || rc == nil { 53 return false, err 54 } 55 56 // If the managed cluster is not active, we should not attempt to push resources 57 isActive, err := isManagedClusterActiveInRancher(rc, clusterID, r.log) 58 if err != nil { 59 return false, err 60 } 61 62 vsNamespaceCreated, _ := isNamespaceCreated(vmc, r, clusterID, constants.VerrazzanoSystemNamespace) 63 if isActive && vsNamespaceCreated { 64 65 // Create or Update the agent and registration secrets 66 agentSecret := corev1.Secret{} 67 agentSecret.Namespace = constants.VerrazzanoSystemNamespace 68 agentSecret.Name = constants.MCAgentSecret 69 regSecret := corev1.Secret{} 70 regSecret.Namespace = constants.VerrazzanoSystemNamespace 71 regSecret.Name = constants.MCRegistrationSecret 72 agentOperation, err := createOrUpdateSecretRancherProxy(&agentSecret, rc, clusterID, func() error { 73 existingAgentSec, err := r.getSecret(vmc.Namespace, GetAgentSecretName(vmc.Name), true) 74 if err != nil { 75 return err 76 } 77 agentSecret.Data = existingAgentSec.Data 78 return nil 79 }, r.log) 80 if err != nil { 81 return false, err 82 } 83 regOperation, err := createOrUpdateSecretRancherProxy(®Secret, rc, clusterID, func() error { 84 existingRegSecret, err := r.getSecret(vmc.Namespace, GetRegistrationSecretName(vmc.Name), true) 85 if err != nil { 86 return err 87 } 88 regSecret.Data = existingRegSecret.Data 89 return nil 90 }, r.log) 91 if err != nil { 92 return false, err 93 } 94 agentModified := agentOperation != controllerutil.OperationResultNone 95 regModified := regOperation != controllerutil.OperationResultNone 96 return agentModified || regModified, nil 97 } 98 return false, nil 99 } 100 101 func (r *VerrazzanoManagedClusterReconciler) pushViaCAPIClient(ctx context.Context, vmc *clusterapi.VerrazzanoManagedCluster, rancherEnabled bool) (bool, error) { 102 r.log.Debugf("Pushing via CAPI client, status: %s", vmc.Status.RancherRegistration.Status) 103 if vmc.Status.RancherRegistration.Status != clusterapi.RegistrationApplied { 104 cluster := &unstructured.Unstructured{} 105 cluster.SetGroupVersionKind(internalcapi.GVKCAPICluster) 106 err := r.Get(ctx, types.NamespacedName{Namespace: vmc.Status.ClusterRef.Namespace, Name: vmc.Status.ClusterRef.Name}, cluster) 107 if err != nil && !errors.IsNotFound(err) { 108 return false, err 109 } 110 manifest, err := r.getClusterManifest(cluster) 111 if err != nil { 112 return false, err 113 } 114 // register the cluster if Verrazzano installed on workload cluster 115 workloadClient, err := r.getWorkloadClusterClient(cluster) 116 if err != nil { 117 r.log.Errorf("Error getting workload cluster %s client: %v", cluster.GetName(), err) 118 return false, err 119 } 120 121 // apply the manifest to workload cluster 122 yamlApplier := k8sutil.NewYAMLApplier(workloadClient, "") 123 err = yamlApplier.ApplyS(string(manifest)) 124 if err != nil { 125 r.log.Errorf("Failed applying cluster manifest to workload cluster %s: %v", cluster.GetName(), err) 126 return false, err 127 } 128 r.log.Infof("Registration manifest applied to cluster %s", cluster.GetName()) 129 130 // update the registration status if Rancher is enabled since repeated application of the manifest will 131 // trigger connection issues 132 if rancherEnabled && vmc.Status.RancherRegistration.Status == clusterapi.RegistrationCompleted { 133 existingVMC := &clusterapi.VerrazzanoManagedCluster{} 134 err = r.Get(ctx, types.NamespacedName{Namespace: vmc.Namespace, Name: vmc.Name}, existingVMC) 135 if err != nil { 136 return false, err 137 } 138 existingVMC.Status.RancherRegistration.Status = clusterapi.RegistrationApplied 139 err = r.Status().Update(ctx, existingVMC) 140 if err != nil { 141 r.log.Errorf("Error updating VMC status for cluster %s: %v", cluster.GetName(), err) 142 return false, err 143 } 144 r.log.Debugf("Registration status updated to Applied") 145 vmc = existingVMC 146 147 // get and label the cattle-system namespace 148 ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: common.CattleSystem}} 149 if _, err := ctrl.CreateOrUpdate(ctx, workloadClient, ns, func() error { 150 if ns.Labels == nil { 151 ns.Labels = make(map[string]string) 152 } 153 ns.Labels[constants2.LabelVerrazzanoNamespace] = common.CattleSystem 154 return nil 155 }); err != nil { 156 return false, err 157 } 158 } 159 return true, nil 160 } 161 return false, nil 162 } 163 164 // getClusterManifest retrieves the registration manifest for the workload cluster 165 func (r *VerrazzanoManagedClusterReconciler) getClusterManifest(cluster *unstructured.Unstructured) ([]byte, error) { 166 // retrieve the manifest for the workload cluster 167 resourceName := getClusterResourceName(cluster, r.Client) 168 manifestSecret := &corev1.Secret{} 169 err := r.Get(context.TODO(), types.NamespacedName{ 170 Name: fmt.Sprintf("verrazzano-cluster-%s-manifest", resourceName), 171 Namespace: constants.VerrazzanoMultiClusterNamespace}, 172 manifestSecret) 173 if err != nil { 174 return nil, err 175 } 176 manifest, ok := manifestSecret.Data["yaml"] 177 if !ok { 178 return nil, fmt.Errorf("Error retrieving cluster manifest for %s", cluster.GetName()) 179 } 180 return manifest, nil 181 }