diff --git a/google/resource_compute_global_address.go b/google/resource_compute_global_address.go index 2e6899e5..19153bf1 100644 --- a/google/resource_compute_global_address.go +++ b/google/resource_compute_global_address.go @@ -18,6 +18,7 @@ import ( "fmt" "log" "reflect" + "strconv" "time" "github.com/hashicorp/terraform/helper/schema" @@ -48,6 +49,14 @@ func resourceComputeGlobalAddress() *schema.Resource { Required: true, ForceNew: true, }, + "address_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"EXTERNAL", "INTERNAL", ""}, false), + DiffSuppressFunc: emptyOrDefaultStringSuppress("EXTERNAL"), + Default: "EXTERNAL", + }, "description": { Type: schema.TypeString, Optional: true, @@ -65,6 +74,23 @@ func resourceComputeGlobalAddress() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "network": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "prefix_length": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "purpose": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"VPC_PEERING", ""}, false), + }, "address": { Type: schema.TypeString, Computed: true, @@ -119,6 +145,30 @@ func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{} } else if v, ok := d.GetOkExists("ip_version"); !isEmptyValue(reflect.ValueOf(ipVersionProp)) && (ok || !reflect.DeepEqual(v, ipVersionProp)) { obj["ipVersion"] = ipVersionProp } + prefixLengthProp, err := expandComputeGlobalAddressPrefixLength(d.Get("prefix_length"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("prefix_length"); !isEmptyValue(reflect.ValueOf(prefixLengthProp)) && (ok || !reflect.DeepEqual(v, prefixLengthProp)) { + obj["prefixLength"] = prefixLengthProp + } + addressTypeProp, err := expandComputeGlobalAddressAddressType(d.Get("address_type"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("address_type"); !isEmptyValue(reflect.ValueOf(addressTypeProp)) && (ok || !reflect.DeepEqual(v, addressTypeProp)) { + obj["addressType"] = addressTypeProp + } + purposeProp, err := expandComputeGlobalAddressPurpose(d.Get("purpose"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("purpose"); !isEmptyValue(reflect.ValueOf(purposeProp)) && (ok || !reflect.DeepEqual(v, purposeProp)) { + obj["purpose"] = purposeProp + } + networkProp, err := expandComputeGlobalAddressNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } url, err := replaceVars(d, config, "https://www.googleapis.com/compute/beta/projects/{{project}}/global/addresses") if err != nil { @@ -235,6 +285,18 @@ func resourceComputeGlobalAddressRead(d *schema.ResourceData, meta interface{}) if err := d.Set("ip_version", flattenComputeGlobalAddressIpVersion(res["ipVersion"])); err != nil { return fmt.Errorf("Error reading GlobalAddress: %s", err) } + if err := d.Set("prefix_length", flattenComputeGlobalAddressPrefixLength(res["prefixLength"])); err != nil { + return fmt.Errorf("Error reading GlobalAddress: %s", err) + } + if err := d.Set("address_type", flattenComputeGlobalAddressAddressType(res["addressType"])); err != nil { + return fmt.Errorf("Error reading GlobalAddress: %s", err) + } + if err := d.Set("purpose", flattenComputeGlobalAddressPurpose(res["purpose"])); err != nil { + return fmt.Errorf("Error reading GlobalAddress: %s", err) + } + if err := d.Set("network", flattenComputeGlobalAddressNetwork(res["network"])); err != nil { + return fmt.Errorf("Error reading GlobalAddress: %s", err) + } if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { return fmt.Errorf("Error reading GlobalAddress: %s", err) } @@ -380,6 +442,31 @@ func flattenComputeGlobalAddressIpVersion(v interface{}) interface{} { return v } +func flattenComputeGlobalAddressPrefixLength(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeGlobalAddressAddressType(v interface{}) interface{} { + return v +} + +func flattenComputeGlobalAddressPurpose(v interface{}) interface{} { + return v +} + +func flattenComputeGlobalAddressNetwork(v interface{}) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + func expandComputeGlobalAddressDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } @@ -402,3 +489,23 @@ func expandComputeGlobalAddressLabels(v interface{}, d *schema.ResourceData, con func expandComputeGlobalAddressIpVersion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } + +func expandComputeGlobalAddressPrefixLength(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeGlobalAddressAddressType(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeGlobalAddressPurpose(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeGlobalAddressNetwork(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("networks", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for network: %s", err) + } + return f.RelativeLink(), nil +} diff --git a/google/resource_compute_global_address_test.go b/google/resource_compute_global_address_test.go index c93d724c..7d78c2ce 100644 --- a/google/resource_compute_global_address_test.go +++ b/google/resource_compute_global_address_test.go @@ -67,6 +67,26 @@ func TestAccComputeGlobalAddress_ipv6(t *testing.T) { }) } +func TestAccComputeGlobalAddress_internal(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeGlobalAddressDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeGlobalAddress_internal(), + }, + resource.TestStep{ + ResourceName: "google_compute_global_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckComputeGlobalAddressDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) @@ -156,3 +176,19 @@ resource "google_compute_global_address" "foobar" { ip_version = "IPV6" }`, acctest.RandString(10)) } + +func testAccComputeGlobalAddress_internal() string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + name = "address-test-%s" +} + + +resource "google_compute_global_address" "foobar" { + name = "address-test-%s" + address_type = "INTERNAL" + purpose = "VPC_PEERING" + prefix_length = 24 + network = "${google_compute_network.foobar.self_link}" +}`, acctest.RandString(10), acctest.RandString(10)) +} diff --git a/website/docs/r/compute_global_address.html.markdown b/website/docs/r/compute_global_address.html.markdown index b64b6191..23c42e99 100644 --- a/website/docs/r/compute_global_address.html.markdown +++ b/website/docs/r/compute_global_address.html.markdown @@ -70,6 +70,31 @@ The following arguments are supported: (Optional) The IP Version that will be used by this address. Valid options are IPV4 or IPV6. The default value is IPV4. + +* `prefix_length` - + (Optional) + The prefix length of the IP range. If not present, it means the + address field is a single IP address. + This field is not applicable to addresses with addressType=EXTERNAL. + +* `address_type` - + (Optional) + The type of the address to reserve, default is EXTERNAL. + * EXTERNAL indicates public/external single IP address. + * INTERNAL indicates internal IP ranges belonging to some network. + +* `purpose` - + (Optional) + The purpose of the resource. For global internal addresses it can be + * VPC_PEERING - for peer networks + This should only be set when using an Internal address. + +* `network` - + (Optional) + The URL of the network in which to reserve the IP range. The IP range + must be in RFC1918 space. The network cannot be deleted if there are + any reserved IP ranges referring to it. + This should only be set when using an Internal address. * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used.