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 subnetwork secondary ip ranges beta feature #310

Merged
merged 11 commits into from
Aug 9, 2017
11 changes: 11 additions & 0 deletions google/compute_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/hashicorp/terraform/helper/resource"

computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
)

Expand Down Expand Up @@ -91,3 +92,13 @@ func computeOperationWaitTime(config *Config, op *compute.Operation, project, ac

return nil
}

func computeBetaOperationWaitTime(config *Config, op *computeBeta.Operation, project, activity string, timeoutMin int) error {
opV1 := &compute.Operation{}
err := Convert(op, opV1)
if err != nil {
return err
}

return computeOperationWaitTime(config, opV1, project, activity, 4)
}
2 changes: 1 addition & 1 deletion google/compute_shared_operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func computeSharedOperationWaitTime(config *Config, op interface{}, project stri
case *compute.Operation:
return computeOperationWaitTime(config, op.(*compute.Operation), project, activity, minutes)
case *computeBeta.Operation:
return computeBetaOperationWaitGlobalTime(config, op.(*computeBeta.Operation), project, activity, minutes)
return computeBetaOperationWaitTime(config, op.(*computeBeta.Operation), project, activity, minutes)
default:
panic("Attempted to wait on an Operation of unknown type.")
}
Expand Down
5 changes: 5 additions & 0 deletions google/data_source_google_compute_subnetwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
)

Expand Down Expand Up @@ -90,3 +91,7 @@ func dataSourceGoogleComputeSubnetworkRead(d *schema.ResourceData, meta interfac
d.SetId(createSubnetID(subnetwork))
return nil
}

func createSubnetID(s *compute.Subnetwork) string {
return fmt.Sprintf("%s/%s", s.Region, s.Name)
}
172 changes: 143 additions & 29 deletions google/resource_compute_subnetwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ 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
var SubnetworkVersionedFeatures = []Feature{
{
Version: v0beta,
Item: "secondary_ip_range",
},
}

func resourceComputeSubnetwork() *schema.Resource {
return &schema.Resource{
Create: resourceComputeSubnetworkCreate,
Expand Down Expand Up @@ -37,7 +46,7 @@ func resourceComputeSubnetwork() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: linkDiffSuppress,
DiffSuppressFunc: compareSelfLinkResourceNames,
},

"description": &schema.Schema{
Expand Down Expand Up @@ -68,6 +77,26 @@ func resourceComputeSubnetwork() *schema.Resource {
Optional: true,
},

"secondary_ip_range": &schema.Schema{
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure if it will ever make a difference, but this should probably be marked ForceNew as well as it's children.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Type: schema.TypeList,
Optional: 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,
},
},
},
},

"self_link": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Expand All @@ -76,18 +105,8 @@ func resourceComputeSubnetwork() *schema.Resource {
}
}

func createSubnetID(s *compute.Subnetwork) string {
return fmt.Sprintf("%s/%s", s.Region, s.Name)
}

func splitSubnetID(id string) (region string, name string) {
parts := strings.Split(id, "/")
region = parts[0]
name = parts[1]
return
}

func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config)

region, err := getRegion(d, config)
Expand All @@ -106,17 +125,32 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
}

// Build the subnetwork parameters
subnetwork := &compute.Subnetwork{
subnetwork := &computeBeta.Subnetwork{
Name: d.Get("name").(string),
Description: d.Get("description").(string),
IpCidrRange: d.Get("ip_cidr_range").(string),
PrivateIpGoogleAccess: d.Get("private_ip_google_access").(bool),
SecondaryIpRanges: expandSecondaryRanges(d.Get("secondary_ip_range").([]interface{})),
Network: network,
}

log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
op, err := config.clientCompute.Subnetworks.Insert(
project, region, subnetwork).Do()

var op interface{}
switch computeApiVersion {
case v1:
subnetworkV1 := &compute.Subnetwork{}
err := Convert(subnetwork, subnetworkV1)
if err != nil {
return err
}

op, err = config.clientCompute.Subnetworks.Insert(
project, region, subnetworkV1).Do()
case v0beta:
op, err = config.clientComputeBeta.Subnetworks.Insert(
project, region, subnetwork).Do()
}

if err != nil {
return fmt.Errorf("Error creating subnetwork: %s", err)
Expand All @@ -128,9 +162,9 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
// The same name can appear twice in a project, as long as each one is in a different region."
// https://cloud.google.com/compute/docs/subnetworks
subnetwork.Region = region
d.SetId(createSubnetID(subnetwork))
d.SetId(createBetaSubnetID(subnetwork))

err = computeOperationWait(config, op, project, "Creating Subnetwork")
err = computeSharedOperationWait(config, op, project, "Creating Subnetwork")
if err != nil {
return err
}
Expand All @@ -139,6 +173,7 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e
}

func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config)

region, err := getRegion(d, config)
Expand All @@ -153,10 +188,25 @@ func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) err

name := d.Get("name").(string)

