From 01ea9da5bbf022d2e7b46f396cd4bfaadf46c72a Mon Sep 17 00:00:00 2001 From: Tapajit Chandra Paul Date: Thu, 7 Sep 2023 16:33:03 +0600 Subject: [PATCH] Add default valid nodepool name generator and Update validator for the nodepool name Signed-off-by: Tapajit Chandra Paul --- .../azuremanagedmachinepool_webhook.go | 76 +++++++++++++++++-- go.mod | 3 +- go.sum | 2 + 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/api/v1beta1/azuremanagedmachinepool_webhook.go b/api/v1beta1/azuremanagedmachinepool_webhook.go index 86be164f2aa..11b8e94a838 100644 --- a/api/v1beta1/azuremanagedmachinepool_webhook.go +++ b/api/v1beta1/azuremanagedmachinepool_webhook.go @@ -19,17 +19,14 @@ package v1beta1 import ( "context" "fmt" - "reflect" - "regexp" - "strconv" - "strings" - - "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" kerrors "k8s.io/apimachinery/pkg/util/errors" + utilrand "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/utils/ptr" + "reflect" + "regexp" "sigs.k8s.io/cluster-api-provider-azure/feature" azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure" "sigs.k8s.io/cluster-api-provider-azure/util/maps" @@ -39,6 +36,11 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + "strconv" + "strings" + "unicode" + + "github.com/pkg/errors" ) var validNodePublicPrefixID = regexp.MustCompile(`(?i)^/?subscriptions/[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}/resourcegroups/[^/]+/providers/microsoft\.network/publicipprefixes/[^/]+$`) @@ -72,9 +74,9 @@ func (mw *azureManagedMachinePoolWebhook) Default(ctx context.Context, obj runti m.Labels[LabelAgentPoolMode] = m.Spec.Mode if m.Spec.Name == nil || *m.Spec.Name == "" { - m.Spec.Name = &m.Name + aksNodePoolName := generateAKSNodePoolName(m.Name) + m.Spec.Name = &aksNodePoolName } - if m.Spec.OSType == nil { m.Spec.OSType = ptr.To(DefaultOSType) } @@ -82,6 +84,35 @@ func (mw *azureManagedMachinePoolWebhook) Default(ctx context.Context, obj runti return nil } +// generates a valid unqiue nodepool name following limitations of Azure +func generateAKSNodePoolName(name string) string { + var builder strings.Builder + + for _, char := range name { + if builder.Len() == 0 { + if unicode.IsLower(char) { + builder.WriteRune(char) + } + } else if unicode.IsLower(char) || unicode.IsNumber(char) { + builder.WriteRune(char) + } + + if builder.Len() == 6 { + break + } + } + + if builder.Len() == 0 { + builder.WriteString("pool") + } + + numOfChars := 12 - builder.Len() + randomValue := utilrand.String(numOfChars) + builder.WriteString(randomValue) + + return builder.String() +} + //+kubebuilder:webhook:verbs=create;update;delete,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-azuremanagedmachinepool,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=azuremanagedmachinepools,versions=v1beta1,name=validation.azuremanagedmachinepools.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. @@ -371,6 +402,35 @@ func (m *AzureManagedMachinePool) validateName() error { "Windows agent pool name can not be longer than 6 characters.") } + // Length check for linux following restrictions of AKS + if m.Spec.OSType == nil || *m.Spec.OSType == LinuxOS && + m.Spec.Name != nil && len(*m.Spec.Name) > 12 { + return field.Invalid( + field.NewPath("Spec", "Name"), + m.Spec.Name, + "Linux agent pool name can not be longer than 12 characters.") + } + + // Common Checks for both Windows & Linux following restrictions of AKS + if m.Spec.Name != nil { + for _, char := range *m.Spec.Name { + if !unicode.IsLower(char) && !unicode.IsNumber(char) { + return field.Invalid( + field.NewPath("Spec", "Name"), + m.Spec.Name, + "Agent pool name may only contain lowercase alphanumeric characters.") + } + } + + nodePoolName := *m.Spec.Name + if !unicode.IsLower(rune(nodePoolName[0])) { + return field.Invalid( + field.NewPath("Spec", "Name"), + m.Spec.Name, + "Linux agent pool name must begin with a lowercase letter.") + } + } + return nil } diff --git a/go.mod b/go.mod index 20dc4378e98..c74b6bee48d 100644 --- a/go.mod +++ b/go.mod @@ -44,8 +44,10 @@ require ( golang.org/x/crypto v0.12.0 golang.org/x/mod v0.12.0 golang.org/x/text v0.13.0 + gomodules.xyz/password-generator v0.2.9 k8s.io/api v0.27.2 k8s.io/apimachinery v0.27.2 + k8s.io/apiserver v0.27.2 k8s.io/client-go v0.27.2 k8s.io/component-base v0.27.2 k8s.io/klog/v2 v2.90.1 @@ -194,7 +196,6 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.27.2 // indirect - k8s.io/apiserver v0.27.2 // indirect k8s.io/cli-runtime v0.27.2 // indirect k8s.io/cloud-provider v0.27.1 // indirect k8s.io/cluster-bootstrap v0.27.2 // indirect diff --git a/go.sum b/go.sum index 5718963827e..e70f9b37ec8 100644 --- a/go.sum +++ b/go.sum @@ -925,6 +925,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gomodules.xyz/password-generator v0.2.9 h1:qYoXoA61+9zs9A1scffefCgcRGpi9Tw1LsTkIe4bEno= +gomodules.xyz/password-generator v0.2.9/go.mod h1:TvwYYTx9+P1pPwKQKfZgB/wr2Id9MqAQ3B5auY7reNg= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=