Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update name validation rules for azurerm_(linux|windows)_virtual_machine #5966

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 76 additions & 44 deletions azurerm/internal/services/compute/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,85 @@ import (
)

func ValidateLinuxName(i interface{}, k string) (warnings []string, errors []error) {
return validateName(64)(i, k)
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("Expected %q to be a string but it wasn't!", k))
return
}

// The value must not be empty.
if strings.TrimSpace(v) == "" {
errors = append(errors, fmt.Errorf("%q must not be empty", k))
return
}

const maxLength = 64
// The value must be between 1 and 64 (Linux) characters long.
if len(v) > maxLength {
errors = append(errors, fmt.Errorf("%q can be at most %d characters, got %d", k, maxLength, len(v)))
}

if strings.HasPrefix(v, "_") {
errors = append(errors, fmt.Errorf("%q cannot begin with an underscore", k))
}

if strings.HasSuffix(v, ".") || strings.HasSuffix(v, "-") {
errors = append(errors, fmt.Errorf("%q cannot end with an period or dash", k))
}

// Azure resource names cannot contain special characters \/""[]:|<>+=;,?*@& or begin with '_' or end with '.' or '-'
specialCharacters := `\/""[]:|<>+=;,?*@&`
if strings.ContainsAny(v, specialCharacters) {
errors = append(errors, fmt.Errorf("%q cannot contain the special characters: `%s`", k, specialCharacters))
}

// The value can only contain alphanumeric characters and can start with a number.
if matched := regexp.MustCompile(`^[a-zA-Z0-9-_.]+$`).Match([]byte(v)); !matched {
errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters, dashes and underscores", k))
}

// Portal: Virtual machine name cannot contain only numbers.
if matched := regexp.MustCompile(`^\d+$`).Match([]byte(v)); matched {
errors = append(errors, fmt.Errorf("%q cannot contain only numbers", k))
}

return warnings, errors
}

func ValidateWindowsName(i interface{}, k string) (warnings []string, errors []error) {
return validateName(16)(i, k)
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("Expected %q to be a string but it wasn't!", k))
return
}

// The value must not be empty.
if strings.TrimSpace(v) == "" {
errors = append(errors, fmt.Errorf("%q must not be empty", k))
return
}

const maxLength = 15
// The value must be between 1 and 15 (Windows) characters long.
if len(v) > maxLength {
errors = append(errors, fmt.Errorf("%q can be at most %d characters, got %d", k, maxLength, len(v)))
}

if strings.HasSuffix(v, "-") {
errors = append(errors, fmt.Errorf("%q cannot end with dash", k))
}

// A windows computer name can only contain alphanumeric characters and hyphens
if matched := regexp.MustCompile(`^[a-zA-Z0-9-]+$`).Match([]byte(v)); !matched {
errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters and dashes", k))
}

// Portal: Virtual machine name cannot contain only numbers.
if matched := regexp.MustCompile(`^\d+$`).Match([]byte(v)); matched {
errors = append(errors, fmt.Errorf("%q cannot contain only numbers", k))
}

return warnings, errors
}

func ValidateScaleSetResourceID(i interface{}, k string) (s []string, es []error) {
Expand All @@ -37,48 +111,6 @@ func ValidateScaleSetResourceID(i interface{}, k string) (s []string, es []error
return
}

func validateName(maxLength int) func(i interface{}, k string) (warnings []string, errors []error) {
return func(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
errors = append(errors, fmt.Errorf("Expected %q to be a string but it wasn't!", k))
return
}

// The value must not be empty.
if strings.TrimSpace(v) == "" {
errors = append(errors, fmt.Errorf("%q must not be empty", k))
return
}

// The value must be between 1 and 64 (Linux) or 16 (Windows) characters long.
if len(v) >= maxLength {
errors = append(errors, fmt.Errorf("%q can be at most %d characters, got %d", k, maxLength-1, len(v)))
}

if strings.HasPrefix(v, "_") {
errors = append(errors, fmt.Errorf("%q cannot begin with an underscore", k))
}

if strings.HasSuffix(v, ".") || strings.HasSuffix(v, "-") {
errors = append(errors, fmt.Errorf("%q cannot end with an period or dash", k))
}

// Azure resource names cannot contain special characters \/""[]:|<>+=;,?*@& or begin with '_' or end with '.' or '-'
specialCharacters := `\/""[]:|<>+=;,?*@&`
if strings.ContainsAny(v, specialCharacters) {
errors = append(errors, fmt.Errorf("%q cannot contain the special characters: `%s`", k, specialCharacters))
}

// The value can only contain alphanumeric characters and cannot start with a number.
if matched := regexp.MustCompile(`^[a-zA-Z0-9-_]+$`).Match([]byte(v)); !matched {
errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters, dashes and underscores", k))
}

return
}
}

func validateDiskEncryptionSetName(i interface{}, k string) (warnings []string, errors []error) {
v, ok := i.(string)
if !ok {
Expand Down
41 changes: 38 additions & 3 deletions azurerm/internal/services/compute/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,34 @@ func TestValidateLinuxName(t *testing.T) {
input: "hello.",
expected: false,
},
{
// can have a dot in the middle
input: "hello.world",
expected: true,
},
{
// start with a number
input: "0abc",
expected: true,
},
{
// cannot contain only numbers
input: "12345",
expected: false,
},
{
// 63 chars
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij",
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk",
expected: true,
},
{
// 64 chars
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk",
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkj",
expected: true,
},
{
// 65 chars
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkj",
input: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkjl",
expected: false,
},
}
Expand Down Expand Up @@ -90,6 +105,11 @@ func TestValidateWindowsName(t *testing.T) {
input: "_hello",
expected: false,
},
{
// can't contain underscore
input: "hello_world",
expected: false,
},
{
// can't end with a dash
input: "hello-",
Expand All @@ -110,6 +130,21 @@ func TestValidateWindowsName(t *testing.T) {
input: "hello.",
expected: false,
},
{
// can't contain dot
input: "hello.world",
expected: false,
},
{
// start with a number
input: "0abc",
expected: true,
},
{
// cannot contain only numbers
input: "12345",
expected: false,
},
{
// 14 chars
input: "abcdefghijklmn",
Expand Down