github.com/ironcore-dev/gardener-extension-provider-ironcore@v0.3.2-0.20240314231816-8336447fb9a0/pkg/webhook/cloudprovider/ensurer.go (about)

     1  // SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package cloudprovider
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/gardener/gardener/extensions/pkg/webhook/cloudprovider"
    11  	gcontext "github.com/gardener/gardener/extensions/pkg/webhook/context"
    12  	"github.com/go-logr/logr"
    13  	corev1 "k8s.io/api/core/v1"
    14  	"k8s.io/apimachinery/pkg/runtime"
    15  	"k8s.io/apimachinery/pkg/runtime/serializer"
    16  	clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest"
    17  	clientcmdv1 "k8s.io/client-go/tools/clientcmd/api/v1"
    18  	"sigs.k8s.io/controller-runtime/pkg/client"
    19  	"sigs.k8s.io/controller-runtime/pkg/manager"
    20  
    21  	apisironcore "github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/apis/ironcore"
    22  	"github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/ironcore"
    23  )
    24  
    25  // NewEnsurer creates cloudprovider ensurer.
    26  func NewEnsurer(logger logr.Logger, mgr manager.Manager) cloudprovider.Ensurer {
    27  	return &ensurer{
    28  		logger:  logger,
    29  		client:  mgr.GetClient(),
    30  		decoder: serializer.NewCodecFactory(mgr.GetScheme(), serializer.EnableStrict).UniversalDecoder(),
    31  	}
    32  }
    33  
    34  type ensurer struct {
    35  	logger  logr.Logger
    36  	client  client.Client
    37  	decoder runtime.Decoder
    38  }
    39  
    40  // EnsureCloudProviderSecret ensures that cloudprovider secret contains
    41  // the shared credentials file.
    42  func (e *ensurer) EnsureCloudProviderSecret(ctx context.Context, gctx gcontext.GardenContext, newCloudProviderSecret, _ *corev1.Secret) error {
    43  	token, ok := newCloudProviderSecret.Data[ironcore.TokenFieldName]
    44  	if !ok {
    45  		return fmt.Errorf("could not mutate cloudprovider secret as %q field is missing", ironcore.TokenFieldName)
    46  	}
    47  	namespace, ok := newCloudProviderSecret.Data[ironcore.NamespaceFieldName]
    48  	if !ok {
    49  		return fmt.Errorf("could not mutate cloudprovider secret as %q field is missing", ironcore.NamespaceFieldName)
    50  	}
    51  	username, ok := newCloudProviderSecret.Data[ironcore.UsernameFieldName]
    52  	if !ok {
    53  		return fmt.Errorf("could not mutate cloud provider secret as %q fied is missing", ironcore.UsernameFieldName)
    54  	}
    55  
    56  	cluster, err := gctx.GetCluster(ctx)
    57  	if err != nil {
    58  		return fmt.Errorf("failed to get cluster: %w", err)
    59  	}
    60  
    61  	cloudProfileConfig := &apisironcore.CloudProfileConfig{}
    62  	raw, err := cluster.CloudProfile.Spec.ProviderConfig.MarshalJSON()
    63  	if err != nil {
    64  		return fmt.Errorf("could not decode cluster object's providerConfig: %w", err)
    65  	}
    66  	if _, _, err := e.decoder.Decode(raw, nil, cloudProfileConfig); err != nil {
    67  		return fmt.Errorf("could not decode cluster object's providerConfig: %w", err)
    68  	}
    69  
    70  	kubeconfig := &clientcmdv1.Config{
    71  		CurrentContext: cluster.Shoot.Spec.Region,
    72  		Clusters: []clientcmdv1.NamedCluster{{
    73  			Name: cluster.Shoot.Spec.Region,
    74  		}},
    75  		AuthInfos: []clientcmdv1.NamedAuthInfo{{
    76  			Name: string(username),
    77  			AuthInfo: clientcmdv1.AuthInfo{
    78  				Token: string(token),
    79  			},
    80  		}},
    81  		Contexts: []clientcmdv1.NamedContext{{
    82  			Name: cluster.Shoot.Spec.Region,
    83  			Context: clientcmdv1.Context{
    84  				Cluster:   cluster.Shoot.Spec.Region,
    85  				AuthInfo:  string(username),
    86  				Namespace: string(namespace),
    87  			},
    88  		}},
    89  	}
    90  
    91  	var regionFound bool
    92  	for _, region := range cloudProfileConfig.RegionConfigs {
    93  		if region.Name == cluster.Shoot.Spec.Region {
    94  			kubeconfig.Clusters[0].Cluster.Server = region.Server
    95  			kubeconfig.Clusters[0].Cluster.CertificateAuthorityData = region.CertificateAuthorityData
    96  			regionFound = true
    97  			break
    98  		}
    99  	}
   100  	if !regionFound {
   101  		return fmt.Errorf("faild to find region %s in cloudprofile", cluster.Shoot.Spec.Region)
   102  	}
   103  
   104  	raw, err = runtime.Encode(clientcmdlatest.Codec, kubeconfig)
   105  	if err != nil {
   106  		return fmt.Errorf("failed to encode kubeconfig: %w", err)
   107  	}
   108  
   109  	newCloudProviderSecret.Data[ironcore.KubeConfigFieldName] = raw
   110  	return nil
   111  }