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  }