diff --git a/api/v1beta1/azuremanagedcontrolplane_types.go b/api/v1beta1/azuremanagedcontrolplane_types.go index 19bef9155891..8b63b928f617 100644 --- a/api/v1beta1/azuremanagedcontrolplane_types.go +++ b/api/v1beta1/azuremanagedcontrolplane_types.go @@ -457,6 +457,10 @@ type MarketplaceExtension struct { // Version is the version of the extension. // +optional Version *string `json:"version,omitempty"` + + // Identity is the identity type of the Extension resource in an AKS cluster. + // +optional + Identity ExtensionIdentity `json:"identity,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1beta1/azuremanagedcontrolplane_webhook.go b/api/v1beta1/azuremanagedcontrolplane_webhook.go index 41c6b2c71556..5a9d766b0a6e 100644 --- a/api/v1beta1/azuremanagedcontrolplane_webhook.go +++ b/api/v1beta1/azuremanagedcontrolplane_webhook.go @@ -687,9 +687,15 @@ func (m *AzureManagedControlPlane) validateOIDCIssuerProfileUpdate(old *AzureMan func (m *AzureManagedControlPlane) validateMarketplaceExtensionsUpdate(old *AzureManagedControlPlane) field.ErrorList { var allErrs field.ErrorList - if m.Spec.MarketplaceExtensions != nil && old.Spec.MarketplaceExtensions != nil { - for i, extension := range m.Spec.MarketplaceExtensions { - if extension.Name != old.Spec.MarketplaceExtensions[i].Name { + oldMarketplaceExtensionsMap := make(map[string]MarketplaceExtension, len(old.Spec.MarketplaceExtensions)) + oldMarketplaceExtensionsIndex := make(map[string]int, len(old.Spec.MarketplaceExtensions)) + for i, extension := range old.Spec.MarketplaceExtensions { + oldMarketplaceExtensionsMap[extension.Name] = extension + oldMarketplaceExtensionsIndex[extension.Name] = i + } + for i, extension := range m.Spec.MarketplaceExtensions { + if oldExtension, ok := oldMarketplaceExtensionsMap[extension.Name]; ok { + if extension.Name != oldExtension.Name { allErrs = append(allErrs, field.Invalid( field.NewPath("Spec", "MarketplaceExtensions", fmt.Sprintf("[%d]", i), "Name"), @@ -698,7 +704,16 @@ func (m *AzureManagedControlPlane) validateMarketplaceExtensionsUpdate(old *Azur ), ) } - if extension.Plan.Publisher != old.Spec.MarketplaceExtensions[i].Plan.Publisher { + if extension.ExtensionType != oldExtension.ExtensionType { + allErrs = append(allErrs, + field.Invalid( + field.NewPath("Spec", "MarketplaceExtensions", fmt.Sprintf("[%d]", i), "ExtensionType"), + extension.ExtensionType, + "field is immutable", + ), + ) + } + if extension.Plan.Publisher != oldExtension.Plan.Publisher { allErrs = append(allErrs, field.Invalid( field.NewPath("Spec", "MarketplaceExtensions", fmt.Sprintf("[%d]", i), "Publisher"), @@ -707,7 +722,7 @@ func (m *AzureManagedControlPlane) validateMarketplaceExtensionsUpdate(old *Azur ), ) } - if extension.Plan.Product != old.Spec.MarketplaceExtensions[i].Plan.Product { + if extension.Plan.Product != oldExtension.Plan.Product { allErrs = append(allErrs, field.Invalid( field.NewPath("Spec", "MarketplaceExtensions", fmt.Sprintf("[%d]", i), "Product"), @@ -746,6 +761,9 @@ func validateMarketplaceExtensions(extensions []MarketplaceExtension, fldPath *f if extension.Plan.Publisher == "" { allErrs = append(allErrs, field.Required(fldPath.Child("Plan", "Publisher"), "Publisher must be provided")) } + if extension.AutoUpgradeMinorVersion == ptr.To(false) && extension.ReleaseTrain != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("ReleaseTrain"), "ReleaseTrain must not be given if AutoUpgradeMinorVersion is false")) + } } return allErrs diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index d45b8408fd90..a6bf322f258f 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -1109,3 +1109,14 @@ type MarketplacePlan struct { // +optional Version string `json:"version,omitempty"` } + +// ExtensionIdentity defines the identity of the aks marketplace extension, if configured. +// +kubebuilder:validation:Enum=SystemAssigned;UserAssigned +type ExtensionIdentity string + +const ( + // ExtensionIdentitySystemAssigned ... + ExtensionIdentitySystemAssigned ExtensionIdentity = "SystemAssigned" + // ExtensionIdentityUserAssigned ... + ExtensionIdentityUserAssigned ExtensionIdentity = "UserAssigned" +) diff --git a/azure/scope/managedcontrolplane.go b/azure/scope/managedcontrolplane.go index 12bbc3da2241..4aec0d2aa30e 100644 --- a/azure/scope/managedcontrolplane.go +++ b/azure/scope/managedcontrolplane.go @@ -929,7 +929,7 @@ func (s *ManagedControlPlaneScope) AKSExtensionSpecs() []azure.ASOResourceSpecGe Owner: azure.ManagedClusterID(s.SubscriptionID(), s.ResourceGroup(), s.ControlPlane.Name), OwnerRef: *metav1.NewControllerRef(s.ControlPlane, infrav1.GroupVersion.WithKind(infrav1.AzureManagedControlPlaneKind)), Plan: *extension.Plan, - // AKSAssignedIdentityType: extension.AKSAssignedIdentityType, + AKSAssignedIdentityType: extension.Identity, } extensionSpecs = append(extensionSpecs, extensionSpec) diff --git a/azure/services/aksextensions/spec.go b/azure/services/aksextensions/spec.go index e2eceed062a7..c623924bfa84 100644 --- a/azure/services/aksextensions/spec.go +++ b/azure/services/aksextensions/spec.go @@ -30,7 +30,7 @@ import ( type AKSExtensionSpec struct { Name string Namespace string - AKSAssignedIdentityType string + AKSAssignedIdentityType infrav1.ExtensionIdentity AutoUpgradeMinorVersion *bool ConfigurationSettings map[string]string ExtensionType *string @@ -77,6 +77,11 @@ func (s *AKSExtensionSpec) Parameters(ctx context.Context, existingAKSExtension Publisher: ptr.To(s.Plan.Publisher), Version: ptr.To(s.Plan.Version), } + if s.AKSAssignedIdentityType != "" { + aksExtension.Spec.Identity = &asokubernetesconfigurationv1.Identity{ + Type: (*asokubernetesconfigurationv1.Identity_Type)(&s.AKSAssignedIdentityType), + } + } return aksExtension, nil } diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanes.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanes.yaml index d97cc1ca1638..2d0479bce5d5 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanes.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanes.yaml @@ -405,6 +405,13 @@ spec: Types registered with Microsoft.KubernetesConfiguration by the Extension publisher. type: string + identity: + description: Identity is the identity type of the Extension + resource in an AKS cluster. + enum: + - SystemAssigned + - UserAssigned + type: string name: description: Name is the name of the extension. type: string diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanetemplates.yaml index 9b3d99023372..918fc23c7475 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_azuremanagedcontrolplanetemplates.yaml @@ -413,6 +413,13 @@ spec: be one of the Extension Types registered with Microsoft.KubernetesConfiguration by the Extension publisher. type: string + identity: + description: Identity is the identity type of the Extension + resource in an AKS cluster. + enum: + - SystemAssigned + - UserAssigned + type: string name: description: Name is the name of the extension. type: string