subnetwork, err := config.clientCompute.Subnetworks.Get(
project, region, name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Subnetwork %q", name))
subnetwork := &computeBeta.Subnetwork{}
switch computeApiVersion {
case v1:
subnetworkV1, err := config.clientCompute.Subnetworks.Get(
project, region, name).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Subnetwork %q", name))
}

err = Convert(subnetworkV1, subnetwork)
if err != nil {
return err
}
case v0beta:
var err error
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)
Expand All @@ -165,12 +215,14 @@ func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) err
d.Set("description", subnetwork.Description)
d.Set("private_ip_google_access", subnetwork.PrivateIpGoogleAccess)
d.Set("gateway_address", subnetwork.GatewayAddress)
d.Set("self_link", subnetwork.SelfLink)
d.Set("secondary_ip_range", flattenSecondaryRanges(subnetwork.SecondaryIpRanges))
d.Set("self_link", ConvertSelfLinkToV1(subnetwork.SelfLink))

return nil
}

func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersionUpdate(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures, []Feature{})
config := meta.(*Config)

region, err := getRegion(d, config)
Expand All @@ -186,18 +238,34 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e
d.Partial(true)

if d.HasChange("private_ip_google_access") {
subnetworksSetPrivateIpGoogleAccessRequest := &compute.SubnetworksSetPrivateIpGoogleAccessRequest{
subnetworksSetPrivateIpGoogleAccessRequest := &computeBeta.SubnetworksSetPrivateIpGoogleAccessRequest{
PrivateIpGoogleAccess: d.Get("private_ip_google_access").(bool),
}

log.Printf("[DEBUG] Updating Subnetwork PrivateIpGoogleAccess %q: %#v", d.Id(), subnetworksSetPrivateIpGoogleAccessRequest)
op, err := config.clientCompute.Subnetworks.SetPrivateIpGoogleAccess(
project, region, d.Get("name").(string), subnetworksSetPrivateIpGoogleAccessRequest).Do()

var op interface{}
switch computeApiVersion {
case v1:
subnetworksSetPrivateIpGoogleAccessRequestV1 := &compute.SubnetworksSetPrivateIpGoogleAccessRequest{}
err := Convert(subnetworksSetPrivateIpGoogleAccessRequest, subnetworksSetPrivateIpGoogleAccessRequestV1)
if err != nil {
return err
}

op, err = config.clientCompute.Subnetworks.SetPrivateIpGoogleAccess(
project, region, d.Get("name").(string), subnetworksSetPrivateIpGoogleAccessRequestV1).Do()
case v0beta:
op, err = config.clientComputeBeta.Subnetworks.SetPrivateIpGoogleAccess(
project, region, d.Get("name").(string), subnetworksSetPrivateIpGoogleAccessRequest).Do()

}

if err != nil {
return fmt.Errorf("Error updating subnetwork PrivateIpGoogleAccess: %s", err)
}

err = computeOperationWait(config, op, project, "Updating Subnetwork PrivateIpGoogleAccess")
err = computeSharedOperationWait(config, op, project, "Updating Subnetwork PrivateIpGoogleAccess")
if err != nil {
return err
}
Expand All @@ -211,6 +279,7 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e
}

func resourceComputeSubnetworkDelete(d *schema.ResourceData, meta interface{}) error {
computeApiVersion := getComputeApiVersion(d, SubnetworkBaseApiVersion, SubnetworkVersionedFeatures)
config := meta.(*Config)

region, err := getRegion(d, config)
Expand All @@ -224,13 +293,20 @@ func resourceComputeSubnetworkDelete(d *schema.ResourceData, meta interface{}) e
}

// Delete the subnetwork
op, err := config.clientCompute.Subnetworks.Delete(
project, region, d.Get("name").(string)).Do()
var op interface{}
switch computeApiVersion {
case v1:
op, err = config.clientCompute.Subnetworks.Delete(
project, region, d.Get("name").(string)).Do()
case v0beta:
op, err = config.clientComputeBeta.Subnetworks.Delete(
project, region, d.Get("name").(string)).Do()
}
if err != nil {
return fmt.Errorf("Error deleting subnetwork: %s", err)
}

err = computeOperationWait(config, op, project, "Deleting Subnetwork")
err = computeSharedOperationWait(config, op, project, "Deleting Subnetwork")
if err != nil {
return err
}
Expand All @@ -256,3 +332,41 @@ func resourceComputeSubnetworkImportState(d *schema.ResourceData, meta interface

return []*schema.ResourceData{d}, nil
}

func createBetaSubnetID(s *computeBeta.Subnetwork) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

This and createSubnetID should probably live in the same file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved createSubnetID to resource_compute_subnetwork.go

return fmt.Sprintf("%s/%s", s.Region, s.Name)
}

func splitSubnetID(id string) (region string, name string) {
parts := strings.Split(id, "/")
region = parts[0]
name = parts[1]
return
}

func expandSecondaryRanges(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 []*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
}
Loading