diff --git a/google/resource_compute_subnetwork.go b/google/resource_compute_subnetwork.go index 1a254972..5105bb4c 100644 --- a/google/resource_compute_subnetwork.go +++ b/google/resource_compute_subnetwork.go @@ -7,9 +7,17 @@ import ( "strings" "github.com/hashicorp/terraform/helper/schema" + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" ) +var ( + SubnetworkBaseApiVersion = v1 + SubnetworkVersionedFeatures = []Feature{ + {Version: v0beta, Item: "secondary_ip_range"}, + } +) + func resourceComputeSubnetwork() *schema.Resource { return &schema.Resource{ Create: resourceComputeSubnetworkCreate, @@ -46,6 +54,11 @@ func resourceComputeSubnetwork() *schema.Resource { ForceNew: true, }, + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "gateway_address": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -73,19 +86,16 @@ func resourceComputeSubnetwork() *schema.Resource { "secondary_ip_range": &schema.Schema{ Type: schema.TypeList, Optional: true, - ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "range_name": &schema.Schema{ Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: validateGCPName, }, "ip_cidr_range": &schema.Schema{ Type: schema.TypeString, Required: true, - ForceNew: true, }, }, }, @@ -151,6 +161,11 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e } func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) error { + computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures) + if computeApiVersion == v0beta { + return resourceComputeSubnetworkReadV0Beta(d, meta) + } + config := meta.(*Config) region, err := getRegion(d, config) @@ -184,7 +199,43 @@ func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) err return nil } +func resourceComputeSubnetworkReadV0Beta(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + region, err := getRegion(d, config) + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + + name := d.Get("name").(string) + + subnetwork, err := config.clientComputeBeta.Subnetworks.Get(project, region, name).Do() + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("Subnetwork %q", name)) + } + + d.Set("name", subnetwork.Name) + d.Set("ip_cidr_range", subnetwork.IpCidrRange) + d.Set("network", subnetwork.Network) + d.Set("description", subnetwork.Description) + d.Set("private_ip_google_access", subnetwork.PrivateIpGoogleAccess) + d.Set("gateway_address", subnetwork.GatewayAddress) + d.Set("secondary_ip_range", flattenSecondaryRangesV0Beta(subnetwork.SecondaryIpRanges)) + d.Set("project", project) + d.Set("region", region) + d.Set("self_link", ConvertSelfLinkToV1(subnetwork.SelfLink)) + d.Set("fingerprint", subnetwork.Fingerprint) + + return nil +} + func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) error { + computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures) config := meta.(*Config) region, err := getRegion(d, config) @@ -221,6 +272,26 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("private_ip_google_access") } + if d.HasChange("secondary_ip_range") && computeApiVersion == v0beta { + v0BetaSubnetwork := &computeBeta.Subnetwork{ + SecondaryIpRanges: expandSecondaryRangesV0Beta(d.Get("secondary_ip_range").([]interface{})), + Fingerprint: d.Get("fingerprint").(string), + } + + op, err := config.clientComputeBeta.Subnetworks.Patch( + project, region, d.Get("name").(string), v0BetaSubnetwork).Do() + if err != nil { + return fmt.Errorf("Error updating subnetwork SecondaryIpRanges: %s", err) + } + + err = computeSharedOperationWait(config.clientCompute, op, project, "Updating Subnetwork SecondaryIpRanges") + if err != nil { + return err + } + + d.SetPartial("secondary_ip_range") + } + d.Partial(false) return resourceComputeSubnetworkRead(d, meta) @@ -298,6 +369,20 @@ func expandSecondaryRanges(configured []interface{}) []*compute.SubnetworkSecond return secondaryRanges } +func expandSecondaryRangesV0Beta(configured []interface{}) []*computeBeta.SubnetworkSecondaryRange { + secondaryRanges := make([]*computeBeta.SubnetworkSecondaryRange, 0, len(configured)) + for _, raw := range configured { + data := raw.(map[string]interface{}) + secondaryRange := computeBeta.SubnetworkSecondaryRange{ + RangeName: data["range_name"].(string), + IpCidrRange: data["ip_cidr_range"].(string), + } + + secondaryRanges = append(secondaryRanges, &secondaryRange) + } + return secondaryRanges +} + func flattenSecondaryRanges(secondaryRanges []*compute.SubnetworkSecondaryRange) []map[string]interface{} { secondaryRangesSchema := make([]map[string]interface{}, 0, len(secondaryRanges)) for _, secondaryRange := range secondaryRanges { @@ -310,3 +395,16 @@ func flattenSecondaryRanges(secondaryRanges []*compute.SubnetworkSecondaryRange) } return secondaryRangesSchema } + +func flattenSecondaryRangesV0Beta(secondaryRanges []*computeBeta.SubnetworkSecondaryRange) []map[string]interface{} { + secondaryRangesSchema := make([]map[string]interface{}, 0, len(secondaryRanges)) + for _, secondaryRange := range secondaryRanges { + data := map[string]interface{}{ + "range_name": secondaryRange.RangeName, + "ip_cidr_range": secondaryRange.IpCidrRange, + } + + secondaryRangesSchema = append(secondaryRangesSchema, data) + } + return secondaryRangesSchema +} diff --git a/google/resource_compute_subnetwork_test.go b/google/resource_compute_subnetwork_test.go index bc081185..78bacb6b 100644 --- a/google/resource_compute_subnetwork_test.go +++ b/google/resource_compute_subnetwork_test.go @@ -74,6 +74,46 @@ func TestAccComputeSubnetwork_update(t *testing.T) { } } +func TestAccComputeSubnetwork_secondaryIpRangesUpdate(t *testing.T) { + t.Parallel() + + var subnetwork compute.Subnetwork + + cnName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + subnetworkName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSubnetworkDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeSubnetwork_secondaryIpRanges_update1(cnName, subnetworkName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSubnetworkExists("google_compute_subnetwork.network-with-private-secondary-ip-ranges", &subnetwork), + testAccCheckComputeSubnetworkHasSecondaryIpRange(&subnetwork, "tf-test-secondary-range-update1", "192.168.10.0/24"), + ), + }, + resource.TestStep{ + Config: testAccComputeSubnetwork_secondaryIpRanges_update2(cnName, subnetworkName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSubnetworkExists("google_compute_subnetwork.network-with-private-secondary-ip-ranges", &subnetwork), + testAccCheckComputeSubnetworkHasSecondaryIpRange(&subnetwork, "tf-test-secondary-range-update1", "192.168.10.0/24"), + testAccCheckComputeSubnetworkHasSecondaryIpRange(&subnetwork, "tf-test-secondary-range-update2", "192.168.11.0/24"), + ), + }, + resource.TestStep{ + Config: testAccComputeSubnetwork_secondaryIpRanges_update3(cnName, subnetworkName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeSubnetworkExists("google_compute_subnetwork.network-with-private-secondary-ip-ranges", &subnetwork), + testAccCheckComputeSubnetworkHasSecondaryIpRange(&subnetwork, "tf-test-secondary-range-update1", "192.168.10.0/24"), + testAccCheckComputeSubnetworkHasNotSecondaryIpRange(&subnetwork, "tf-test-secondary-range-update2", "192.168.11.0/24"), + ), + }, + }, + }) +} + func TestAccComputeSubnetwork_secondaryIpRanges(t *testing.T) { t.Parallel() @@ -162,6 +202,20 @@ func testAccCheckComputeSubnetworkHasSecondaryIpRange(subnetwork *compute.Subnet } } +func testAccCheckComputeSubnetworkHasNotSecondaryIpRange(subnetwork *compute.Subnetwork, rangeName, ipCidrRange string) resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, secondaryRange := range subnetwork.SecondaryIpRanges { + if secondaryRange.RangeName == rangeName { + if secondaryRange.IpCidrRange == ipCidrRange { + return fmt.Errorf("Secondary range %s has the wrong ip_cidr_range. Expected %s, got %s", rangeName, ipCidrRange, secondaryRange.IpCidrRange) + } + } + } + + return nil + } +} + func testAccComputeSubnetwork_basic(cnName, subnetwork1Name, subnetwork2Name, subnetwork3Name string) string { return fmt.Sprintf(` resource "google_compute_network" "custom-test" { @@ -246,3 +300,67 @@ resource "google_compute_subnetwork" "network-with-private-secondary-ip-range" { } `, cnName, subnetworkName) } + +func testAccComputeSubnetwork_secondaryIpRanges_update1(cnName, subnetworkName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "custom-test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "network-with-private-secondary-ip-ranges" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = "${google_compute_network.custom-test.self_link}" + secondary_ip_range { + range_name = "tf-test-secondary-range-update1" + ip_cidr_range = "192.168.10.0/24" + } +} +`, cnName, subnetworkName) +} + +func testAccComputeSubnetwork_secondaryIpRanges_update2(cnName, subnetworkName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "custom-test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "network-with-private-secondary-ip-ranges" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = "${google_compute_network.custom-test.self_link}" + secondary_ip_range { + range_name = "tf-test-secondary-range-update1" + ip_cidr_range = "192.168.10.0/24" + } + secondary_ip_range { + range_name = "tf-test-secondary-range-update2" + ip_cidr_range = "192.168.11.0/24" + }, +} +`, cnName, subnetworkName) +} + +func testAccComputeSubnetwork_secondaryIpRanges_update3(cnName, subnetworkName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "custom-test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "network-with-private-secondary-ip-ranges" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = "${google_compute_network.custom-test.self_link}" + secondary_ip_range { + range_name = "tf-test-secondary-range-update1" + ip_cidr_range = "192.168.10.0/24" + } +} +`, cnName, subnetworkName) +}