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 }