sigs.k8s.io/cluster-api-provider-azure@v1.14.3/controllers/azuremanagedcontrolplane_reconciler.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package controllers 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/pkg/errors" 24 "k8s.io/client-go/tools/clientcmd" 25 "sigs.k8s.io/cluster-api-provider-azure/azure" 26 "sigs.k8s.io/cluster-api-provider-azure/azure/scope" 27 "sigs.k8s.io/cluster-api-provider-azure/azure/services/aksextensions" 28 "sigs.k8s.io/cluster-api-provider-azure/azure/services/fleetsmembers" 29 "sigs.k8s.io/cluster-api-provider-azure/azure/services/groups" 30 "sigs.k8s.io/cluster-api-provider-azure/azure/services/managedclusters" 31 "sigs.k8s.io/cluster-api-provider-azure/azure/services/privateendpoints" 32 "sigs.k8s.io/cluster-api-provider-azure/azure/services/resourcehealth" 33 "sigs.k8s.io/cluster-api-provider-azure/azure/services/subnets" 34 "sigs.k8s.io/cluster-api-provider-azure/azure/services/virtualnetworks" 35 "sigs.k8s.io/cluster-api-provider-azure/util/tele" 36 "sigs.k8s.io/cluster-api/util/secret" 37 "sigs.k8s.io/controller-runtime/pkg/client" 38 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 39 ) 40 41 // azureManagedControlPlaneService contains the services required by the cluster controller. 42 type azureManagedControlPlaneService struct { 43 kubeclient client.Client 44 scope managedclusters.ManagedClusterScope 45 services []azure.ServiceReconciler 46 } 47 48 // newAzureManagedControlPlaneReconciler populates all the services based on input scope. 49 func newAzureManagedControlPlaneReconciler(scope *scope.ManagedControlPlaneScope) (*azureManagedControlPlaneService, error) { 50 resourceHealthSvc, err := resourcehealth.New(scope) 51 if err != nil { 52 return nil, err 53 } 54 return &azureManagedControlPlaneService{ 55 kubeclient: scope.Client, 56 scope: scope, 57 services: []azure.ServiceReconciler{ 58 groups.New(scope), 59 virtualnetworks.New(scope), 60 subnets.New(scope), 61 managedclusters.New(scope), 62 privateendpoints.New(scope), 63 fleetsmembers.New(scope), 64 aksextensions.New(scope), 65 resourceHealthSvc, 66 }, 67 }, nil 68 } 69 70 // Reconcile reconciles all the services in a predetermined order. 71 func (r *azureManagedControlPlaneService) Reconcile(ctx context.Context) error { 72 ctx, _, done := tele.StartSpanWithLogger(ctx, "controllers.azureManagedControlPlaneService.Reconcile") 73 defer done() 74 75 for _, service := range r.services { 76 if err := service.Reconcile(ctx); err != nil { 77 return errors.Wrapf(err, "failed to reconcile AzureManagedControlPlane service %s", service.Name()) 78 } 79 } 80 81 if err := r.reconcileKubeconfig(ctx); err != nil { 82 return errors.Wrap(err, "failed to reconcile kubeconfig secret") 83 } 84 85 return nil 86 } 87 88 // Pause pauses all components making up the cluster. 89 func (r *azureManagedControlPlaneService) Pause(ctx context.Context) error { 90 ctx, _, done := tele.StartSpanWithLogger(ctx, "controllers.azureManagedControlPlaneService.Pause") 91 defer done() 92 93 for _, service := range r.services { 94 pauser, ok := service.(azure.Pauser) 95 if !ok { 96 continue 97 } 98 if err := pauser.Pause(ctx); err != nil { 99 return errors.Wrapf(err, "failed to pause AzureManagedControlPlane service %s", service.Name()) 100 } 101 } 102 103 return nil 104 } 105 106 // Delete reconciles all the services in a predetermined order. 107 func (r *azureManagedControlPlaneService) Delete(ctx context.Context) error { 108 ctx, _, done := tele.StartSpanWithLogger(ctx, "controllers.azureManagedControlPlaneService.Delete") 109 defer done() 110 111 // Delete services in reverse order of creation. 112 for i := len(r.services) - 1; i >= 0; i-- { 113 if err := r.services[i].Delete(ctx); err != nil { 114 return errors.Wrapf(err, "failed to delete AzureManagedControlPlane service %s", r.services[i].Name()) 115 } 116 } 117 118 return nil 119 } 120 121 func (r *azureManagedControlPlaneService) reconcileKubeconfig(ctx context.Context) error { 122 ctx, _, done := tele.StartSpanWithLogger(ctx, "controllers.azureManagedControlPlaneService.reconcileKubeconfig") 123 defer done() 124 125 kubeConfigs := [][]byte{r.scope.GetAdminKubeconfigData(), r.scope.GetUserKubeconfigData()} 126 127 for i, kubeConfigData := range kubeConfigs { 128 if len(kubeConfigData) == 0 { 129 continue 130 } 131 kubeConfigSecret := r.scope.MakeEmptyKubeConfigSecret() 132 if i == 1 { 133 // 2nd kubeconfig is the user kubeconfig 134 kubeConfigSecret.Name = fmt.Sprintf("%s-user", kubeConfigSecret.Name) 135 } 136 if _, err := controllerutil.CreateOrUpdate(ctx, r.kubeclient, &kubeConfigSecret, func() error { 137 kubeConfigSecret.Data = map[string][]byte{ 138 secret.KubeconfigDataName: kubeConfigData, 139 } 140 return nil 141 }); err != nil { 142 return errors.Wrap(err, "failed to reconcile kubeconfig secret for cluster") 143 } 144 } 145 146 // store cluster-info for the cluster with the admin kubeconfig. 147 kubeconfigFile, err := clientcmd.Load(kubeConfigs[0]) 148 if err != nil { 149 return errors.Wrap(err, "failed to turn aks credentials into kubeconfig file struct") 150 } 151 152 cluster := kubeconfigFile.Contexts[kubeconfigFile.CurrentContext].Cluster 153 caData := kubeconfigFile.Clusters[cluster].CertificateAuthorityData 154 caSecret := r.scope.MakeClusterCA() 155 if _, err := controllerutil.CreateOrUpdate(ctx, r.kubeclient, caSecret, func() error { 156 caSecret.Data = map[string][]byte{ 157 secret.TLSCrtDataName: caData, 158 secret.TLSKeyDataName: []byte("foo"), 159 } 160 return nil 161 }); err != nil { 162 return errors.Wrapf(err, "failed to reconcile certificate authority data secret for cluster") 163 } 164 165 if err := r.scope.StoreClusterInfo(ctx, caData); err != nil { 166 return errors.Wrap(err, "failed to construct cluster-info") 167 } 168 169 return nil 170 }