mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-04 17:51:11 +00:00
[WIP] support for creating distributed networks, and subnetwork resources
This commit is contained in:
parent
34833ac922
commit
7d97c69498
@ -59,6 +59,7 @@ func Provider() terraform.ResourceProvider {
|
|||||||
"google_compute_project_metadata": resourceComputeProjectMetadata(),
|
"google_compute_project_metadata": resourceComputeProjectMetadata(),
|
||||||
"google_compute_route": resourceComputeRoute(),
|
"google_compute_route": resourceComputeRoute(),
|
||||||
"google_compute_ssl_certificate": resourceComputeSslCertificate(),
|
"google_compute_ssl_certificate": resourceComputeSslCertificate(),
|
||||||
|
"google_compute_subnetwork": resourceComputeSubnetwork(),
|
||||||
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(),
|
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(),
|
||||||
"google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(),
|
"google_compute_target_https_proxy": resourceComputeTargetHttpsProxy(),
|
||||||
"google_compute_target_pool": resourceComputeTargetPool(),
|
"google_compute_target_pool": resourceComputeTargetPool(),
|
||||||
|
@ -14,6 +14,7 @@ func resourceComputeNetwork() *schema.Resource {
|
|||||||
Create: resourceComputeNetworkCreate,
|
Create: resourceComputeNetworkCreate,
|
||||||
Read: resourceComputeNetworkRead,
|
Read: resourceComputeNetworkRead,
|
||||||
Delete: resourceComputeNetworkDelete,
|
Delete: resourceComputeNetworkDelete,
|
||||||
|
Update: resourceComputeNetworkUpdate,
|
||||||
|
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"name": &schema.Schema{
|
"name": &schema.Schema{
|
||||||
@ -24,7 +25,7 @@ func resourceComputeNetwork() *schema.Resource {
|
|||||||
|
|
||||||
"ipv4_range": &schema.Schema{
|
"ipv4_range": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -33,6 +34,17 @@ func resourceComputeNetwork() *schema.Resource {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"auto_create_subnetworks": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false, // copy behaviour of Google Cloud GUI and gcloud tool
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
"self_link": &schema.Schema{
|
"self_link": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
@ -44,11 +56,36 @@ func resourceComputeNetwork() *schema.Resource {
|
|||||||
func resourceComputeNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceComputeNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
config := meta.(*Config)
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Possible modes:
|
||||||
|
// -1- Legacy mode - Create a network in the legacy mode. ipv4_range is set. auto_create_subnetworks must be false
|
||||||
|
// and not sent in reqest, and subnetworks empty
|
||||||
|
// -2- Distributed Mode - Create a new generation network that supports subnetworks:
|
||||||
|
// 2.a - Auto subnet mode - auto_create_subnetworks = true, Google will generate 1 subnetwork per region
|
||||||
|
// 2.b - Custom subnet mode - auto_create_subnetworks = false & ipv4_range not set,
|
||||||
|
//
|
||||||
|
ipv4range := d.Get("ipv4_range").(string)
|
||||||
|
autoCreateSubnetworks := d.Get("auto_create_subnetworks").(bool)
|
||||||
|
|
||||||
|
if ipv4range != "" && autoCreateSubnetworks {
|
||||||
|
return fmt.Errorf("Error: cannot define ipv4_range with auto_create_subnetworks = true.")
|
||||||
|
}
|
||||||
|
|
||||||
// Build the network parameter
|
// Build the network parameter
|
||||||
network := &compute.Network{
|
network := &compute.Network{
|
||||||
Name: d.Get("name").(string),
|
Name: d.Get("name").(string),
|
||||||
IPv4Range: d.Get("ipv4_range").(string),
|
AutoCreateSubnetworks: autoCreateSubnetworks,
|
||||||
|
Description: d.Get("description").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("ipv4_range"); ok {
|
||||||
|
log.Printf("[DEBUG] Setting IPv4Range (%#V) for legacy network mode", v.(string))
|
||||||
|
network.IPv4Range = v.(string)
|
||||||
|
} else {
|
||||||
|
// custom subnet mode, so make sure AutoCreateSubnetworks field is included in request
|
||||||
|
network.ForceSendFields = []string{"AutoCreateSubnetworks"}
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Network insert request: %#v", network)
|
log.Printf("[DEBUG] Network insert request: %#v", network)
|
||||||
op, err := config.clientCompute.Networks.Insert(
|
op, err := config.clientCompute.Networks.Insert(
|
||||||
config.Project, network).Do()
|
config.Project, network).Do()
|
||||||
@ -64,7 +101,7 @@ func resourceComputeNetworkCreate(d *schema.ResourceData, meta interface{}) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceComputeNetworkRead(d, meta)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceComputeNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
func resourceComputeNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
@ -86,6 +123,10 @@ func resourceComputeNetworkRead(d *schema.ResourceData, meta interface{}) error
|
|||||||
|
|
||||||
d.Set("gateway_ipv4", network.GatewayIPv4)
|
d.Set("gateway_ipv4", network.GatewayIPv4)
|
||||||
d.Set("self_link", network.SelfLink)
|
d.Set("self_link", network.SelfLink)
|
||||||
|
for i, v := range network.Subnetworks {
|
||||||
|
prefix := fmt.Sprintf("subnetwork_links.%d", i)
|
||||||
|
d.Set(prefix, v)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -108,3 +149,8 @@ func resourceComputeNetworkDelete(d *schema.ResourceData, meta interface{}) erro
|
|||||||
d.SetId("")
|
d.SetId("")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resourceComputeNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//config := meta.(*Config)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -29,6 +29,46 @@ func TestAccComputeNetwork_basic(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccComputeNetwork_auto_subnet(t *testing.T) {
|
||||||
|
var network compute.Network
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeNetworkDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeNetwork_auto_subnet,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeNetworkExists(
|
||||||
|
"google_compute_network.bar", &network),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccComputeNetwork_custom_subnet(t *testing.T) {
|
||||||
|
var network compute.Network
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeNetworkDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeNetwork_custom_subnet,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeNetworkExists(
|
||||||
|
"google_compute_network.baz", &network),
|
||||||
|
testAccCheckComputeNetworkIsCustomSubnet(
|
||||||
|
"google_compute_network.baz", &network),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckComputeNetworkDestroy(s *terraform.State) error {
|
func testAccCheckComputeNetworkDestroy(s *terraform.State) error {
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
@ -76,8 +116,42 @@ func testAccCheckComputeNetworkExists(n string, network *compute.Network) resour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeNetworkIsCustomSubnet(n string, network *compute.Network) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
found, err := config.clientCompute.Networks.Get(
|
||||||
|
config.Project, network.Name).Do()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if found.AutoCreateSubnetworks {
|
||||||
|
return fmt.Errorf("should have AutoCreateSubnetworks = false")
|
||||||
|
}
|
||||||
|
|
||||||
|
if found.IPv4Range != "" {
|
||||||
|
return fmt.Errorf("should not have IPv4Range")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var testAccComputeNetwork_basic = fmt.Sprintf(`
|
var testAccComputeNetwork_basic = fmt.Sprintf(`
|
||||||
resource "google_compute_network" "foobar" {
|
resource "google_compute_network" "foobar" {
|
||||||
name = "network-test-%s"
|
name = "network-test-%s"
|
||||||
ipv4_range = "10.0.0.0/16"
|
ipv4_range = "10.0.0.0/16"
|
||||||
}`, acctest.RandString(10))
|
}`, acctest.RandString(10))
|
||||||
|
|
||||||
|
var testAccComputeNetwork_auto_subnet = fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "bar" {
|
||||||
|
name = "network-test-%s"
|
||||||
|
auto_create_subnetworks = true
|
||||||
|
}`, acctest.RandString(10))
|
||||||
|
|
||||||
|
var testAccComputeNetwork_custom_subnet = fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "baz" {
|
||||||
|
name = "network-test-%s"
|
||||||
|
auto_create_subnetworks = false
|
||||||
|
}`, acctest.RandString(10))
|
||||||
|
142
resource_compute_subnetwork.go
Normal file
142
resource_compute_subnetwork.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"google.golang.org/api/compute/v1"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceComputeSubnetwork() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceComputeSubnetworkCreate,
|
||||||
|
Read: resourceComputeSubnetworkRead,
|
||||||
|
Delete: resourceComputeSubnetworkDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"region": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"network": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ipCidrRange": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"gateway_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"self_link": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSubnetID(s *compute.Subnetwork) string {
|
||||||
|
return fmt.Sprintf("%s/%s", s.Region, s.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
// Build the subnetwork parameters
|
||||||
|
subnetwork := &compute.Subnetwork{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Description: d.Get("description").(string),
|
||||||
|
IpCidrRange: d.Get("ipCidrRange").(string),
|
||||||
|
Network: d.Get("network").(string),
|
||||||
|
}
|
||||||
|
region := d.Get("region").(string)
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Subnetwork insert request: %#v", subnetwork)
|
||||||
|
op, err := config.clientCompute.Subnetworks.Insert(
|
||||||
|
config.Project, region, subnetwork).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating subnetwork: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It probably maybe worked, so store the ID now
|
||||||
|
// Subnetwork name is not guaranteed to be unique in a project, but must be unique within a region
|
||||||
|
subnetwork.Region = region
|
||||||
|
d.SetId(createSubnetID(subnetwork))
|
||||||
|
|
||||||
|
err = computeOperationWaitRegion(config, op, region, "Creating Subnetwork")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceComputeSubnetworkRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeSubnetworkRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
region := d.Get("region").(string)
|
||||||
|
|
||||||
|
subnetwork, err := config.clientCompute.Subnetworks.Get(
|
||||||
|
config.Project, region, name).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing Subnetwork %q because it's gone", name)
|
||||||
|
// The resource doesn't exist anymore
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error reading subnetwork: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("gateway_address", subnetwork.GatewayAddress)
|
||||||
|
d.Set("self_link", subnetwork.SelfLink)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeSubnetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
region := d.Get("region").(string)
|
||||||
|
|
||||||
|
// Delete the network
|
||||||
|
op, err := config.clientCompute.Subnetworks.Delete(
|
||||||
|
config.Project, region, d.Get("name").(string)).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting network: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = computeOperationWaitRegion(config, op, region, "Deleting Network")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user