From 9c3a28ab22c45d5d988f796d783dc67d098e0fe8 Mon Sep 17 00:00:00 2001 From: Vivek Kumar Singh Date: Mon, 16 Dec 2024 09:27:20 +0530 Subject: [PATCH] add webhook validation and tests --- internal/webhooks/vspheremachinetemplate.go | 43 ++++++++- .../webhooks/vspheremachinetemplate_test.go | 88 +++++++++++++------ pkg/services/vimmachine_test.go | 84 ++++++++++++++++++ .../main/clusterclass/kustomization.yaml | 3 + .../clusterclass/patch-vm-namingstrategy.yaml | 4 + 5 files changed, 194 insertions(+), 28 deletions(-) create mode 100644 test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/patch-vm-namingstrategy.yaml diff --git a/internal/webhooks/vspheremachinetemplate.go b/internal/webhooks/vspheremachinetemplate.go index 8a1c865481..f344b3ebcf 100644 --- a/internal/webhooks/vspheremachinetemplate.go +++ b/internal/webhooks/vspheremachinetemplate.go @@ -24,6 +24,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" "sigs.k8s.io/cluster-api/util/topology" ctrl "sigs.k8s.io/controller-runtime" @@ -31,6 +32,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" + "sigs.k8s.io/cluster-api-provider-vsphere/pkg/services" ) const machineTemplateImmutableMsg = "VSphereMachineTemplate spec.template.spec field is immutable. Please create a new resource instead." @@ -50,7 +52,7 @@ func (webhook *VSphereMachineTemplateWebhook) SetupWebhookWithManager(mgr ctrl.M } // ValidateCreate implements webhook.Validator so a webhook will be registered for the type. -func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(_ context.Context, raw runtime.Object) (admission.Warnings, error) { +func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(ctx context.Context, raw runtime.Object) (admission.Warnings, error) { obj, ok := raw.(*infrav1.VSphereMachineTemplate) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a VSphereMachineTemplate but got a %T", raw)) @@ -87,6 +89,10 @@ func (webhook *VSphereMachineTemplateWebhook) ValidateCreate(_ context.Context, pciErrs := validatePCIDevices(spec.PciDevices) allErrs = append(allErrs, pciErrs...) + templateErrs := validateVSphereVMNamingTemplate(ctx, obj) + if len(templateErrs) > 0 { + allErrs = append(allErrs, templateErrs...) + } return nil, AggregateObjErrors(obj.GroupVersionKind().GroupKind(), obj.Name, allErrs) } @@ -111,6 +117,11 @@ func (webhook *VSphereMachineTemplateWebhook) ValidateUpdate(ctx context.Context !reflect.DeepEqual(newTyped.Spec.Template.Spec, oldTyped.Spec.Template.Spec) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "template", "spec"), newTyped, machineTemplateImmutableMsg)) } + + templateErrs := validateVSphereVMNamingTemplate(ctx, newTyped) + if len(templateErrs) > 0 { + allErrs = append(allErrs, templateErrs...) + } return nil, AggregateObjErrors(newTyped.GroupVersionKind().GroupKind(), newTyped.Name, allErrs) } @@ -118,3 +129,33 @@ func (webhook *VSphereMachineTemplateWebhook) ValidateUpdate(ctx context.Context func (webhook *VSphereMachineTemplateWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } + +func validateVSphereVMNamingTemplate(_ context.Context, vsphereMachineTemplate *infrav1.VSphereMachineTemplate) field.ErrorList { + var allErrs field.ErrorList + namingStrategy := vsphereMachineTemplate.Spec.Template.Spec.NamingStrategy + if namingStrategy != nil && namingStrategy.Template != nil { + name, err := services.GenerateVSphereVMName("machine", namingStrategy) + templateFldPath := field.NewPath("spec", "template", "spec", "namingStrategy", "template") + if err != nil { + allErrs = append(allErrs, + field.Invalid( + templateFldPath, + *namingStrategy.Template, + fmt.Sprintf("invalid VSphereVM name template: %v", err), + ), + ) + } else { + // Note: This validates that the resulting name is a valid Kubernetes object name. + for _, err := range validation.IsDNS1123Subdomain(name) { + allErrs = append(allErrs, + field.Invalid( + templateFldPath, + *namingStrategy.Template, + fmt.Sprintf("invalid VSphereVM name template, generated name is not a valid Kubernetes object name: %v", err), + ), + ) + } + } + } + return allErrs +} diff --git a/internal/webhooks/vspheremachinetemplate_test.go b/internal/webhooks/vspheremachinetemplate_test.go index 95ccd7042e..00dedad3f4 100644 --- a/internal/webhooks/vspheremachinetemplate_test.go +++ b/internal/webhooks/vspheremachinetemplate_test.go @@ -37,70 +37,96 @@ func TestVSphereMachineTemplate_ValidateCreate(t *testing.T) { }{ { name: "preferredAPIServerCIDR set on creation ", - vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "192.168.0.1/32", []string{}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "192.168.0.1/32", []string{}, nil, nil), wantErr: true, }, { name: "ProviderID set on creation", - vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{}, nil, nil), wantErr: true, }, { name: "IPs are not in CIDR format", - vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32", "192.168.0.3"}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32", "192.168.0.3"}, nil, nil), wantErr: true, }, { name: "successful VSphereMachine creation", - vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil, nil), wantErr: true, }, { name: "incomplete hardware version", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil, nil), wantErr: true, }, { name: "incorrect hardware version", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-0", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-0", nil, "", []string{"192.168.0.1/32", "192.168.0.3/32"}, nil, nil), wantErr: true, }, { name: "empty pciDevice", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: ""}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: ""}}, nil), wantErr: true, }, { name: "incorrect pciDevice", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu", DeviceID: ptr.To[int32](1)}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu", DeviceID: ptr.To[int32](1)}}, nil), wantErr: true, }, { name: "incorrect pciDevice", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu", DeviceID: ptr.To[int32](1), VendorID: ptr.To[int32](1)}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu", DeviceID: ptr.To[int32](1), VendorID: ptr.To[int32](1)}}, nil), wantErr: true, }, { name: "incomplete pciDevice", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{DeviceID: ptr.To[int32](1)}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{DeviceID: ptr.To[int32](1)}}, nil), wantErr: true, }, { name: "incomplete pciDevice", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VendorID: ptr.To[int32](1)}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VendorID: ptr.To[int32](1)}}, nil), wantErr: true, }, { name: "successful VSphereMachine creation with PCI device", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{DeviceID: ptr.To[int32](1), VendorID: ptr.To[int32](1)}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{DeviceID: ptr.To[int32](1), VendorID: ptr.To[int32](1)}}, nil), }, { name: "successful VSphereMachine creation with vgpu", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu"}}), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu"}}, nil), }, { name: "successful VSphereMachine creation with hardware version set", - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, nil), + }, + { + name: "successful VSphereMachineTemplate creation with namingStrategy not set", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, nil), + }, + { + name: "successful VSphereMachineTemplate creation with namingStrategy.Template not set", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: nil}), + }, + { + name: "successful VSphereMachineTemplate creation with namingStrategy.template is set to the fallback value", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: ptr.To[string]("{{ .machine.name }}")}), + }, + { + name: "successful VSphereMachineTemplate creation with namingStrategy.template is set the Windows example", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: ptr.To[string]("{{ if le (len .machine.name) 20 }}{{ .machine.name }}{{else}}{{ trimSuffix \"-\" (trunc 14 .machine.name) }}-{{ trunc -5 .machine.name }}{{end}}")}), + }, + { + name: "failed VSphereMachineTemplate creation with namingStrategy.template is set to an invalid template", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: ptr.To[string]("{{ invalid")}), + wantErr: true, + }, + { + name: "failed VSphereMachineTemplate creation with namingStrategy.template is set to a valid template that renders an invalid name", + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-17", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: ptr.To[string]("-{{ .machine.name }}")}), + wantErr: true, }, } for _, tc := range tests { @@ -127,46 +153,53 @@ func TestVSphereMachineTemplate_ValidateUpdate(t *testing.T) { }{ { name: "ProviderID cannot be updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil), - vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{"192.168.0.1/32"}, nil), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{"192.168.0.1/32"}, nil, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: true, }, { name: "ip addresses cannot be updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil), - vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: true, }, { name: "server cannot be updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil), - vsphereMachine: createVSphereMachineTemplate("baz.com", "", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("baz.com", "", &someProviderID, "", []string{"192.168.0.1/32", "192.168.0.10/32"}, nil, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: true, }, { name: "hardware version cannot be updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil), - vsphereMachine: createVSphereMachineTemplate("baz.com", "vmx-17", nil, "", []string{"192.168.0.1/32"}, nil), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("baz.com", "vmx-17", nil, "", []string{"192.168.0.1/32"}, nil, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: true, }, { name: "pci devices cannot be updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu"}}), - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, []infrav1.PCIDeviceSpec{{VGPUProfile: "new-vgpu"}}), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, []infrav1.PCIDeviceSpec{{VGPUProfile: "vgpu"}}, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, []infrav1.PCIDeviceSpec{{VGPUProfile: "new-vgpu"}}, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: true, }, { name: "with hardware version set and not updated", - oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil), - vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil), + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil, nil), req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, wantErr: false, // explicitly calling out that this is a valid scenario. }, + { + name: "naming strategy can not be updated", + oldVSphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{"192.168.0.1/32"}, nil, nil), + vsphereMachine: createVSphereMachineTemplate("foo.com", "vmx-16", nil, "", []string{}, nil, &infrav1.VSphereVMNamingStrategy{Template: ptr.To[string]("{{ .machine.name }}")}), + req: &admission.Request{AdmissionRequest: admissionv1.AdmissionRequest{DryRun: ptr.To(false)}}, + wantErr: true, + }, } for _, tc := range tests { t.Run(tc.name, func(*testing.T) { @@ -185,7 +218,7 @@ func TestVSphereMachineTemplate_ValidateUpdate(t *testing.T) { } } -func createVSphereMachineTemplate(server, hwVersion string, providerID *string, preferredAPIServerCIDR string, ips []string, pciDevices []infrav1.PCIDeviceSpec) *infrav1.VSphereMachineTemplate { +func createVSphereMachineTemplate(server, hwVersion string, providerID *string, preferredAPIServerCIDR string, ips []string, pciDevices []infrav1.PCIDeviceSpec, vmNamingStrategy *infrav1.VSphereVMNamingStrategy) *infrav1.VSphereMachineTemplate { vsphereMachineTemplate := &infrav1.VSphereMachineTemplate{ Spec: infrav1.VSphereMachineTemplateSpec{ Template: infrav1.VSphereMachineTemplateResource{ @@ -200,6 +233,7 @@ func createVSphereMachineTemplate(server, hwVersion string, providerID *string, HardwareVersion: hwVersion, PciDevices: pciDevices, }, + NamingStrategy: vmNamingStrategy, }, }, }, diff --git a/pkg/services/vimmachine_test.go b/pkg/services/vimmachine_test.go index c3961bb822..01bfdd1284 100644 --- a/pkg/services/vimmachine_test.go +++ b/pkg/services/vimmachine_test.go @@ -21,6 +21,7 @@ import ( "testing" . "github.com/onsi/gomega" + gomegatypes "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -29,6 +30,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context/fake" "sigs.k8s.io/cluster-api-provider-vsphere/pkg/util" @@ -904,3 +906,85 @@ func Test_VimMachineService_SyncFailureReason(t *testing.T) { g.Expect(err).NotTo(HaveOccurred()) }) } + +func Test_GenerateVSphereVMName(t *testing.T) { + tests := []struct { + name string + machineName string + template *string + want []gomegatypes.GomegaMatcher + wantErr bool + }{ + { + name: "default template", + machineName: "quick-start-d34gt4-md-0-wqc85-8nxwc-gfd5v", + template: nil, + want: []gomegatypes.GomegaMatcher{ + Equal("quick-start-d34gt4-md-0-wqc85-8nxwc-gfd5v"), + }, + }, + { + name: "template which doesn't respect max length: trim to max length", + machineName: "quick-start-d34gt4-md-0-wqc85-8nxwc-gfd5v", // 41 characters + template: ptr.To[string]("{{ .machine.name }}-{{ .machine.name }}"), + want: []gomegatypes.GomegaMatcher{ + Equal("quick-start-d34gt4-md-0-wqc85-8nxwc-gfd5v-quick-start-d34gt4-md"), // 63 characters + }, + }, + { + name: "template for 20 characters: keep machine name if name has 20 characters", + machineName: "quick-md-8nxwc-gfd5v", // 20 characters + template: ptr.To[string]("{{ if le (len .machine.name) 20 }}{{ .machine.name }}{{else}}{{ trimSuffix \"-\" (trunc 14 .machine.name) }}-{{ trunc -5 .machine.name }}{{end}}"), + want: []gomegatypes.GomegaMatcher{ + Equal("quick-md-8nxwc-gfd5v"), // 20 characters + }, + }, + { + name: "template for 20 characters: trim to 20 characters if name has more than 20 characters", + machineName: "quick-start-d34gt4-md-0-wqc85-8nxwc-gfd5v", // 41 characters + template: ptr.To[string]("{{ if le (len .machine.name) 20 }}{{ .machine.name }}{{else}}{{ trimSuffix \"-\" (trunc 14 .machine.name) }}-{{ trunc -5 .machine.name }}{{end}}"), + want: []gomegatypes.GomegaMatcher{ + Equal("quick-start-d3-gfd5v"), // 20 characters + }, + }, + { + name: "template for 20 characters: trim to 19 characters if name has more than 20 characters and last character of prefix is -", + machineName: "quick-start-d-34gt4-md-0-wqc85-8nxwc-gfd5v", // 42 characters + template: ptr.To[string]("{{ if le (len .machine.name) 20 }}{{ .machine.name }}{{else}}{{ trimSuffix \"-\" (trunc 14 .machine.name) }}-{{ trunc -5 .machine.name }}{{end}}"), + want: []gomegatypes.GomegaMatcher{ + Equal("quick-start-d-gfd5v"), // 19 characters + }, + }, + { + name: "template with a prefix and only 5 random character from the machine name", + machineName: "quick-start-d-34gt4-md-0-wqc85-8nxwc-gfd5v", // 42 characters + template: ptr.To[string]("vm-{{ trunc -5 .machine.name }}"), + want: []gomegatypes.GomegaMatcher{ + Equal("vm-gfd5v"), // 8 characters + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + + got, err := GenerateVSphereVMName(tt.machineName, &v1beta1.VSphereVMNamingStrategy{ + Template: tt.template, + }) + + if (err != nil) != tt.wantErr { + t.Errorf("GenerateVSphereVMName error = %v, wantErr %v", err, tt.wantErr) + return + } + + if len(got) > maxNameLength { + t.Errorf("generated name should never be longer than %d, got %d", maxNameLength, len(got)) + } + + for _, matcher := range tt.want { + g.Expect(got).To(matcher) + } + }) + } +} diff --git a/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/kustomization.yaml b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/kustomization.yaml index 4128896681..62ed6efe0e 100644 --- a/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/kustomization.yaml +++ b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/kustomization.yaml @@ -15,3 +15,6 @@ patches: - target: kind: ClusterClass path: ./patch-namingstrategy.yaml + - target: + kind: VSphereMachineTemplate + path: ./patch-vm-namingstrategy.yaml diff --git a/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/patch-vm-namingstrategy.yaml b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/patch-vm-namingstrategy.yaml new file mode 100644 index 0000000000..805a368fe3 --- /dev/null +++ b/test/e2e/data/infrastructure-vsphere-govmomi/main/clusterclass/patch-vm-namingstrategy.yaml @@ -0,0 +1,4 @@ +- op: add + path: /spec/template/spec/namingStrategy + value: + template: '{{ if le (len .machine.name) 20 }}{{ .machine.name }}{{else}}{{ trimSuffix "-" (trunc 14 .machine.name) }}-{{ trunc -5 .machine.name }}{{end}}' \ No newline at end of file