diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index a8e1b31d..75e8b720 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -42,10 +42,8 @@ type ( ) const ( - // Provider CAPA + // Provider AWS ProviderAWSName = "cluster-api-provider-aws" - // Provider Azure - ProviderAzureName = "cluster-api-provider-azure" // Provider vSphere ProviderVSphereName = "cluster-api-provider-vsphere" // Provider OpenStack diff --git a/api/v1alpha1/management_types.go b/api/v1alpha1/management_types.go index 618c5d19..a1272f7b 100644 --- a/api/v1alpha1/management_types.go +++ b/api/v1alpha1/management_types.go @@ -86,6 +86,10 @@ type Provider struct { Name string `json:"name"` } +func (p Provider) String() string { + return p.Name +} + func (in *Component) HelmValues() (values map[string]any, err error) { if in.Config != nil { err = yaml.Unmarshal(in.Config.Raw, &values) @@ -93,17 +97,6 @@ func (in *Component) HelmValues() (values map[string]any, err error) { return values, err } -func GetDefaultProviders() []Provider { - return []Provider{ - {Name: ProviderK0smotronName}, - {Name: ProviderAWSName}, - {Name: ProviderAzureName}, - {Name: ProviderVSphereName}, - {Name: ProviderOpenStackName}, - {Name: ProviderSveltosName}, - } -} - // Templates returns a list of provider templates explicitly defined in the Management object func (in *Management) Templates() []string { templates := []string{} diff --git a/cmd/main.go b/cmd/main.go index 66e6f88c..99759592 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -31,7 +31,6 @@ import ( "k8s.io/client-go/dynamic" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" - capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" capv "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" ctrl "sigs.k8s.io/controller-runtime" @@ -69,7 +68,6 @@ func init() { utilruntime.Must(sourcev1.AddToScheme(scheme)) utilruntime.Must(hcv2.AddToScheme(scheme)) utilruntime.Must(sveltosv1beta1.AddToScheme(scheme)) - utilruntime.Must(capz.AddToScheme(scheme)) utilruntime.Must(capv.AddToScheme(scheme)) utilruntime.Must(capo.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme diff --git a/config/dev/azure-credentials.yaml b/config/dev/azure-credentials.yaml index e3c72f4e..77e7a9d6 100644 --- a/config/dev/azure-credentials.yaml +++ b/config/dev/azure-credentials.yaml @@ -41,3 +41,57 @@ spec: kind: AzureClusterIdentity name: azure-cluster-identity namespace: ${NAMESPACE} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: azure-cluster-identity-resource-template + namespace: ${NAMESPACE} + annotations: + projectsveltos.io/template: "true" +data: + configmap.yaml: | + {{- $$cluster := .InfrastructureProvider -}} + {{- $$identity := (getResource "InfrastructureProviderIdentity") -}} + {{- $$secret := (getResource "InfrastructureProviderIdentitySecret") -}} + {{- $$subnetName := "" -}} + {{- $$securityGroupName := "" -}} + {{- $$routeTableName := "" -}} + {{- range $$cluster.spec.networkSpec.subnets -}} + {{- if eq .role "node" -}} + {{- $$subnetName = .name -}} + {{- $$securityGroupName = .securityGroup.name -}} + {{- $$routeTableName = .routeTable.name -}} + {{- break -}} + {{- end -}} + {{- end -}} + {{- $$cloudConfig := dict + "aadClientId" $$identity.spec.clientID + "aadClientSecret" (index $$secret.data "clientSecret" | b64dec) + "cloud" $$cluster.spec.azureEnvironment + "loadBalancerName" "" + "loadBalancerSku" "Standard" + "location" $$cluster.spec.location + "maximumLoadBalancerRuleCount" 250 + "resourceGroup" $$cluster.spec.resourceGroup + "routeTableName" $$routeTableName + "securityGroupName" $$securityGroupName + "securityGroupResourceGroup" $$cluster.spec.networkSpec.vnet.resourceGroup + "subnetName" $$subnetName + "subscriptionId" $$cluster.spec.subscriptionID + "tenantId" $$identity.spec.tenantID + "useInstanceMetadata" true + "useManagedIdentityExtension" false + "vmType" "vmss" + "vnetName" $$cluster.spec.networkSpec.vnet.name + "vnetResourceGroup" $$cluster.spec.networkSpec.vnet.resourceGroup + -}} + --- + apiVersion: v1 + kind: Secret + metadata: + name: azure-cloud-provider + namespace: kube-system + type: Opaque + data: + cloud-config: {{ $$cloudConfig | toJson | b64enc }} diff --git a/go.mod b/go.mod index f877bafc..4c517a6e 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/fluxcd/pkg/apis/meta v1.9.0 github.com/fluxcd/pkg/runtime v0.50.1 github.com/fluxcd/source-controller/api v1.4.1 + github.com/go-logr/logr v1.4.2 github.com/google/uuid v1.6.0 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/onsi/ginkgo/v2 v2.22.2 @@ -29,7 +30,6 @@ require ( k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 sigs.k8s.io/cluster-api v1.9.3 sigs.k8s.io/cluster-api-operator v0.15.1 - sigs.k8s.io/cluster-api-provider-azure v1.17.2 sigs.k8s.io/cluster-api-provider-openstack v0.11.3 sigs.k8s.io/cluster-api-provider-vsphere v1.12.0 sigs.k8s.io/controller-runtime v0.19.3 @@ -39,9 +39,6 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/BurntSushi/toml v1.4.0 // indirect @@ -85,7 +82,6 @@ require ( github.com/go-errors/errors v1.5.1 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-ldap/ldap/v3 v3.4.8 // indirect - github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -173,13 +169,13 @@ require ( github.com/zeebo/blake3 v0.2.4 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect - golang.org/x/mod v0.22.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/sync v0.10.0 // indirect diff --git a/go.sum b/go.sum index e4f65c9f..304dec1a 100644 --- a/go.sum +++ b/go.sum @@ -4,27 +4,10 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= -github.com/Azure/azure-service-operator/v2 v2.8.0 h1:BcyB8LvRmtgVIIUaXwWIJz5eHvknyno0qq5LkDuvM/s= -github.com/Azure/azure-service-operator/v2 v2.8.0/go.mod h1:ezbJS56PcORFFqLV8XZmM9xZ12m6aGAkg353fQhWD/8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= @@ -55,8 +38,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -203,8 +184,6 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -262,7 +241,7 @@ github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFO github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= @@ -393,8 +372,6 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -708,8 +685,6 @@ sigs.k8s.io/cluster-api v1.9.3 h1:lKWbrXzyNmJh++IcX54ZbAmnO7tZ2wKgds7WvskpiXY= sigs.k8s.io/cluster-api v1.9.3/go.mod h1:5iojv38PSvOd4cxqu08Un5TQmy2yBkd3+0U7R/e+msk= sigs.k8s.io/cluster-api-operator v0.15.1 h1:oGEqNE7c1Ieqwso/DwjRVD2b/7wFXIjEKAodlwsO6/Q= sigs.k8s.io/cluster-api-operator v0.15.1/go.mod h1:0yvW+1BLHcE5/gQfWSin1L4Gj+8wa9y7+vVTXOhUnSg= -sigs.k8s.io/cluster-api-provider-azure v1.17.2 h1:uS9ggE/bryI0hiOWHBa56nYHkWmsPZW3bzYeAddL4vM= -sigs.k8s.io/cluster-api-provider-azure v1.17.2/go.mod h1:ohdf0TYutOn5vKsXpNVeZUVfUSNIwNhfF6wDjbiqPI0= sigs.k8s.io/cluster-api-provider-openstack v0.11.3 h1:ZJ3G+m11bgaD227EuFjuFsFC95MRzJm9JbDIte0xwII= sigs.k8s.io/cluster-api-provider-openstack v0.11.3/go.mod h1:0rH6yksLcuwWK/SoSoCOJi4A0kOSL3qrA+qvDVZ9NjU= sigs.k8s.io/cluster-api-provider-vsphere v1.12.0 h1:9ze+1JSdLAGiLklsnORvj/vs2XpR9jyVmkT0Dwo1nuc= diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index 67746882..dea45837 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -50,6 +50,7 @@ import ( hmc "github.com/K0rdent/kcm/api/v1alpha1" "github.com/K0rdent/kcm/internal/credspropagation" "github.com/K0rdent/kcm/internal/helm" + providersloader "github.com/K0rdent/kcm/internal/providers" "github.com/K0rdent/kcm/internal/sveltos" "github.com/K0rdent/kcm/internal/telemetry" "github.com/K0rdent/kcm/internal/utils" @@ -453,6 +454,49 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *hm return ctrl.Result{}, err } + cred := &hmc.Credential{} + err = r.Client.Get(ctx, client.ObjectKey{ + Name: mc.Spec.Credential, + Namespace: mc.Namespace, + }, cred) + if err != nil { + return ctrl.Result{}, err + } + + var ( + templateResourceRefs []sveltosv1beta1.TemplateResourceRef + policyRefs []sveltosv1beta1.PolicyRef + ) + + if cred.Spec.IdentityRef != nil { + templateResourceRefs = []sveltosv1beta1.TemplateResourceRef{ + { + Resource: *cred.Spec.IdentityRef, + Identifier: "InfrastructureProviderIdentity", + }, + { + Resource: corev1.ObjectReference{ + APIVersion: "v1", + Kind: "Secret", + Namespace: cred.Spec.IdentityRef.Namespace, + Name: cred.Spec.IdentityRef.Name + "-secret", + }, + Identifier: "InfrastructureProviderIdentitySecret", + }, + } + + policyRefs = []sveltosv1beta1.PolicyRef{ + { + Kind: "ConfigMap", + Namespace: cred.Spec.IdentityRef.Namespace, + Name: cred.Spec.IdentityRef.Name + "-resource-template", + DeploymentType: sveltosv1beta1.DeploymentTypeRemote, + }, + } + } + + templateResourceRefs = append(templateResourceRefs, mc.Spec.ServiceSpec.TemplateResourceRefs...) + if _, err = sveltos.ReconcileProfile(ctx, r.Client, mc.Namespace, mc.Name, sveltos.ReconcileProfileOpts{ OwnerReference: &metav1.OwnerReference{ @@ -471,7 +515,8 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *hm Priority: mc.Spec.ServiceSpec.Priority, StopOnConflict: mc.Spec.ServiceSpec.StopOnConflict, Reload: mc.Spec.ServiceSpec.Reload, - TemplateResourceRefs: mc.Spec.ServiceSpec.TemplateResourceRefs, + TemplateResourceRefs: templateResourceRefs, + PolicyRefs: policyRefs, }); err != nil { return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) } @@ -574,35 +619,16 @@ func (r *ClusterDeploymentReconciler) releaseCluster(ctx context.Context, namesp return err } - var ( - gvkAWSCluster = schema.GroupVersionKind{ - Group: "infrastructure.cluster.x-k8s.io", - Version: "v1beta2", - Kind: "AWSCluster", - } - - gvkAzureCluster = schema.GroupVersionKind{ - Group: "infrastructure.cluster.x-k8s.io", - Version: "v1beta1", - Kind: "AzureCluster", - } - - gvkMachine = schema.GroupVersionKind{ - Group: "cluster.x-k8s.io", - Version: "v1beta1", - Kind: "Machine", - } - ) - - providerGVKs := map[string]schema.GroupVersionKind{ - "aws": gvkAWSCluster, - "azure": gvkAzureCluster, + gvkMachine := schema.GroupVersionKind{ + Group: "cluster.x-k8s.io", + Version: "v1beta1", + Kind: "Machine", } // Associate the provider with it's GVK for _, provider := range providers { - gvk, ok := providerGVKs[provider] - if !ok { + gvk := providersloader.GetClusterGVK(provider) + if !gvk.Empty() { continue } @@ -636,13 +662,12 @@ func (r *ClusterDeploymentReconciler) getInfraProvidersNames(ctx context.Context return nil, err } - const infraPrefix = "infrastructure-" var ( ips = make([]string, 0, len(template.Status.Providers)) - lprefix = len(infraPrefix) + lprefix = len(providersloader.InfraPrefix) ) for _, v := range template.Status.Providers { - if idx := strings.Index(v, infraPrefix); idx > -1 { + if idx := strings.Index(v, providersloader.InfraPrefix); idx > -1 { ips = append(ips, v[idx+lprefix:]) } } @@ -719,73 +744,36 @@ func (r *ClusterDeploymentReconciler) reconcileCredentialPropagation(ctx context } for _, provider := range providers { - switch provider { - case "aws": - l.Info("Skipping creds propagation for AWS") - case "azure": - l.Info("Azure creds propagation start") - if err := credspropagation.PropagateAzureSecrets(ctx, propnCfg); err != nil { - errMsg := fmt.Sprintf("failed to create Azure CCM credentials: %s", err) - apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ - Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionFalse, - Reason: hmc.FailedReason, - Message: errMsg, - }) - - return errors.New(errMsg) - } + titleName := providersloader.GetProviderTitleName(provider) + f, ok := providersloader.CredentialPropagationFunc(provider) + if !ok || titleName == "" { apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionTrue, - Reason: hmc.SucceededReason, - Message: "Azure CCM credentials created", + Status: metav1.ConditionFalse, + Reason: hmc.FailedReason, + Message: "unsupported infrastructure provider " + provider, }) - case "vsphere": - l.Info("vSphere creds propagation start") - if err := credspropagation.PropagateVSphereSecrets(ctx, propnCfg); err != nil { - errMsg := fmt.Sprintf("failed to create vSphere CCM credentials: %s", err) - apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ - Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionFalse, - Reason: hmc.FailedReason, - Message: errMsg, - }) - return errors.New(errMsg) - } + continue + } + + enabled, err := f(ctx, propnCfg, l) + if err != nil { + errMsg := fmt.Sprintf("failed to create %s CCM credentials: %s", titleName, err) apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionTrue, - Reason: hmc.SucceededReason, - Message: "vSphere CCM credentials created", + Status: metav1.ConditionFalse, + Reason: hmc.FailedReason, + Message: errMsg, }) - case "openstack": - l.Info("OpenStack creds propagation start") - if err := credspropagation.PropagateOpenStackSecrets(ctx, propnCfg); err != nil { - errMsg := fmt.Sprintf("failed to create OpenStack CCM credentials: %s", err) - apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ - Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionFalse, - Reason: hmc.FailedReason, - Message: errMsg, - }) - return errors.New(errMsg) - } - + return errors.New(errMsg) + } else if enabled { apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ Type: hmc.CredentialsPropagatedCondition, Status: metav1.ConditionTrue, Reason: hmc.SucceededReason, - Message: "OpenStack CCM credentials created", - }) - default: - apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metav1.Condition{ - Type: hmc.CredentialsPropagatedCondition, - Status: metav1.ConditionFalse, - Reason: hmc.FailedReason, - Message: "unsupported infrastructure provider " + provider, + Message: titleName + " CCM credentials created", }) } } diff --git a/internal/controller/clusterdeployment_controller_test.go b/internal/controller/clusterdeployment_controller_test.go index 1fe200fa..29de414d 100644 --- a/internal/controller/clusterdeployment_controller_test.go +++ b/internal/controller/clusterdeployment_controller_test.go @@ -577,11 +577,6 @@ var _ = Describe("ClusterDeployment Controller", func() { }) }) - // TODO (#852 brongineer): Add test for ClusterDeployment reconciliation with Azure credentials - PIt("should reconcile ClusterDeployment with Azure credentials", func() { - // TBD - }) - // TODO (#852 brongineer): Add tests for ClusterDeployment reconciliation with other providers' credentials PIt("should reconcile ClusterDeployment with XXX credentials", func() { // TBD diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 56248a42..6db109c4 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -47,6 +47,7 @@ import ( hmc "github.com/K0rdent/kcm/api/v1alpha1" "github.com/K0rdent/kcm/internal/build" "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/providers" "github.com/K0rdent/kcm/internal/utils" ) @@ -200,7 +201,7 @@ func (r *ReleaseReconciler) ensureManagement(ctx context.Context) error { if err != nil { return err } - mgmtObj.Spec.Providers = hmc.GetDefaultProviders() + mgmtObj.Spec.Providers = providers.List() getter := helm.NewMemoryRESTClientGetter(r.Config, r.RESTMapper()) actionConfig := new(action.Configuration) diff --git a/internal/credspropagation/azure.go b/internal/credspropagation/azure.go deleted file mode 100644 index c8129151..00000000 --- a/internal/credspropagation/azure.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2024 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package credspropagation - -import ( - "context" - "encoding/json" - "fmt" - - corev1 "k8s.io/api/core/v1" - capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -func PropagateAzureSecrets(ctx context.Context, cfg *PropagationCfg) error { - azureCluster := &capz.AzureCluster{} - if err := cfg.Client.Get(ctx, client.ObjectKey{ - Name: cfg.ClusterDeployment.Name, - Namespace: cfg.ClusterDeployment.Namespace, - }, azureCluster); err != nil { - return fmt.Errorf("failed to get AzureCluster %s: %w", cfg.ClusterDeployment.Name, err) - } - - azureClIdty := &capz.AzureClusterIdentity{} - if err := cfg.Client.Get(ctx, client.ObjectKey{ - Name: azureCluster.Spec.IdentityRef.Name, - Namespace: azureCluster.Spec.IdentityRef.Namespace, - }, azureClIdty); err != nil { - return fmt.Errorf("failed to get AzureClusterIdentity %s: %w", azureCluster.Spec.IdentityRef.Name, err) - } - - azureSecret := &corev1.Secret{} - if err := cfg.Client.Get(ctx, client.ObjectKey{ - Name: azureClIdty.Spec.ClientSecret.Name, - Namespace: azureClIdty.Spec.ClientSecret.Namespace, - }, azureSecret); err != nil { - return fmt.Errorf("failed to get azure Secret %s: %w", azureClIdty.Spec.ClientSecret.Name, err) - } - - ccmSecret, err := generateAzureCCMSecret(azureCluster, azureClIdty, azureSecret) - if err != nil { - return fmt.Errorf("failed to generate Azure CCM secret: %w", err) - } - - if err := applyCCMConfigs(ctx, cfg.KubeconfSecret, ccmSecret); err != nil { - return fmt.Errorf("failed to apply Azure CCM secret: %w", err) - } - - return nil -} - -func generateAzureCCMSecret(azureCluster *capz.AzureCluster, azureClIdty *capz.AzureClusterIdentity, azureSecret *corev1.Secret) (*corev1.Secret, error) { - subnetName, secGroup, routeTable := getAzureSubnetData(azureCluster) - azureJSONMap := map[string]any{ - "cloud": azureCluster.Spec.AzureEnvironment, - "tenantId": azureClIdty.Spec.TenantID, - "subscriptionId": azureCluster.Spec.SubscriptionID, - "aadClientId": azureClIdty.Spec.ClientID, - "aadClientSecret": string(azureSecret.Data["clientSecret"]), - "resourceGroup": azureCluster.Spec.ResourceGroup, - "securityGroupName": secGroup, - "securityGroupResourceGroup": azureCluster.Spec.NetworkSpec.Vnet.ResourceGroup, - "location": azureCluster.Spec.Location, - "vmType": "vmss", - "vnetName": azureCluster.Spec.NetworkSpec.Vnet.Name, - "vnetResourceGroup": azureCluster.Spec.NetworkSpec.Vnet.ResourceGroup, - "subnetName": subnetName, - "routeTableName": routeTable, - "loadBalancerSku": "Standard", - "loadBalancerName": "", - "maximumLoadBalancerRuleCount": 250, - "useManagedIdentityExtension": false, - "useInstanceMetadata": true, - } - azureJSON, err := json.Marshal(azureJSONMap) - if err != nil { - return nil, fmt.Errorf("error marshalling azure.json: %w", err) - } - - secretData := map[string][]byte{ - "cloud-config": azureJSON, - } - - return makeSecret("azure-cloud-provider", secretData), nil -} - -func getAzureSubnetData(azureCluster *capz.AzureCluster) (subnetName, secGroup, routeTable string) { - for _, sn := range azureCluster.Spec.NetworkSpec.Subnets { - if sn.Role == "node" { - subnetName = sn.Name - secGroup = sn.SecurityGroup.Name - routeTable = sn.RouteTable.Name - break - } - } - return subnetName, secGroup, routeTable -} diff --git a/internal/credspropagation/openstack.go b/internal/credspropagation/openstack.go index c39acef9..ec6f3dd5 100644 --- a/internal/credspropagation/openstack.go +++ b/internal/credspropagation/openstack.go @@ -60,8 +60,8 @@ type ( } ) -// PropagateOpenStackSecrets propagates OpenStack secrets -func PropagateOpenStackSecrets(ctx context.Context, cfg *PropagationCfg) error { +// PropagateOpenStackProviderObjects propagates OpenStack secrets +func PropagateOpenStackProviderObjects(ctx context.Context, cfg *PropagationCfg) error { if cfg == nil { return errors.New("PropagationCfg is nil") } diff --git a/internal/credspropagation/vsphere.go b/internal/credspropagation/vsphere.go index bf0cf4dd..9df21737 100644 --- a/internal/credspropagation/vsphere.go +++ b/internal/credspropagation/vsphere.go @@ -30,7 +30,7 @@ import ( hmc "github.com/K0rdent/kcm/api/v1alpha1" ) -func PropagateVSphereSecrets(ctx context.Context, cfg *PropagationCfg) error { +func PropagateVSphereProviderObjects(ctx context.Context, cfg *PropagationCfg) error { vsphereCluster := &capv.VSphereCluster{} if err := cfg.Client.Get(ctx, client.ObjectKey{ Name: cfg.ClusterDeployment.Name, diff --git a/internal/providers/aws.go b/internal/providers/aws.go new file mode 100644 index 00000000..1a4d1136 --- /dev/null +++ b/internal/providers/aws.go @@ -0,0 +1,67 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package providers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/K0rdent/kcm/internal/credspropagation" +) + +type ProviderAWS struct{} + +var _ ProviderModule = (*ProviderAWS)(nil) + +func init() { + Register(&ProviderAWS{}) +} + +func (*ProviderAWS) GetName() string { + return "aws" +} + +func (*ProviderAWS) GetTitleName() string { + return "AWS" +} + +func (*ProviderAWS) GetClusterGVK() schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: "infrastructure.cluster.x-k8s.io", + Version: "v1beta2", + Kind: "AWSCluster", + } +} + +func (*ProviderAWS) GetClusterIdentityKinds() []string { + return []string{"AWSClusterStaticIdentity", "AWSClusterRoleIdentity", "AWSClusterControllerIdentity"} +} + +func (p *ProviderAWS) CredentialPropagationFunc() func( + _ context.Context, + _ *credspropagation.PropagationCfg, + l logr.Logger, +) (enabled bool, err error) { + return func( + _ context.Context, + _ *credspropagation.PropagationCfg, + l logr.Logger, + ) (enabled bool, err error) { + l.Info("Skipping creds propagation for " + p.GetTitleName()) + return enabled, err + } +} diff --git a/internal/providers/azure.go b/internal/providers/azure.go new file mode 100644 index 00000000..0dee264f --- /dev/null +++ b/internal/providers/azure.go @@ -0,0 +1,62 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package providers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/K0rdent/kcm/internal/credspropagation" +) + +type ProviderAzure struct{} + +var _ ProviderModule = (*ProviderAzure)(nil) + +func init() { + Register(&ProviderAzure{}) +} + +func (*ProviderAzure) GetName() string { + return "azure" +} + +func (*ProviderAzure) GetTitleName() string { + return "Azure" +} + +func (*ProviderAzure) GetClusterGVK() schema.GroupVersionKind { + return schema.GroupVersionKind{} +} + +func (*ProviderAzure) GetClusterIdentityKinds() []string { + return []string{"AzureClusterIdentity"} +} + +func (*ProviderAzure) CredentialPropagationFunc() func( + _ context.Context, + _ *credspropagation.PropagationCfg, + _ logr.Logger, +) (enabled bool, err error) { + return func( + _ context.Context, + _ *credspropagation.PropagationCfg, + _ logr.Logger, + ) (enabled bool, err error) { + return enabled, err + } +} diff --git a/internal/providers/openstack.go b/internal/providers/openstack.go new file mode 100644 index 00000000..abdbc145 --- /dev/null +++ b/internal/providers/openstack.go @@ -0,0 +1,64 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package providers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/K0rdent/kcm/internal/credspropagation" +) + +type ProviderOpenStack struct{} + +var _ ProviderModule = (*ProviderOpenStack)(nil) + +func init() { + Register(&ProviderOpenStack{}) +} + +func (*ProviderOpenStack) GetName() string { + return "openstack" +} + +func (*ProviderOpenStack) GetTitleName() string { + return "OpenStack" +} + +func (*ProviderOpenStack) GetClusterGVK() schema.GroupVersionKind { + return schema.GroupVersionKind{} +} + +func (*ProviderOpenStack) GetClusterIdentityKinds() []string { + return []string{"Secret"} +} + +func (p *ProviderOpenStack) CredentialPropagationFunc() func( + ctx context.Context, + cfg *credspropagation.PropagationCfg, + l logr.Logger, +) (enabled bool, err error) { + return func( + ctx context.Context, + cfg *credspropagation.PropagationCfg, + l logr.Logger, + ) (enabled bool, err error) { + l.Info(p.GetTitleName() + " creds propagation start") + enabled, err = true, credspropagation.PropagateOpenStackProviderObjects(ctx, cfg) + return enabled, err + } +} diff --git a/internal/providers/providers.go b/internal/providers/providers.go new file mode 100644 index 00000000..458e2f6c --- /dev/null +++ b/internal/providers/providers.go @@ -0,0 +1,159 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package providers + +import ( + "context" + "fmt" + "slices" + "strings" + "sync" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime/schema" + + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/credspropagation" +) + +const ( + // InfraPrefix is the prefix used for infrastructure provider names + InfraPrefix = "infrastructure-" + // ProviderPrefix is the prefix used for cluster API provider names + ProviderPrefix = "cluster-api-provider-" +) + +var ( + mu sync.RWMutex + + providers = []hmc.Provider{ + { + Name: hmc.ProviderK0smotronName, + }, + { + Name: hmc.ProviderSveltosName, + }, + } + + registry map[string]ProviderModule +) + +type ProviderModule interface { + // GetName returns the short name of the provider + GetName() string + // GetTitleName returns the display title of the provider + GetTitleName() string + // GetClusterGVK returns the GroupVersionKind for the provider's cluster resource + GetClusterGVK() schema.GroupVersionKind + // GetClusterIdentityKinds returns a list of supported cluster identity kinds + GetClusterIdentityKinds() []string + // CredentialPropagationFunc returns a function to handle credential propagation + CredentialPropagationFunc() func( + ctx context.Context, + cfg *credspropagation.PropagationCfg, + l logr.Logger, + ) (enabled bool, err error) +} + +// Register adds a new provider module to the registry +func Register(p ProviderModule) { + mu.Lock() + defer mu.Unlock() + + if registry == nil { + registry = make(map[string]ProviderModule) + } + + shortName := p.GetName() + + if _, exists := registry[shortName]; exists { + panic(fmt.Sprintf("provider %q already registered", shortName)) + } + + providers = append(providers, + hmc.Provider{ + Name: ProviderPrefix + p.GetName(), + }, + ) + + registry[shortName] = p +} + +// List returns a copy of all registered providers +func List() []hmc.Provider { + return slices.Clone(providers) +} + +// CredentialPropagationFunc returns the credential propagation function for a given provider +func CredentialPropagationFunc(fullName string) ( + func(ctx context.Context, propnCfg *credspropagation.PropagationCfg, l logr.Logger) (enabled bool, err error), bool, +) { + mu.RLock() + defer mu.RUnlock() + + shortName := strings.TrimPrefix(fullName, ProviderPrefix) + + module, ok := registry[shortName] + if !ok { + return nil, false + } + + f := module.CredentialPropagationFunc() + + return f, f != nil +} + +// GetClusterGVK returns the GroupVersionKind for a provider's cluster resource +func GetClusterGVK(shortName string) schema.GroupVersionKind { + mu.RLock() + defer mu.RUnlock() + + module, ok := registry[shortName] + if !ok { + return schema.GroupVersionKind{} + } + + return module.GetClusterGVK() +} + +// GetClusterIdentityKinds returns the supported identity kinds for a given infrastructure provider +func GetClusterIdentityKinds(infraName string) ([]string, bool) { + mu.RLock() + defer mu.RUnlock() + + shortName := strings.TrimPrefix(infraName, InfraPrefix) + + module, ok := registry[shortName] + if !ok { + return nil, false + } + + list := slices.Clone(module.GetClusterIdentityKinds()) + + return list, list != nil +} + +// GetProviderTitleName returns the display title for a given provider +func GetProviderTitleName(shortName string) string { + mu.RLock() + defer mu.RUnlock() + + module, ok := registry[shortName] + if !ok { + return "" + } + + return module.GetTitleName() +} diff --git a/internal/providers/vsphere.go b/internal/providers/vsphere.go new file mode 100644 index 00000000..aa854458 --- /dev/null +++ b/internal/providers/vsphere.go @@ -0,0 +1,64 @@ +// Copyright 2024 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package providers + +import ( + "context" + + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/K0rdent/kcm/internal/credspropagation" +) + +type ProvidervSphere struct{} + +var _ ProviderModule = (*ProvidervSphere)(nil) + +func init() { + Register(&ProvidervSphere{}) +} + +func (*ProvidervSphere) GetName() string { + return "vsphere" +} + +func (*ProvidervSphere) GetTitleName() string { + return "vSphere" +} + +func (*ProvidervSphere) GetClusterGVK() schema.GroupVersionKind { + return schema.GroupVersionKind{} +} + +func (*ProvidervSphere) GetClusterIdentityKinds() []string { + return []string{"VSphereClusterIdentity"} +} + +func (p *ProvidervSphere) CredentialPropagationFunc() func( + ctx context.Context, + cfg *credspropagation.PropagationCfg, + l logr.Logger, +) (enabled bool, err error) { + return func( + ctx context.Context, + cfg *credspropagation.PropagationCfg, + l logr.Logger, + ) (enabled bool, err error) { + l.Info(p.GetTitleName() + " creds propagation start") + enabled, err = true, credspropagation.PropagateVSphereProviderObjects(ctx, cfg) + return enabled, err + } +} diff --git a/internal/sveltos/profile.go b/internal/sveltos/profile.go index 1d65d016..8e0cb230 100644 --- a/internal/sveltos/profile.go +++ b/internal/sveltos/profile.go @@ -37,6 +37,7 @@ type ReconcileProfileOpts struct { LabelSelector metav1.LabelSelector HelmChartOpts []HelmChartOpts TemplateResourceRefs []sveltosv1beta1.TemplateResourceRef + PolicyRefs []sveltosv1beta1.PolicyRef Priority int32 StopOnConflict bool Reload bool @@ -239,6 +240,7 @@ func GetSpec(opts *ReconcileProfileOpts) (*sveltosv1beta1.Spec, error) { HelmCharts: make([]sveltosv1beta1.HelmChart, 0, len(opts.HelmChartOpts)), Reloader: opts.Reload, TemplateResourceRefs: opts.TemplateResourceRefs, + PolicyRefs: opts.PolicyRefs, } for _, hc := range opts.HelmChartOpts { diff --git a/internal/webhook/clusterdeployment_webhook.go b/internal/webhook/clusterdeployment_webhook.go index f405702b..57e9833f 100644 --- a/internal/webhook/clusterdeployment_webhook.go +++ b/internal/webhook/clusterdeployment_webhook.go @@ -31,6 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + providersloader "github.com/K0rdent/kcm/internal/providers" ) type ClusterDeploymentValidator struct { @@ -269,30 +270,25 @@ func isCredMatchTemplate(cred *hmcv1alpha1.Credential, template *hmcv1alpha1.Clu } for _, provider := range template.Status.Providers { - switch provider { - case "infrastructure-aws": - if idtyKind != "AWSClusterStaticIdentity" && - idtyKind != "AWSClusterRoleIdentity" && - idtyKind != "AWSClusterControllerIdentity" { - return errMsg(provider) - } - case "infrastructure-azure": - if idtyKind != "AzureClusterIdentity" && - idtyKind != "Secret" { - return errMsg(provider) - } - case "infrastructure-vsphere": - if idtyKind != "VSphereClusterIdentity" { - return errMsg(provider) - } - case "infrastructure-openstack", "infrastructure-internal": + if provider == providersloader.InfraPrefix+"internal" { if idtyKind != "Secret" { return errMsg(provider) } - default: - if strings.HasPrefix(provider, "infrastructure-") { + + continue + } + + idtys, found := providersloader.GetClusterIdentityKinds(provider) + if !found { + if strings.HasPrefix(provider, providersloader.InfraPrefix) { return fmt.Errorf("unsupported infrastructure provider %s", provider) } + + continue + } + + if !slices.Contains(idtys, idtyKind) { + return errMsg(provider) } } diff --git a/internal/webhook/clusterdeployment_webhook_test.go b/internal/webhook/clusterdeployment_webhook_test.go index a66cd9b8..25417a3a 100644 --- a/internal/webhook/clusterdeployment_webhook_test.go +++ b/internal/webhook/clusterdeployment_webhook_test.go @@ -276,10 +276,18 @@ func TestClusterDeploymentValidateCreate(t *testing.T) { clusterdeployment.WithCredential(testCredentialName), ), existingObjects: []runtime.Object{ - cred, + credential.NewCredential( + credential.WithName(testCredentialName), + credential.WithReady(true), + credential.WithIdentityRef( + &corev1.ObjectReference{ + Kind: "SomeOtherDummyClusterStaticIdentity", + Name: "otherdummyclid", + }), + ), management.NewManagement( management.WithAvailableProviders(v1alpha1.Providers{ - "infrastructure-azure", + "infrastructure-aws", "control-plane-k0smotron", "bootstrap-k0smotron", }), @@ -287,14 +295,14 @@ func TestClusterDeploymentValidateCreate(t *testing.T) { template.NewClusterTemplate( template.WithName(testTemplateName), template.WithProvidersStatus( - "infrastructure-azure", + "infrastructure-aws", "control-plane-k0smotron", "bootstrap-k0smotron", ), template.WithValidationStatus(v1alpha1.TemplateValidationStatus{Valid: true}), ), }, - err: "the ClusterDeployment is invalid: wrong kind of the ClusterIdentity \"AWSClusterStaticIdentity\" for provider \"infrastructure-azure\"", + err: "the ClusterDeployment is invalid: wrong kind of the ClusterIdentity \"SomeOtherDummyClusterStaticIdentity\" for provider \"infrastructure-aws\"", }, } for _, tt := range tests {