diff --git a/google/data_source_google_compute_address.go b/google/data_source_google_compute_address.go index 40fcef73..137c4157 100644 --- a/google/data_source_google_compute_address.go +++ b/google/data_source_google_compute_address.go @@ -2,11 +2,18 @@ package google import ( "fmt" + "regexp" "strconv" + "strings" "github.com/hashicorp/terraform/helper/schema" ) +var ( + computeAddressIdTemplate = "projects/%s/regions/%s/addresses/%s" + computeAddressLinkRegex = regexp.MustCompile("projects/(.+)/regions/(.+)/addresses/(.+)$") +) + func dataSourceGoogleComputeAddress() *schema.Resource { return &schema.Resource{ Read: dataSourceGoogleComputeAddressRead, @@ -74,3 +81,63 @@ func dataSourceGoogleComputeAddressRead(d *schema.ResourceData, meta interface{} d.SetId(strconv.FormatUint(uint64(address.Id), 10)) return nil } + +type computeAddressId struct { + Project string + Region string + Name string +} + +func (s computeAddressId) canonicalId() string { + return fmt.Sprintf(computeAddressIdTemplate, s.Project, s.Region, s.Name) +} + +func parseComputeAddressId(id string, config *Config) (*computeAddressId, error) { + var parts []string + if computeAddressLinkRegex.MatchString(id) { + parts = computeAddressLinkRegex.FindStringSubmatch(id) + + return &computeAddressId{ + Project: parts[1], + Region: parts[2], + Name: parts[3], + }, nil + } else { + parts = strings.Split(id, "/") + } + + if len(parts) == 3 { + return &computeAddressId{ + Project: parts[0], + Region: parts[1], + Name: parts[2], + }, nil + } else if len(parts) == 2 { + // Project is optional. + if config.Project == "" { + return nil, fmt.Errorf("The default project for the provider must be set when using the `{region}/{name}` id format.") + } + + return &computeAddressId{ + Project: config.Project, + Region: parts[0], + Name: parts[1], + }, nil + } else if len(parts) == 1 { + // Project and region is optional + if config.Project == "" { + return nil, fmt.Errorf("The default project for the provider must be set when using the `{name}` id format.") + } + if config.Region == "" { + return nil, fmt.Errorf("The default region for the provider must be set when using the `{name}` id format.") + } + + return &computeAddressId{ + Project: config.Project, + Region: config.Region, + Name: parts[0], + }, nil + } + + return nil, fmt.Errorf("Invalid compute address id. Expecting resource link, `{project}/{region}/{name}`, `{region}/{name}` or `{name}` format.") +} diff --git a/google/data_source_google_compute_address_test.go b/google/data_source_google_compute_address_test.go index 94f2fff1..9f1e9798 100644 --- a/google/data_source_google_compute_address_test.go +++ b/google/data_source_google_compute_address_test.go @@ -8,6 +8,66 @@ import ( "github.com/hashicorp/terraform/terraform" ) +func TestComputeAddressIdParsing(t *testing.T) { + cases := map[string]struct { + ImportId string + ExpectedError bool + ExpectedCanonicalId string + Config *Config + }{ + "id is a full self link": { + ImportId: "https://www.googleapis.com/compute/v1/projects/test-project/regions/us-central1/addresses/test-address", + ExpectedError: false, + ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", + }, + "id is a partial self link": { + ImportId: "projects/test-project/regions/us-central1/addresses/test-address", + ExpectedError: false, + ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", + }, + "id is project/region/address": { + ImportId: "test-project/us-central1/test-address", + ExpectedError: false, + ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", + }, + "id is region/address": { + ImportId: "us-central1/test-address", + ExpectedError: false, + ExpectedCanonicalId: "projects/default-project/regions/us-central1/addresses/test-address", + Config: &Config{Project: "default-project"}, + }, + "id is address": { + ImportId: "test-address", + ExpectedError: false, + ExpectedCanonicalId: "projects/default-project/regions/us-east1/addresses/test-address", + Config: &Config{Project: "default-project", Region: "us-east1"}, + }, + "id has invalid format": { + ImportId: "i/n/v/a/l/i/d", + ExpectedError: true, + }, + } + + for tn, tc := range cases { + addressId, err := parseComputeAddressId(tc.ImportId, tc.Config) + + if tc.ExpectedError && err == nil { + t.Fatalf("bad: %s, expected an error", tn) + } + + if err != nil { + if tc.ExpectedError { + continue + } + t.Fatalf("bad: %s, err: %#v", tn, err) + } + + if addressId.canonicalId() != tc.ExpectedCanonicalId { + t.Fatalf("bad: %s, expected canonical id to be `%s` but is `%s`", tn, tc.ExpectedCanonicalId, addressId.canonicalId()) + } + } +} + func TestAccDataSourceComputeAddress(t *testing.T) { t.Parallel() diff --git a/google/resource_compute_address.go b/google/resource_compute_address.go index 170177cb..647789ba 100644 --- a/google/resource_compute_address.go +++ b/google/resource_compute_address.go @@ -3,8 +3,6 @@ package google import ( "fmt" - "regexp" - "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" computeBeta "google.golang.org/api/compute/v0.beta" @@ -15,11 +13,6 @@ const ( addressTypeInternal = "INTERNAL" ) -var ( - computeAddressIdTemplate = "projects/%s/regions/%s/addresses/%s" - computeAddressLinkRegex = regexp.MustCompile("projects/(.+)/regions/(.+)/addresses/(.+)$") -) - func resourceComputeAddress() *schema.Resource { return &schema.Resource{ Create: resourceComputeAddressCreate, @@ -29,9 +22,6 @@ func resourceComputeAddress() *schema.Resource { State: resourceComputeAddressImportState, }, - SchemaVersion: 1, - MigrateState: resourceComputeAddressMigrateState, - Schema: map[string]*schema.Schema{ "name": &schema.Schema{ Type: schema.TypeString, diff --git a/google/resource_compute_address_migrate.go b/google/resource_compute_address_migrate.go deleted file mode 100644 index 036ef194..00000000 --- a/google/resource_compute_address_migrate.go +++ /dev/null @@ -1,109 +0,0 @@ -package google - -import ( - "fmt" - "github.com/hashicorp/terraform/terraform" - "log" - "strings" -) - -func resourceComputeAddressMigrateState(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { - if is.Empty() { - log.Println("[DEBUG] Empty InstanceState; nothing to migrate.") - return is, nil - } - - switch v { - case 0: - log.Println("[INFO] Found Container Node Pool State v0; migrating to v1") - return migrateComputeAddressV0toV1(is, meta) - default: - return is, fmt.Errorf("Unexpected schema version: %d", v) - } -} - -func migrateComputeAddressV0toV1(is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { - log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes) - log.Printf("[DEBUG] ID before migration: %s", is.ID) - - config := meta.(*Config) - - project, err := getProjectFromInstanceState(is, config) - if err != nil { - return is, err - } - - region, err := getRegionFromInstanceState(is, config) - if err != nil { - return is, err - } - - is.ID = computeAddressId{ - Project: project, - Region: region, - Name: is.Attributes["name"], - }.canonicalId() - - log.Printf("[DEBUG] ID after migration: %s", is.ID) - return is, nil -} - -type computeAddressId struct { - Project string - Region string - Name string -} - -func (s computeAddressId) canonicalId() string { - return fmt.Sprintf(computeAddressIdTemplate, s.Project, s.Region, s.Name) -} - -func parseComputeAddressId(id string, config *Config) (*computeAddressId, error) { - var parts []string - if computeAddressLinkRegex.MatchString(id) { - parts = computeAddressLinkRegex.FindStringSubmatch(id) - - return &computeAddressId{ - Project: parts[1], - Region: parts[2], - Name: parts[3], - }, nil - } else { - parts = strings.Split(id, "/") - } - - if len(parts) == 3 { - return &computeAddressId{ - Project: parts[0], - Region: parts[1], - Name: parts[2], - }, nil - } else if len(parts) == 2 { - // Project is optional. - if config.Project == "" { - return nil, fmt.Errorf("The default project for the provider must be set when using the `{region}/{name}` id format.") - } - - return &computeAddressId{ - Project: config.Project, - Region: parts[0], - Name: parts[1], - }, nil - } else if len(parts) == 1 { - // Project and region is optional - if config.Project == "" { - return nil, fmt.Errorf("The default project for the provider must be set when using the `{name}` id format.") - } - if config.Region == "" { - return nil, fmt.Errorf("The default region for the provider must be set when using the `{name}` id format.") - } - - return &computeAddressId{ - Project: config.Project, - Region: config.Region, - Name: parts[0], - }, nil - } - - return nil, fmt.Errorf("Invalid compute address id. Expecting resource link, `{project}/{region}/{name}`, `{region}/{name}` or `{name}` format.") -} diff --git a/google/resource_compute_address_migrate_test.go b/google/resource_compute_address_migrate_test.go deleted file mode 100644 index d0d09e09..00000000 --- a/google/resource_compute_address_migrate_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package google - -import ( - "github.com/hashicorp/terraform/terraform" - "testing" -) - -func TestComputeAddressMigrateState(t *testing.T) { - cases := map[string]struct { - StateVersion int - Attributes map[string]string - ExpectedId string - Meta interface{} - }{ - "update id from name to region/name": { - StateVersion: 0, - Attributes: map[string]string{ - "name": "address-1", - }, - ExpectedId: "projects/gcp-project/regions/us-central1/addresses/address-1", - Meta: &Config{Region: "us-central1", Project: "gcp-project"}, - }, - } - - for tn, tc := range cases { - is := &terraform.InstanceState{ - ID: tc.Attributes["name"], - Attributes: tc.Attributes, - } - - is, err := resourceComputeAddressMigrateState(tc.StateVersion, is, tc.Meta) - - if err != nil { - t.Fatalf("bad: %s, err: %#v", tn, err) - } - - if is.ID != tc.ExpectedId { - t.Fatalf("Id should be set to `%s` but is `%s`", tc.ExpectedId, is.ID) - } - } -} - -func TestComputeAddressMigrateState_empty(t *testing.T) { - var is *terraform.InstanceState - var meta *Config - - // should handle nil - is, err := resourceComputeAddressMigrateState(0, is, meta) - - if err != nil { - t.Fatalf("err: %#v", err) - } - - if is != nil { - t.Fatalf("expected nil instancestate, got: %#v", is) - } - - // should handle non-nil but empty - is = &terraform.InstanceState{} - is, err = resourceComputeAddressMigrateState(0, is, meta) - - if err != nil { - t.Fatalf("err: %#v", err) - } -} diff --git a/google/resource_compute_address_test.go b/google/resource_compute_address_test.go index ed17ad93..ae006cec 100644 --- a/google/resource_compute_address_test.go +++ b/google/resource_compute_address_test.go @@ -11,70 +11,6 @@ import ( "google.golang.org/api/compute/v1" ) -// Unit tests - -func TestComputeAddressIdParsing(t *testing.T) { - cases := map[string]struct { - ImportId string - ExpectedError bool - ExpectedCanonicalId string - Config *Config - }{ - "id is a full self link": { - ImportId: "https://www.googleapis.com/compute/v1/projects/test-project/regions/us-central1/addresses/test-address", - ExpectedError: false, - ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", - }, - "id is a partial self link": { - ImportId: "projects/test-project/regions/us-central1/addresses/test-address", - ExpectedError: false, - ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", - }, - "id is project/region/address": { - ImportId: "test-project/us-central1/test-address", - ExpectedError: false, - ExpectedCanonicalId: "projects/test-project/regions/us-central1/addresses/test-address", - }, - "id is region/address": { - ImportId: "us-central1/test-address", - ExpectedError: false, - ExpectedCanonicalId: "projects/default-project/regions/us-central1/addresses/test-address", - Config: &Config{Project: "default-project"}, - }, - "id is address": { - ImportId: "test-address", - ExpectedError: false, - ExpectedCanonicalId: "projects/default-project/regions/us-east1/addresses/test-address", - Config: &Config{Project: "default-project", Region: "us-east1"}, - }, - "id has invalid format": { - ImportId: "i/n/v/a/l/i/d", - ExpectedError: true, - }, - } - - for tn, tc := range cases { - addressId, err := parseComputeAddressId(tc.ImportId, tc.Config) - - if tc.ExpectedError && err == nil { - t.Fatalf("bad: %s, expected an error", tn) - } - - if err != nil { - if tc.ExpectedError { - continue - } - t.Fatalf("bad: %s, err: %#v", tn, err) - } - - if addressId.canonicalId() != tc.ExpectedCanonicalId { - t.Fatalf("bad: %s, expected canonical id to be `%s` but is `%s`", tn, tc.ExpectedCanonicalId, addressId.canonicalId()) - } - } -} - -// Acceptance tests - func TestAccComputeAddress_basic(t *testing.T) { t.Parallel()