From 68f2e3528cdc0b5c041787f82aaf5ac5dfbbc91b Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Fri, 4 Aug 2017 10:53:43 -0700 Subject: [PATCH] Add Beta support & Beta feature ip_version to google_compute_global_address (#250) * Make google_compute_global_address a versioned resource with Beta support. * Added Beta support for ip_version in google_compute_global_address. * Move checks to TestCheckFuncs, add a regression test for IPV4 on v1 resources. * Consolidated TestCheckFuncs to a single function. * Add missing return statement. * Fix IPV4 test * Clarified comment. --- google/resource_compute_global_address.go | 108 ++++++++++++++---- .../resource_compute_global_address_test.go | 85 ++++++++++++++ .../r/compute_global_address.html.markdown | 5 + 3 files changed, 178 insertions(+), 20 deletions(-) diff --git a/google/resource_compute_global_address.go b/google/resource_compute_global_address.go index 1667771b..a5ac8856 100644 --- a/google/resource_compute_global_address.go +++ b/google/resource_compute_global_address.go @@ -5,9 +5,15 @@ import ( "log" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" ) +var GlobalAddressBaseApiVersion = v1 +var GlobalAddressVersionedFeatures = []Feature{Feature{Version: v0beta, Item: "ip_version"}} + func resourceComputeGlobalAddress() *schema.Resource { return &schema.Resource{ Create: resourceComputeGlobalAddressCreate, @@ -16,6 +22,7 @@ func resourceComputeGlobalAddress() *schema.Resource { Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, + Schema: map[string]*schema.Schema{ "name": &schema.Schema{ Type: schema.TypeString, @@ -23,9 +30,11 @@ func resourceComputeGlobalAddress() *schema.Resource { ForceNew: true, }, - "address": &schema.Schema{ - Type: schema.TypeString, - Computed: true, + "ip_version": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV6"}, false), }, "project": &schema.Schema{ @@ -34,6 +43,11 @@ func resourceComputeGlobalAddress() *schema.Resource { ForceNew: true, }, + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "self_link": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -43,6 +57,7 @@ func resourceComputeGlobalAddress() *schema.Resource { } func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{}) error { + computeApiVersion := getComputeApiVersion(d, GlobalAddressBaseApiVersion, GlobalAddressVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -51,17 +66,41 @@ func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{} } // Build the address parameter - addr := &compute.Address{Name: d.Get("name").(string)} - op, err := config.clientCompute.GlobalAddresses.Insert( - project, addr).Do() - if err != nil { - return fmt.Errorf("Error creating address: %s", err) + addr := &computeBeta.Address{ + Name: d.Get("name").(string), + IpVersion: d.Get("ip_version").(string), + } + + var op interface{} + switch computeApiVersion { + case v1: + v1Addr := &compute.Address{} + err = Convert(addr, v1Addr) + if err != nil { + return err + } + + op, err = config.clientCompute.GlobalAddresses.Insert(project, v1Addr).Do() + if err != nil { + return fmt.Errorf("Error creating address: %s", err) + } + case v0beta: + v0BetaAddr := &computeBeta.Address{} + err = Convert(addr, v0BetaAddr) + if err != nil { + return err + } + + op, err = config.clientComputeBeta.GlobalAddresses.Insert(project, v0BetaAddr).Do() + if err != nil { + return fmt.Errorf("Error creating address: %s", err) + } } // It probably maybe worked, so store the ID now d.SetId(addr.Name) - err = computeOperationWait(config, op, project, "Creating Global Address") + err = computeSharedOperationWait(config, op, project, "Creating Global Address") if err != nil { return err } @@ -70,6 +109,7 @@ func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{} } func resourceComputeGlobalAddressRead(d *schema.ResourceData, meta interface{}) error { + computeApiVersion := getComputeApiVersion(d, GlobalAddressBaseApiVersion, GlobalAddressVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -77,20 +117,40 @@ func resourceComputeGlobalAddressRead(d *schema.ResourceData, meta interface{}) return err } - addr, err := config.clientCompute.GlobalAddresses.Get( - project, d.Id()).Do() - if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("Global Address %q", d.Get("name").(string))) + addr := &computeBeta.Address{} + switch computeApiVersion { + case v1: + v1Addr, err := config.clientCompute.GlobalAddresses.Get(project, d.Id()).Do() + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("Global Address %q", d.Get("name").(string))) + } + + err = Convert(v1Addr, addr) + if err != nil { + return err + } + case v0beta: + v0BetaAddr, err := config.clientComputeBeta.GlobalAddresses.Get(project, d.Id()).Do() + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("Global Address %q", d.Get("name").(string))) + } + + err = Convert(v0BetaAddr, addr) + if err != nil { + return err + } } - d.Set("address", addr.Address) - d.Set("self_link", addr.SelfLink) d.Set("name", addr.Name) + d.Set("ip_version", addr.IpVersion) + d.Set("address", addr.Address) + d.Set("self_link", ConvertSelfLinkToV1(addr.SelfLink)) return nil } func resourceComputeGlobalAddressDelete(d *schema.ResourceData, meta interface{}) error { + computeApiVersion := getComputeApiVersion(d, GlobalAddressBaseApiVersion, GlobalAddressVersionedFeatures) config := meta.(*Config) project, err := getProject(d, config) @@ -100,13 +160,21 @@ func resourceComputeGlobalAddressDelete(d *schema.ResourceData, meta interface{} // Delete the address log.Printf("[DEBUG] address delete request") - op, err := config.clientCompute.GlobalAddresses.Delete( - project, d.Id()).Do() - if err != nil { - return fmt.Errorf("Error deleting address: %s", err) + var op interface{} + switch computeApiVersion { + case v1: + op, err = config.clientCompute.GlobalAddresses.Delete(project, d.Id()).Do() + if err != nil { + return fmt.Errorf("Error deleting address: %s", err) + } + case v0beta: + op, err = config.clientComputeBeta.GlobalAddresses.Delete(project, d.Id()).Do() + if err != nil { + return fmt.Errorf("Error deleting address: %s", err) + } } - err = computeOperationWait(config, op, project, "Deleting Global Address") + err = computeSharedOperationWait(config, op, project, "Deleting Global Address") if err != nil { return err } diff --git a/google/resource_compute_global_address_test.go b/google/resource_compute_global_address_test.go index 9ed49d83..aa91748c 100644 --- a/google/resource_compute_global_address_test.go +++ b/google/resource_compute_global_address_test.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" + + computeBeta "google.golang.org/api/compute/v0.beta" "google.golang.org/api/compute/v1" ) @@ -23,6 +25,29 @@ func TestAccComputeGlobalAddress_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeGlobalAddressExists( "google_compute_global_address.foobar", &addr), + + // implicitly IPV4 - if we don't send an ip_version, we don't get one back even when using Beta apis + testAccCheckComputeBetaGlobalAddressIpVersion("google_compute_global_address.foobar", ""), + ), + }, + }, + }) +} + +func TestAccComputeGlobalAddress_ipv6(t *testing.T) { + var addr computeBeta.Address + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeGlobalAddressDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeGlobalAddress_ipv6, + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeBetaGlobalAddressExists( + "google_compute_global_address.foobar", &addr), + testAccCheckComputeBetaGlobalAddressIpVersion("google_compute_global_address.foobar", "IPV6"), ), }, }, @@ -76,7 +101,67 @@ func testAccCheckComputeGlobalAddressExists(n string, addr *compute.Address) res } } +func testAccCheckComputeBetaGlobalAddressExists(n string, addr *computeBeta.Address) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + found, err := config.clientComputeBeta.GlobalAddresses.Get(config.Project, rs.Primary.ID).Do() + if err != nil { + return err + } + + if found.Name != rs.Primary.ID { + return fmt.Errorf("Addr not found") + } + + *addr = *found + + return nil + } +} + +func testAccCheckComputeBetaGlobalAddressIpVersion(n, version string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + + addr, err := config.clientComputeBeta.GlobalAddresses.Get(config.Project, rs.Primary.ID).Do() + if err != nil { + return err + } + + if addr.IpVersion != version { + return fmt.Errorf("Expected IP version to be %s, got %s", version, addr.IpVersion) + } + + return nil + } +} + var testAccComputeGlobalAddress_basic = fmt.Sprintf(` resource "google_compute_global_address" "foobar" { name = "address-test-%s" }`, acctest.RandString(10)) + +var testAccComputeGlobalAddress_ipv6 = fmt.Sprintf(` +resource "google_compute_global_address" "foobar" { + name = "address-test-%s" + ip_version = "IPV6" +}`, acctest.RandString(10)) diff --git a/website/docs/r/compute_global_address.html.markdown b/website/docs/r/compute_global_address.html.markdown index 231b0d5d..7899d9dd 100644 --- a/website/docs/r/compute_global_address.html.markdown +++ b/website/docs/r/compute_global_address.html.markdown @@ -33,6 +33,11 @@ The following arguments are supported: * `project` - (Optional) The project in which the resource belongs. If it is not provided, the provider project is used. +- - - + +* `ip_version` - (Optional, Beta) The IP Version that will be used by this address. +One of `"IPV4"` or `"IPV6"`. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are