From 56fe45ade97ee36004c0b4513c0c57ef71c36e8f Mon Sep 17 00:00:00 2001 From: emily Date: Tue, 7 Jan 2020 10:35:25 -0800 Subject: [PATCH] Add bootstrapped test networks for service networking tests (#2920) Merged PR #2920. --- build/terraform | 2 +- build/terraform-beta | 2 +- ...urce_service_networking_connection_test.go | 95 +++++-------------- ...resource_sql_database_instance_test.go.erb | 15 ++- .../terraform/utils/bootstrap_utils_test.go | 61 ++++++++++++ 5 files changed, 94 insertions(+), 81 deletions(-) diff --git a/build/terraform b/build/terraform index a0521bd7d4a7..f004d58dee60 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit a0521bd7d4a7d81aa4ab6c77a5809c419aaaf0d5 +Subproject commit f004d58dee6013cb72b3209e6e71b69684a3f751 diff --git a/build/terraform-beta b/build/terraform-beta index 7b7994e1497f..812048aa8a13 160000 --- a/build/terraform-beta +++ b/build/terraform-beta @@ -1 +1 @@ -Subproject commit 7b7994e1497f4d4080c18282bdefb25dbcb5b5d9 +Subproject commit 812048aa8a13da9f199efc53ca76d7ac39e0f1b7 diff --git a/third_party/terraform/tests/resource_service_networking_connection_test.go b/third_party/terraform/tests/resource_service_networking_connection_test.go index 65263055da90..4932b7f7ef26 100644 --- a/third_party/terraform/tests/resource_service_networking_connection_test.go +++ b/third_party/terraform/tests/resource_service_networking_connection_test.go @@ -9,19 +9,20 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/terraform" ) -func TestAccServiceNetworkingConnectionCreate(t *testing.T) { +func TestAccServiceNetworkingConnection_create(t *testing.T) { t.Parallel() + network := BootstrapSharedServiceNetworkingConsumerNetwork(t, "service-networking-connection-create") + addr := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + service := "servicenetworking.googleapis.com" + resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testServiceNetworkingConnectionDestroy(service, network), Steps: []resource.TestStep{ { - Config: testAccServiceNetworkingConnection( - fmt.Sprintf("tf-test-%s", acctest.RandString(10)), - fmt.Sprintf("tf-test-%s", acctest.RandString(10)), - "servicenetworking.googleapis.com", - ), + Config: testAccServiceNetworkingConnection(network, addr, "servicenetworking.googleapis.com"), }, { ResourceName: "google_service_networking_connection.foobar", @@ -32,49 +33,21 @@ func TestAccServiceNetworkingConnectionCreate(t *testing.T) { }) } -// Standard checkDestroy cannot be used here because destroying the network will delete -// all the networking connections so this would return false positives. -func TestAccServiceNetworkingConnectionDestroy(t *testing.T) { +func TestAccServiceNetworkingConnection_update(t *testing.T) { t.Parallel() - network := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - addressRange := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - Steps: []resource.TestStep{ - { - Config: testAccServiceNetworkingConnection( - network, - addressRange, - "servicenetworking.googleapis.com", - ), - }, - { - Config: testAccServiceNetworkingConnectionDestroy(network, addressRange), - Check: resource.ComposeTestCheckFunc( - testServiceNetworkingConnectionDestroy("servicenetworking.googleapis.com", network, getTestProjectFromEnv()), - ), - }, - }, - }) -} - -func TestAccServiceNetworkingConnectionUpdate(t *testing.T) { - t.Parallel() + network := BootstrapSharedServiceNetworkingConsumerNetwork(t, "service-networking-connection-update") + addr1 := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + addr2 := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + service := "servicenetworking.googleapis.com" - network := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testServiceNetworkingConnectionDestroy(service, network), Steps: []resource.TestStep{ { - Config: testAccServiceNetworkingConnection( - network, - fmt.Sprintf("tf-test-%s", acctest.RandString(10)), - "servicenetworking.googleapis.com", - ), + Config: testAccServiceNetworkingConnection(network, addr1, "servicenetworking.googleapis.com"), }, { ResourceName: "google_service_networking_connection.foobar", @@ -82,11 +55,7 @@ func TestAccServiceNetworkingConnectionUpdate(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccServiceNetworkingConnection( - network, - fmt.Sprintf("tf-test-%s", acctest.RandString(10)), - "servicenetworking.googleapis.com", - ), + Config: testAccServiceNetworkingConnection(network, addr2, "servicenetworking.googleapis.com"), }, { ResourceName: "google_service_networking_connection.foobar", @@ -98,11 +67,11 @@ func TestAccServiceNetworkingConnectionUpdate(t *testing.T) { } -func testServiceNetworkingConnectionDestroy(parent, network, project string) resource.TestCheckFunc { +func testServiceNetworkingConnectionDestroy(parent, network string) resource.TestCheckFunc { return func(s *terraform.State) error { config := testAccProvider.Meta().(*Config) parentService := "services/" + parent - networkName := fmt.Sprintf("projects/%s/global/networks/%s", project, network) + networkName := fmt.Sprintf("projects/%s/global/networks/%s", getTestProjectFromEnv(), network) response, err := config.clientServiceNetworking.Services.Connections.List(parentService). Network(networkName).Do() @@ -122,7 +91,7 @@ func testServiceNetworkingConnectionDestroy(parent, network, project string) res func testAccServiceNetworkingConnection(networkName, addressRangeName, serviceName string) string { return fmt.Sprintf(` -resource "google_compute_network" "foobar" { +data "google_compute_network" "servicenet" { name = "%s" } @@ -131,29 +100,13 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = google_compute_network.foobar.self_link + network = data.google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = google_compute_network.foobar.self_link + network = data.google_compute_network.servicenet.self_link service = "%s" reserved_peering_ranges = [google_compute_global_address.foobar.name] } `, networkName, addressRangeName, serviceName) } - -func testAccServiceNetworkingConnectionDestroy(networkName, addressRangeName string) string { - return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "%s" -} - -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.foobar.self_link -} -`, networkName, addressRangeName) -} diff --git a/third_party/terraform/tests/resource_sql_database_instance_test.go.erb b/third_party/terraform/tests/resource_sql_database_instance_test.go.erb index b0dfe68b3ba9..9c0015ead506 100644 --- a/third_party/terraform/tests/resource_sql_database_instance_test.go.erb +++ b/third_party/terraform/tests/resource_sql_database_instance_test.go.erb @@ -628,18 +628,18 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork(t *testing.T) { t.Parallel() databaseName := "tf-test-" + acctest.RandString(10) - networkName := "tf-test-" + acctest.RandString(10) addressName := "tf-test-" + acctest.RandString(10) + networkName := BootstrapSharedServiceNetworkingConsumerNetwork(t, "sql-instance-private") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccSqlDatabaseInstanceDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccSqlDatabaseInstance_withPrivateNetwork(databaseName, networkName, addressName), }, - resource.TestStep{ + { ResourceName: "google_sql_database_instance.instance", ImportState: true, ImportStateVerify: true, @@ -789,9 +789,8 @@ resource "google_sql_database_instance" "instance-failover" { <%# This test doesn't work in GA yet because service networking is still in beta -%> func testAccSqlDatabaseInstance_withPrivateNetwork(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -resource "google_compute_network" "foobar" { +data "google_compute_network" "servicenet" { name = "%s" - auto_create_subnetworks = false } resource "google_compute_global_address" "foobar" { @@ -799,11 +798,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = google_compute_network.foobar.self_link + network = data.google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = google_compute_network.foobar.self_link + network = data.google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -816,7 +815,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.foobar.self_link + private_network = data.google_compute_network.servicenet.self_link } } } diff --git a/third_party/terraform/utils/bootstrap_utils_test.go b/third_party/terraform/utils/bootstrap_utils_test.go index fcab7f2e1f56..f654f55e4db3 100644 --- a/third_party/terraform/utils/bootstrap_utils_test.go +++ b/third_party/terraform/utils/bootstrap_utils_test.go @@ -6,6 +6,7 @@ import ( "log" "os" "testing" + "time" "google.golang.org/api/cloudkms/v1" "google.golang.org/api/iam/v1" @@ -230,3 +231,63 @@ func BootstrapServiceAccount(t *testing.T, project, testRunner string) string { return sa.Email } + +const SharedTestNetworkPrefix = "tf-bootstrap-net-" + +// BootstrapSharedServiceNetworkingConsumerNetwork will return a shared compute network +// for service networking test to prevent hitting limits on tenancy projects. +// +// This will either return an existing network or create one if it hasn't been created +// in the project yet. One consumer network/tenant project we don't own is created +// per producer network (i.e. network created by test), with a hard limit set. +func BootstrapSharedServiceNetworkingConsumerNetwork(t *testing.T, testId string) string { + if v := os.Getenv("TF_ACC"); v == "" { + log.Println("Acceptance tests and bootstrapping skipped unless env 'TF_ACC' set") + // If not running acceptance tests, return an empty string + return "" + } + + project := getTestProjectFromEnv() + networkName := SharedTestNetworkPrefix + testId + config := &Config{ + Credentials: getTestCredsFromEnv(), + Project: project, + Region: getTestRegionFromEnv(), + Zone: getTestZoneFromEnv(), + } + ConfigureBasePaths(config) + if err := config.LoadAndValidate(context.Background()); err != nil { + t.Errorf("Unable to bootstrap network: %s", err) + } + + log.Printf("[DEBUG] Getting shared test network %q", networkName) + _, err := config.clientCompute.Networks.Get(project, networkName).Do() + if err != nil && isGoogleApiErrorWithCode(err, 404) { + log.Printf("[DEBUG] Network %q not found, bootstrapping", networkName) + url := fmt.Sprintf("%sprojects/%s/global/networks", config.ComputeBasePath, project) + netObj := map[string]interface{}{ + "name": networkName, + "autoCreateSubnetworks": false, + } + + res, err := sendRequestWithTimeout(config, "POST", project, url, netObj, 4*time.Minute) + if err != nil { + t.Fatalf("Error bootstrapping shared test network %q: %s", networkName, err) + } + + log.Printf("[DEBUG] Waiting for network creation to finish") + err = computeOperationWaitTime(config, res, project, "Error bootstrapping shared test network", 4) + if err != nil { + t.Fatalf("Error bootstrapping shared test network %q: %s", networkName, err) + } + } + + network, err := config.clientCompute.Networks.Get(project, networkName).Do() + if err != nil { + t.Errorf("Error getting shared test network %q: %s", networkName, err) + } + if network == nil { + t.Fatalf("Error getting shared test network %q: is nil", networkName) + } + return network.Name +}