Supporting IP range reservation for global address (#2087)

<!-- This change is generated by MagicModules. -->
/cc @chrisst
This commit is contained in:
The Magician 2018-09-21 09:43:45 -07:00 committed by Chris Stephens
parent bfb1feb4cb
commit 14bac81a71
3 changed files with 168 additions and 0 deletions

View File

@ -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
}

View File

@ -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))
}

View File

@ -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.