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

Add Beta support & Beta feature ip_version to google_compute_global_address #250

Merged
merged 7 commits into from
Aug 4, 2017
Merged
Show file tree
Hide file tree
Changes from 2 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
19 changes: 19 additions & 0 deletions google/compute_shared_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@ import (
"google.golang.org/api/compute/v1"
)

func computeSharedOperationWait(config *Config, op interface{}, project string, activity string) error {
return computeSharedOperationWaitTime(config, op, project, 4, activity)
}

func computeSharedOperationWaitTime(config *Config, op interface{}, project string, minutes int, activity string) error {
if op == nil {
panic("Attempted to wait on an Operation that was nil.")
}

switch op.(type) {
case *compute.Operation:
return computeOperationWaitTime(config, op.(*compute.Operation), project, activity, minutes)
case *computeBeta.Operation:
return computeBetaOperationWaitGlobalTime(config, op.(*computeBeta.Operation), project, activity, minutes)
default:
panic("Attempted to wait on an Operation of unknown type.")
}
}

func computeSharedOperationWaitZone(config *Config, op interface{}, project string, zone, activity string) error {
return computeSharedOperationWaitZoneTime(config, op, project, zone, 4, activity)
}
Expand Down
108 changes: 88 additions & 20 deletions google/resource_compute_global_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -16,16 +22,19 @@ func resourceComputeGlobalAddress() *schema.Resource {
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
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{
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -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
}
Expand All @@ -70,27 +109,48 @@ 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)
if err != nil {
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)
Expand All @@ -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
}
Expand Down
59 changes: 59 additions & 0 deletions google/resource_compute_global_address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -29,6 +31,29 @@ func TestAccComputeGlobalAddress_basic(t *testing.T) {
})
}

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(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider asserting on the format of the computed address to make sure an IPv6 is used.
Additionally, to prevent regression, make sure the ipv4 address follows the ipv4 pattern.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I agree that we need to validate that the API isn't lying to us when it says an IP address is at some version; especially when we would need to use a regex or vendor a new package to verify it.

Added a test for IPV4 on _basic, and moved checks to a TestCheckFunc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use https://golang.org/pkg/net/#ParseIP

ip := ParseIP(address)
ip.To16 != nil // means it is a IPv6 address.
ip.To4 != nil // means this is a IPv4 address.

Checking if the IpVersion match what we expect is probably fine for the IPv6 case. My main goal was not to test if the API "lies" to us but rather make sure we don't create an ipv6 address when we don't use the beta feature (and since we don't have the ip version field in that case, the only way to check is looking at address itself to validate it is ipv4).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok - we can actually just read the resource using a Beta API in this test and see the IpVersion; that's what the TestCheckFunc does.

"google_compute_global_address.foobar", &addr),
),
},
},
})

if addr.IpVersion != "IPV6" {
t.Errorf("Expected IP version to be IPV6, got %s", addr.IpVersion)
}
}

func testAccCheckComputeGlobalAddressDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

Expand Down Expand Up @@ -76,7 +101,41 @@ 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
}
}

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))
5 changes: 5 additions & 0 deletions website/docs/r/compute_global_address.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down