diff --git a/google/provider.go b/google/provider.go index 10de387a..cd3d3d4d 100644 --- a/google/provider.go +++ b/google/provider.go @@ -168,7 +168,6 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_compute_instance_group": resourceComputeInstanceGroup(), "google_compute_instance_group_manager": resourceComputeInstanceGroupManager(), "google_compute_instance_template": resourceComputeInstanceTemplate(), - "google_compute_network": resourceComputeNetwork(), "google_compute_network_peering": resourceComputeNetworkPeering(), "google_compute_project_metadata": resourceComputeProjectMetadata(), "google_compute_project_metadata_item": resourceComputeProjectMetadataItem(), diff --git a/google/provider_compute_gen.go b/google/provider_compute_gen.go index bc9d84de..1bc09241 100644 --- a/google/provider_compute_gen.go +++ b/google/provider_compute_gen.go @@ -29,6 +29,7 @@ var GeneratedComputeResourcesMap = map[string]*schema.Resource{ "google_compute_health_check": resourceComputeHealthCheck(), "google_compute_image": resourceComputeImage(), "google_compute_interconnect_attachment": resourceComputeInterconnectAttachment(), + "google_compute_network": resourceComputeNetwork(), "google_compute_region_autoscaler": resourceComputeRegionAutoscaler(), "google_compute_region_disk": resourceComputeRegionDisk(), "google_compute_route": resourceComputeRoute(), diff --git a/google/resource_compute_network.go b/google/resource_compute_network.go index 241bf7e5..69ba3e86 100644 --- a/google/resource_compute_network.go +++ b/google/resource_compute_network.go @@ -1,10 +1,27 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + package google import ( "fmt" "log" + "reflect" + "time" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" "google.golang.org/api/compute/v1" ) @@ -14,8 +31,15 @@ func resourceComputeNetwork() *schema.Resource { Read: resourceComputeNetworkRead, Update: resourceComputeNetworkUpdate, Delete: resourceComputeNetworkDelete, + Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceComputeNetworkImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(240 * time.Second), + Update: schema.DefaultTimeout(240 * time.Second), + Delete: schema.DefaultTimeout(240 * time.Second), }, Schema: map[string]*schema.Schema{ @@ -24,46 +48,40 @@ func resourceComputeNetwork() *schema.Resource { Required: true, ForceNew: true, }, - "auto_create_subnetworks": { Type: schema.TypeBool, Optional: true, ForceNew: true, Default: true, }, - "description": { Type: schema.TypeString, Optional: true, ForceNew: true, }, - + "ipv4_range": { + Type: schema.TypeString, + Optional: true, + Deprecated: "Legacy Networks are deprecated and you will no longer be able to create them using this field from Feb 1, 2020 onwards.", + ForceNew: true, + }, "routing_mode": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"REGIONAL", "GLOBAL", ""}, false), }, "gateway_ipv4": { Type: schema.TypeString, Computed: true, }, - - "ipv4_range": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - // This needs to remain deprecated until the API is retired - Deprecated: "Please use google_compute_subnetwork resources instead.", - }, - "project": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, - "self_link": { Type: schema.TypeString, Computed: true, @@ -75,88 +93,132 @@ func resourceComputeNetwork() *schema.Resource { func resourceComputeNetworkCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) + obj := make(map[string]interface{}) + descriptionProp, err := expandComputeNetworkDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + IPv4RangeProp, err := expandComputeNetworkIpv4_range(d.Get("ipv4_range"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ipv4_range"); !isEmptyValue(reflect.ValueOf(IPv4RangeProp)) && (ok || !reflect.DeepEqual(v, IPv4RangeProp)) { + obj["IPv4Range"] = IPv4RangeProp + } + nameProp, err := expandComputeNetworkName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + autoCreateSubnetworksProp, err := expandComputeNetworkAutoCreateSubnetworks(d.Get("auto_create_subnetworks"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("auto_create_subnetworks"); !isEmptyValue(reflect.ValueOf(autoCreateSubnetworksProp)) && (ok || !reflect.DeepEqual(v, autoCreateSubnetworksProp)) { + obj["autoCreateSubnetworks"] = autoCreateSubnetworksProp + } + routingConfigProp, err := expandComputeNetworkRoutingConfig(d, config) + if err != nil { + return err + } else if !isEmptyValue(reflect.ValueOf(routingConfigProp)) { + obj["routingConfig"] = routingConfigProp + } + + obj, err = resourceComputeNetworkEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/networks") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new Network: %#v", obj) + res, err := sendRequestWithTimeout(config, "POST", url, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating Network: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + project, err := getProject(d, config) if err != nil { return err } - - // - // Possible modes: - // - 1 Legacy mode - Create a network in the legacy mode. ipv4_range is set. auto_create_subnetworks must not be - // set (enforced by ConflictsWith schema attribute) - // - 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, - // - autoCreateSubnetworks := d.Get("auto_create_subnetworks").(bool) - if autoCreateSubnetworks && d.Get("ipv4_range").(string) != "" { - return fmt.Errorf("ipv4_range can't be set if auto_create_subnetworks is true.") - } - - // Build the network parameter - network := &compute.Network{ - Name: d.Get("name").(string), - AutoCreateSubnetworks: autoCreateSubnetworks, - Description: d.Get("description").(string), - } - - if v, ok := d.GetOk("routing_mode"); ok { - routingConfig := &compute.NetworkRoutingConfig{ - RoutingMode: v.(string), - } - network.RoutingConfig = routingConfig - } - - 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 otherwise - // google will create a network in legacy mode. - network.ForceSendFields = []string{"AutoCreateSubnetworks"} - } - log.Printf("[DEBUG] Network insert request: %#v", network) - op, err := config.clientCompute.Networks.Insert( - project, network).Do() - if err != nil { - return fmt.Errorf("Error creating network: %s", err) - } - - // It probably maybe worked, so store the ID now - d.SetId(network.Name) - - err = computeOperationWait(config.clientCompute, op, project, "Creating Network") + op := &compute.Operation{} + err = Convert(res, op) if err != nil { return err } + waitErr := computeOperationWaitTime( + config.clientCompute, op, project, "Creating Network", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create Network: %s", waitErr) + } + + log.Printf("[DEBUG] Finished creating Network %q: %#v", d.Id(), res) + return resourceComputeNetworkRead(d, meta) } func resourceComputeNetworkRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - project, err := getProject(d, config) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/networks/{{name}}") if err != nil { return err } - network, err := config.clientCompute.Networks.Get( - project, d.Id()).Do() + res, err := sendRequest(config, "GET", url, nil) if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("Network %q", d.Get("name").(string))) + return handleNotFoundError(err, d, fmt.Sprintf("ComputeNetwork %q", d.Id())) } - routingConfig := network.RoutingConfig + project, err := getProject(d, config) + if err != nil { + return err + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } - d.Set("routing_mode", routingConfig.RoutingMode) - d.Set("gateway_ipv4", network.GatewayIPv4) - d.Set("ipv4_range", network.IPv4Range) - d.Set("self_link", network.SelfLink) - d.Set("name", network.Name) - d.Set("description", network.Description) - d.Set("auto_create_subnetworks", network.AutoCreateSubnetworks) - d.Set("project", project) + if err := d.Set("description", flattenComputeNetworkDescription(res["description"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + if err := d.Set("gateway_ipv4", flattenComputeNetworkGateway_ipv4(res["gatewayIPv4"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + if err := d.Set("ipv4_range", flattenComputeNetworkIpv4_range(res["IPv4Range"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + if err := d.Set("name", flattenComputeNetworkName(res["name"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + if err := d.Set("auto_create_subnetworks", flattenComputeNetworkAutoCreateSubnetworks(res["autoCreateSubnetworks"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + if v, ok := res["routingConfig"].(map[string]interface{}); res["routingConfig"] != nil && ok { + if err := d.Set("routing_mode", flattenComputeNetworkRoutingConfigRoutingMode(v["routingMode"], d)); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } + } else { + d.Set("routing_mode", nil) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading Network: %s", err) + } return nil } @@ -164,25 +226,48 @@ func resourceComputeNetworkRead(d *schema.ResourceData, meta interface{}) error func resourceComputeNetworkUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - project, err := getProject(d, config) - if err != nil { - return err + d.Partial(true) + + if d.HasChange("routing_mode") { + obj := make(map[string]interface{}) + routingConfigProp, err := expandComputeNetworkRoutingConfig(d, config) + if err != nil { + return err + } else if !isEmptyValue(reflect.ValueOf(routingConfigProp)) { + obj["routingConfig"] = routingConfigProp + } + + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/networks/{{name}}") + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "PATCH", url, obj, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error updating Network %q: %s", d.Id(), err) + } + + project, err := getProject(d, config) + if err != nil { + return err + } + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Updating Network", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) + + if err != nil { + return err + } + + d.SetPartial("routing_config") } - op, err := config.clientCompute.Networks.Patch(project, d.Id(), &compute.Network{ - RoutingConfig: &compute.NetworkRoutingConfig{ - RoutingMode: d.Get("routing_mode").(string), - }, - }).Do() - - if err != nil { - return fmt.Errorf("Error updating network: %s", err) - } - - err = computeSharedOperationWait(config.clientCompute, op, project, "UpdateNetwork") - if err != nil { - return err - } + d.Partial(false) return resourceComputeNetworkRead(d, meta) } @@ -190,24 +275,117 @@ func resourceComputeNetworkUpdate(d *schema.ResourceData, meta interface{}) erro func resourceComputeNetworkDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/networks/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting Network %q", d.Id()) + res, err := sendRequestWithTimeout(config, "DELETE", url, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "Network") + } + project, err := getProject(d, config) if err != nil { return err } - - return deleteComputeNetwork(project, d.Id(), config) -} - -func deleteComputeNetwork(project, network string, config *Config) error { - op, err := config.clientCompute.Networks.Delete( - project, network).Do() - if err != nil { - return fmt.Errorf("Error deleting network: %s", err) - } - - err = computeOperationWaitTime(config.clientCompute, op, project, "Deleting Network", 10) + op := &compute.Operation{} + err = Convert(res, op) if err != nil { return err } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Deleting Network", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting Network %q: %#v", d.Id(), res) return nil } + +func resourceComputeNetworkImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{"projects/(?P[^/]+)/global/networks/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeNetworkDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeNetworkGateway_ipv4(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeNetworkIpv4_range(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeNetworkName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeNetworkAutoCreateSubnetworks(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeNetworkRoutingConfigRoutingMode(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func expandComputeNetworkDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkIpv4_range(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkAutoCreateSubnetworks(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkRoutingConfig(d TerraformResourceData, config *Config) (interface{}, error) { + transformed := make(map[string]interface{}) + // Note that nesting flattened objects won't work because we don't handle them properly here. + transformedRoutingMode, err := expandComputeNetworkRoutingConfigRoutingMode(d.Get("routing_mode"), d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRoutingMode); val.IsValid() && !isEmptyValue(val) { + transformed["routingMode"] = transformedRoutingMode + } + + return transformed, nil +} + +func expandComputeNetworkRoutingConfigRoutingMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func resourceComputeNetworkEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + if _, ok := d.GetOk("ipv4_range"); !ok { + obj["autoCreateSubnetworks"] = d.Get("auto_create_subnetworks") + } + + return obj, nil +} diff --git a/google/resource_compute_network_generated_test.go b/google/resource_compute_network_generated_test.go new file mode 100644 index 00000000..72cb9874 --- /dev/null +++ b/google/resource_compute_network_generated_test.go @@ -0,0 +1,82 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccComputeNetwork_networkBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeNetworkDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeNetwork_networkBasicExample(context), + }, + { + ResourceName: "google_compute_network.vpc_network", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeNetwork_networkBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_network" "vpc_network" { + name = "vpc-network-%{random_suffix}" +} +`, context) +} + +func testAccCheckComputeNetworkDestroy(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_network" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := testAccProvider.Meta().(*Config) + + url, err := replaceVarsForTest(rs, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/networks/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", url, nil) + if err == nil { + return fmt.Errorf("ComputeNetwork still exists at %s", url) + } + } + + return nil +} diff --git a/google/resource_compute_network_test.go b/google/resource_compute_network_test.go index 830e9ad9..2b2e96d3 100644 --- a/google/resource_compute_network_test.go +++ b/google/resource_compute_network_test.go @@ -10,7 +10,7 @@ import ( "google.golang.org/api/compute/v1" ) -func TestAccComputeNetwork_basic(t *testing.T) { +func TestAccComputeNetwork_explicitAutoSubnet(t *testing.T) { t.Parallel() var network compute.Network @@ -22,32 +22,6 @@ func TestAccComputeNetwork_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccComputeNetwork_basic(), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeNetworkExists( - "google_compute_network.foobar", &network), - ), - }, - { - ResourceName: "google_compute_network.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccComputeNetwork_auto_subnet(t *testing.T) { - t.Parallel() - - var network compute.Network - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeNetworkDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeNetwork_auto_subnet(), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNetworkExists( "google_compute_network.bar", &network), @@ -64,7 +38,7 @@ func TestAccComputeNetwork_auto_subnet(t *testing.T) { }) } -func TestAccComputeNetwork_custom_subnet(t *testing.T) { +func TestAccComputeNetwork_customSubnet(t *testing.T) { t.Parallel() var network compute.Network @@ -92,10 +66,36 @@ func TestAccComputeNetwork_custom_subnet(t *testing.T) { }) } -func TestAccComputeNetwork_routing_mode(t *testing.T) { +func TestAccComputeNetwork_legacyNetwork(t *testing.T) { t.Parallel() var network compute.Network + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeNetworkDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeNetwork_legacyNetwork(), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeNetworkExists("google_compute_network.default", &network), + resource.TestCheckResourceAttrSet("google_compute_network.default", "ipv4_range"), + ), + }, + { + ResourceName: "google_compute_network.default", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeNetwork_routingModeAndUpdate(t *testing.T) { + t.Parallel() + + var network compute.Network + networkName := acctest.RandString(10) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -103,7 +103,7 @@ func TestAccComputeNetwork_routing_mode(t *testing.T) { CheckDestroy: testAccCheckComputeNetworkDestroy, Steps: []resource.TestStep{ { - Config: testAccComputeNetwork_routing_mode("GLOBAL"), + Config: testAccComputeNetwork_routing_mode(networkName, "GLOBAL"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNetworkExists( "google_compute_network.acc_network_routing_mode", &network), @@ -113,7 +113,7 @@ func TestAccComputeNetwork_routing_mode(t *testing.T) { }, // Test updating the routing field (only updateable field). { - Config: testAccComputeNetwork_routing_mode("REGIONAL"), + Config: testAccComputeNetwork_routing_mode(networkName, "REGIONAL"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNetworkExists( "google_compute_network.acc_network_routing_mode", &network), @@ -141,33 +141,15 @@ func TestAccComputeNetwork_default_routing_mode(t *testing.T) { Config: testAccComputeNetwork_basic(), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNetworkExists( - "google_compute_network.foobar", &network), + "google_compute_network.bar", &network), testAccCheckComputeNetworkHasRoutingMode( - "google_compute_network.foobar", &network, expectedRoutingMode), + "google_compute_network.bar", &network, expectedRoutingMode), ), }, }, }) } -func testAccCheckComputeNetworkDestroy(s *terraform.State) error { - config := testAccProvider.Meta().(*Config) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "google_compute_network" { - continue - } - - _, err := config.clientCompute.Networks.Get( - config.Project, rs.Primary.ID).Do() - if err == nil { - return fmt.Errorf("Network still exists") - } - } - - return nil -} - func testAccCheckComputeNetworkExists(n string, network *compute.Network) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -272,19 +254,21 @@ func testAccCheckComputeNetworkHasRoutingMode(n string, network *compute.Network func testAccComputeNetwork_basic() string { return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "network-test-%s" -}`, acctest.RandString(10)) -} - -func testAccComputeNetwork_auto_subnet() string { - return fmt.Sprintf(` resource "google_compute_network" "bar" { name = "network-test-%s" auto_create_subnetworks = true }`, acctest.RandString(10)) } +func testAccComputeNetwork_legacyNetwork() string { + return fmt.Sprintf(` +resource "google_compute_network" "default" { + name = "network-test-%s" + auto_create_subnetworks = false + ipv4_range = "10.0.0.0/16" +}`, acctest.RandString(10)) +} + func testAccComputeNetwork_custom_subnet() string { return fmt.Sprintf(` resource "google_compute_network" "baz" { @@ -293,10 +277,10 @@ resource "google_compute_network" "baz" { }`, acctest.RandString(10)) } -func testAccComputeNetwork_routing_mode(routingMode string) string { +func testAccComputeNetwork_routing_mode(network, routingMode string) string { return fmt.Sprintf(` resource "google_compute_network" "acc_network_routing_mode" { name = "network-test-%s" routing_mode = "%s" -}`, acctest.RandString(10), routingMode) +}`, network, routingMode) } diff --git a/google/resource_google_project.go b/google/resource_google_project.go index faae6326..f64ceaf3 100644 --- a/google/resource_google_project.go +++ b/google/resource_google_project.go @@ -512,3 +512,17 @@ func updateProjectBillingAccount(d *schema.ResourceData, config *Config) error { return fmt.Errorf("Timed out waiting for billing account to return correct value. Waiting for %s, got %s.", name, strings.TrimPrefix(ba.BillingAccountName, "billingAccounts/")) } + +func deleteComputeNetwork(project, network string, config *Config) error { + op, err := config.clientCompute.Networks.Delete( + project, network).Do() + if err != nil { + return fmt.Errorf("Error deleting network: %s", err) + } + + err = computeOperationWaitTime(config.clientCompute, op, project, "Deleting Network", 10) + if err != nil { + return err + } + return nil +} diff --git a/website/docs/r/compute_network.html.markdown b/website/docs/r/compute_network.html.markdown index a77769c8..9c139d85 100644 --- a/website/docs/r/compute_network.html.markdown +++ b/website/docs/r/compute_network.html.markdown @@ -1,24 +1,46 @@ --- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- layout: "google" page_title: "Google: google_compute_network" -sidebar_current: "docs-google-compute-network-x" +sidebar_current: "docs-google-compute-network" description: |- - Manages a network within GCE. + Manages a VPC network or legacy network resource on GCP. --- # google\_compute\_network -Manages a network within GCE. For more information see -[the official documentation](https://cloud.google.com/compute/docs/vpc) -and -[API](https://cloud.google.com/compute/docs/reference/latest/networks). +Manages a VPC network or legacy network resource on GCP. + + +To get more information about Network, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/networks) +* How-to Guides + * [Official Documentation](https://cloud.google.com/vpc/docs/vpc) + + +## Example Usage - Network Basic -## Example Usage ```hcl -resource "google_compute_network" "default" { - name = "foobar" - auto_create_subnetworks = "true" +resource "google_compute_network" "vpc_network" { + name = "vpc-network" } ``` @@ -26,46 +48,84 @@ resource "google_compute_network" "default" { The following arguments are supported: -* `name` - (Required) A unique name for the resource, required by GCE. - Changing this forces a new resource to be created. + +* `name` - + (Required) + Name of the resource. Provided by the client when the resource is + created. The name must be 1-63 characters long, and comply with + RFC1035. Specifically, the name must be 1-63 characters long and match + the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the + first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the last + character, which cannot be a dash. + - - - -* `auto_create_subnetworks` - (Optional) If set to true, this network will be - created in auto subnet mode, and Google will create a subnet for each region - automatically. If set to false, a custom subnetted network will be created that - can support `google_compute_subnetwork` resources. Defaults to true. -* `ipv4_range` - (Optional) If set to a CIDR block, uses the legacy VPC API with the - specified range. This API is deprecated. If set, `auto_create_subnetworks` must be - explicitly set to false. +* `description` - + (Optional) + An optional description of this resource. The resource must be + recreated to modify this field. -* `routing_mode` - (Optional) Sets the network-wide routing mode for Cloud Routers - to use. Accepted values are `"GLOBAL"` or `"REGIONAL"`. Defaults to `"REGIONAL"`. - Refer to the [Cloud Router documentation](https://cloud.google.com/router/docs/concepts/overview#dynamic-routing-mode) +* `ipv4_range` - + (Optional, Deprecated) + If this field is specified, a deprecated legacy network is created. + You will no longer be able to create a legacy network on Feb 1, 2020. + See the [legacy network docs](https://cloud.google.com/vpc/docs/legacy) for more details. + The range of internal addresses that are legal on this legacy network. + This range is a CIDR specification, for example: `192.168.0.0/16`. + The resource must be recreated to modify this field. -* `description` - (Optional) A brief description of this resource. +* `auto_create_subnetworks` - + (Optional) + When set to `true`, the network is created in "auto subnet mode" and + it will create a subnet for each region automatically across the + `10.128.0.0/9` address range. + When set to `false`, the network is created in "custom subnet mode" so + the user can explicitly connect subnetwork resources. + +* `routing_mode` - + (Optional) + The network-wide routing mode to use. If set to `REGIONAL`, this + network's cloud routers will only advertise routes with subnetworks + of this network in the same region as the router. If set to `GLOBAL`, + this network's cloud routers will advertise routes with all + subnetworks of this network, across regions. +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. -* `project` - (Optional) The ID of the project in which the resource belongs. If it - is not provided, the provider project is used. ## Attributes Reference -In addition to the arguments listed above, the following computed attributes are -exported: +In addition to the arguments listed above, the following computed attributes are exported: -* `gateway_ipv4` - The IPv4 address of the gateway. - -* `name` - The unique name of the network. +* `gateway_ipv4` - + The gateway address for default routing out of the network. This value + is selected by GCP. * `self_link` - The URI of the created resource. +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + ## Import -Networks can be imported using the `name`, e.g. +Network can be imported using any of these accepted formats: ``` -$ terraform import google_compute_network.default foobar +$ terraform import google_compute_network.default projects/{{project}}/global/networks/{{name}} +$ terraform import google_compute_network.default {{project}}/{{name}} +$ terraform import google_compute_network.default {{name}} ``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource.