Skip to content

Commit

Permalink
Add plan-time validation of name on google_compute_instance (#118…
Browse files Browse the repository at this point in the history
…86) (#8520)

[upstream:4f8bd9304149a31b696139ce9c5086f3b42e00b9]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Oct 25, 2024
1 parent 16b777a commit 67ddf00
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .changelog/11886.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
compute: added plan-time validation to `name` on `google_compute_instance`
```
10 changes: 6 additions & 4 deletions google-beta/services/compute/resource_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/verify"

compute "google.golang.org/api/compute/v0.beta"
)
Expand Down Expand Up @@ -389,10 +390,11 @@ func ResourceComputeInstance() *schema.Resource {
},

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `The name of the instance. One of name or self_link must be provided.`,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: verify.ValidateRFC1035Name(1, 63),
Description: `The name of the instance. One of name or self_link must be provided.`,
},

"network_interface": {
Expand Down
35 changes: 21 additions & 14 deletions google-beta/verify/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (

SubnetworkLinkRegex = "projects/(" + ProjectRegex + ")/regions/(" + RegionRegex + ")/subnetworks/(" + SubnetworkRegex + ")$"

RFC1035NameTemplate = "[a-z](?:[-a-z0-9]{%d,%d}[a-z0-9])"
RFC1035NameTemplate = "[a-z]([-a-z0-9]%v[a-z0-9])?"
CloudIoTIdRegex = "^[a-zA-Z][-a-zA-Z0-9._+~%]{2,254}$"

// Format of default Compute service accounts created by Google
Expand All @@ -43,7 +43,7 @@ var (
// The first and last characters have different restrictions, than
// the middle characters. The middle characters length must be between
// 4 and 28 since the first and last character are excluded.
ServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, 4, 28)
ServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, "{4,28}")

ServiceAccountLinkRegexPrefix = "projects/" + ProjectRegexWildCard + "/serviceAccounts/"
PossibleServiceAccountNames = []string{
Expand All @@ -56,7 +56,7 @@ var (
ServiceAccountKeyNameRegex = ServiceAccountLinkRegexPrefix + "(.+)/keys/(.+)"

// Format of service accounts created through the API
CreatedServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, 4, 28) + "@" + ProjectNameInDNSFormRegex + "\\.iam\\.gserviceaccount\\.com$"
CreatedServiceAccountNameRegex = fmt.Sprintf(RFC1035NameTemplate, "{4,28}") + "@" + ProjectNameInDNSFormRegex + "\\.iam\\.gserviceaccount\\.com$"

// Format of service-created service account
// examples are:
Expand Down Expand Up @@ -196,19 +196,26 @@ func ValidateRFC3339Time(v interface{}, k string) (warnings []string, errors []e
}

func ValidateRFC1035Name(min, max int) schema.SchemaValidateFunc {
if min < 2 || max < min {
return func(i interface{}, k string) (s []string, errors []error) {
if min < 2 {
errors = append(errors, fmt.Errorf("min must be at least 2. Got: %d", min))
}
if max < min {
errors = append(errors, fmt.Errorf("max must greater than min. Got [%d, %d]", min, max))
}
return
return func(i interface{}, k string) (s []string, errors []error) {
value := i.(string)
re := fmt.Sprintf("^"+RFC1035NameTemplate+"$", "*")
if min < 1 {
errors = append(errors, fmt.Errorf("min must be at least 1. Got: %d", min))
}
if max < min {
errors = append(errors, fmt.Errorf("max must greater than min. Got [%d, %d]", min, max))
}

if len(value) < min || len(value) > max {
errors = append(errors, fmt.Errorf("%q (%q) must be between %d and %d characters long", k, value, min, max))
}

if !regexp.MustCompile(re).MatchString(value) {
errors = append(errors, fmt.Errorf("%q (%q) must match regex %q", k, value, re))
}
}

return ValidateRegexp(fmt.Sprintf("^"+RFC1035NameTemplate+"$", min-2, max-2))
return
}
}

func ValidateIpCidrRange(v interface{}, k string) (warnings []string, errors []error) {
Expand Down
8 changes: 7 additions & 1 deletion google-beta/verify/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,18 @@ func TestValidateRFC1035Name(t *testing.T) {
{TestName: "valid lower bound", Min: 12, Max: 30, Value: "a-valid-name"},
{TestName: "valid upper bound", Min: 6, Max: 12, Value: "a-valid-name"},
{TestName: "valid with numbers", Min: 6, Max: 30, Value: "valid000-name"},
{TestName: "valid shortest", Min: 1, Max: 63, Value: "a"},
{TestName: "valid longest", Min: 1, Max: 63, Value: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
{TestName: "must start with a letter", Min: 6, Max: 10, Value: "0invalid", ExpectError: true},
{TestName: "cannot end with a dash", Min: 6, Max: 10, Value: "invalid-", ExpectError: true},
{TestName: "too short", Min: 6, Max: 10, Value: "short", ExpectError: true},
{TestName: "too long", Min: 6, Max: 10, Value: "toolooooong", ExpectError: true},
{TestName: "min too small", Min: 1, Max: 10, Value: "", ExpectError: true},
{TestName: "min too small", Min: 0, Max: 10, Value: "", ExpectError: true},
{TestName: "min < max", Min: 6, Max: 5, Value: "", ExpectError: true},
{TestName: "min < max", Min: 6, Max: 5, Value: "", ExpectError: true},
{TestName: "invalid smallest possible w/ higher limit", Min: 2, Max: 63, Value: "a", ExpectError: true},
{TestName: "invalid smallest possible hyphen", Min: 1, Max: 1, Value: "-", ExpectError: true},
{TestName: "invalid smallest possible ends with hyphen", Min: 2, Max: 63, Value: "a-", ExpectError: true},
}

for _, c := range cases {
Expand Down

0 comments on commit 67ddf00

Please sign in to comment.