Skip to content

Commit 8b2d4d5

Browse files
committed
Add validation on clustername
to allow for cluster name to be used as prefix for naming other azure resources - max length of 44 characters - no special characters allowed
1 parent dcbe30d commit 8b2d4d5

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

api/v1alpha3/azurecluster_default_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ func TestVnetDefaults(t *testing.T) {
9090
name: "resource group vnet specified",
9191
cluster: createValidCluster(),
9292
output: &AzureCluster{
93+
ObjectMeta: metav1.ObjectMeta{
94+
Name: "test-cluster",
95+
},
9396
Spec: AzureClusterSpec{
9497
NetworkSpec: NetworkSpec{
9598
Vnet: VnetSpec{

api/v1alpha3/azurecluster_validation.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ import (
2626
)
2727

2828
const (
29+
// can't use: \/"'[]:|<>+=;,.?*@&, Can't start with underscore. Can't end with period or hyphen.
30+
// not using . in the name to avoid issues when the name is part of DNS name
31+
clusterNameRegex = `^[a-z][a-z0-9-]{0,44}[a-z0-9]$`
32+
// max length of 44 to allow for cluster name to be used as a prefix for VMs and other resources that
33+
// have limitations as outlined here https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules
34+
clusterNameMaxLength = 44
2935
// obtained from https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/createorupdate#uri-parameters
3036
resourceGroupRegex = `^[-\w\._\(\)]+$`
3137
// described in https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules
@@ -36,6 +42,7 @@ const (
3642
// validateCluster validates a cluster
3743
func (c *AzureCluster) validateCluster() error {
3844
var allErrs field.ErrorList
45+
allErrs = append(allErrs, c.validateClusterName()...)
3946
allErrs = append(allErrs, c.validateClusterSpec()...)
4047
if len(allErrs) == 0 {
4148
return nil
@@ -53,6 +60,24 @@ func (c *AzureCluster) validateClusterSpec() field.ErrorList {
5360
field.NewPath("spec").Child("networkSpec"))
5461
}
5562

63+
// validateClusterName validates ClusterName
64+
func (c *AzureCluster) validateClusterName() field.ErrorList {
65+
var allErrs field.ErrorList
66+
if len(c.Name) > clusterNameMaxLength {
67+
allErrs = append(allErrs, field.Invalid(field.NewPath("metadata").Child("Name"), c.Name,
68+
fmt.Sprintf("Cluster Name longer than allowed length of %d characters", clusterNameMaxLength)))
69+
}
70+
if success, _ := regexp.MatchString(clusterNameRegex, c.Name); !success {
71+
allErrs = append(allErrs, field.Invalid(field.NewPath("metadata").Child("Name"), c.Name,
72+
fmt.Sprintf("Cluster Name doesn't match regex %s, can contain only lowercase alphanumeric characters and '-', must start/end with an alphanumeric character",
73+
clusterNameRegex)))
74+
}
75+
if len(allErrs) == 0 {
76+
return nil
77+
}
78+
return allErrs
79+
}
80+
5681
// validateNetworkSpec validates a NetworkSpec
5782
func validateNetworkSpec(networkSpec NetworkSpec, fldPath *field.Path) field.ErrorList {
5883
var allErrs field.ErrorList

api/v1alpha3/azurecluster_validation_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,82 @@ import (
2020
"testing"
2121

2222
. "github.com/onsi/gomega"
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2324
"k8s.io/apimachinery/pkg/util/validation/field"
2425
)
2526

27+
func TestClusterNameValidation(t *testing.T) {
28+
g := NewWithT(t)
29+
tests := []struct {
30+
name string
31+
clusterName string
32+
wantErr bool
33+
}{
34+
{
35+
name: "cluster name more than 44 characters",
36+
clusterName: "vegkebfadbczdtevzjiyookobkdgfofjxmlquonomzoes",
37+
wantErr: true,
38+
},
39+
{
40+
name: "cluster name with letters",
41+
clusterName: "cluster",
42+
wantErr: false,
43+
},
44+
{
45+
name: "cluster name with upper case letters",
46+
clusterName: "clusterName",
47+
wantErr: true,
48+
},
49+
{
50+
name: "cluster name with hyphen",
51+
clusterName: "test-cluster",
52+
wantErr: false,
53+
},
54+
{
55+
name: "cluster name with letters and numbers",
56+
clusterName: "clustername1",
57+
wantErr: false,
58+
},
59+
{
60+
name: "cluster name with special characters",
61+
clusterName: "cluster$?name",
62+
wantErr: true,
63+
},
64+
{
65+
name: "cluster name starting with underscore",
66+
clusterName: "_clustername",
67+
wantErr: true,
68+
},
69+
{
70+
name: "cluster name with underscore",
71+
clusterName: "cluster_name",
72+
wantErr: true,
73+
},
74+
{
75+
name: "cluster name with period",
76+
clusterName: "cluster.name",
77+
wantErr: true,
78+
},
79+
}
80+
for _, tc := range tests {
81+
t.Run(tc.name, func(t *testing.T) {
82+
83+
azureCluster := AzureCluster{
84+
ObjectMeta: metav1.ObjectMeta{
85+
Name: tc.clusterName,
86+
},
87+
}
88+
89+
allErrs := azureCluster.validateClusterName()
90+
if tc.wantErr {
91+
g.Expect(allErrs).ToNot(BeNil())
92+
} else {
93+
g.Expect(allErrs).To(BeNil())
94+
}
95+
})
96+
}
97+
}
98+
2699
func TestClusterWithPreexistingVnetValid(t *testing.T) {
27100
g := NewWithT(t)
28101

@@ -539,6 +612,9 @@ func TestIngressRules(t *testing.T) {
539612

540613
func createValidCluster() *AzureCluster {
541614
return &AzureCluster{
615+
ObjectMeta: metav1.ObjectMeta{
616+
Name: "test-cluster",
617+
},
542618
Spec: AzureClusterSpec{
543619
NetworkSpec: createValidNetworkSpec(),
544620
},

docs/development.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ The steps below are provided in a convenient script in [hack/create-dev-cluster.
219219
CLUSTER_NAME=<my-capz-cluster-name> ./hack/create-dev-cluster.sh
220220
```
221221

222+
NOTE: `CLUSTER_NAME` can only include letters, numbers, and hyphens and can't be longer than 44 characters.
223+
222224
##### Building and pushing dev images
223225

224226
1. To build images with custom tags,

0 commit comments

Comments
 (0)