Skip to content

Commit

Permalink
Fix failed tests related to google_service_networking_connection (#8904
Browse files Browse the repository at this point in the history
…) (#6332)

* Bootstrap service networking connection

* Revert tests

* Rename network names

* Modify tests

* Fix tests

* Catch the error when deleteConnection fails

* Fix test TestAccVertexAIIndexEndpoint_updated

* Fix test TestAccAlloydbInstance_createInstanceWithNetworkConfigAndAllocatedIPRange

* Fix test

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Sep 21, 2023
1 parent 0696e16 commit f436492
Show file tree
Hide file tree
Showing 23 changed files with 466 additions and 787 deletions.
3 changes: 3 additions & 0 deletions .changelog/8904.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:breaking-change
servicenetworking: used the `deleteConnection` method to delete the resource `google_service_networking_connection`
```
131 changes: 131 additions & 0 deletions google-beta/acctest/bootstrap_test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
tpgcompute "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/compute"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/services/privateca"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/services/resourcemanager"
tpgservicenetworking "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/servicenetworking"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/services/sql"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgiamresource"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
Expand All @@ -25,6 +26,7 @@ import (
cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
iam "google.golang.org/api/iam/v1"
"google.golang.org/api/iamcredentials/v1"
"google.golang.org/api/servicenetworking/v1"
"google.golang.org/api/serviceusage/v1"
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)
Expand Down Expand Up @@ -356,6 +358,135 @@ func BootstrapSharedTestNetwork(t *testing.T, testId string) string {
return network.Name
}

const SharedTestGlobalAddressPrefix = "tf-bootstrap-addr-"

func BootstrapSharedTestGlobalAddress(t *testing.T, testId, networkId string) string {
project := envvar.GetTestProjectFromEnv()
addressName := SharedTestGlobalAddressPrefix + testId

config := BootstrapConfig(t)
if config == nil {
return ""
}

log.Printf("[DEBUG] Getting shared test global address %q", addressName)
_, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do()
if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) {
log.Printf("[DEBUG] Global address %q not found, bootstrapping", addressName)
url := fmt.Sprintf("%sprojects/%s/global/addresses", config.ComputeBasePath, project)
netObj := map[string]interface{}{
"name": addressName,
"address_type": "INTERNAL",
"purpose": "VPC_PEERING",
"prefix_length": 16,
"network": networkId,
}

res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "POST",
Project: project,
RawURL: url,
UserAgent: config.UserAgent,
Body: netObj,
Timeout: 4 * time.Minute,
})
if err != nil {
t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err)
}

log.Printf("[DEBUG] Waiting for global address creation to finish")
err = tpgcompute.ComputeOperationWaitTime(config, res, project, "Error bootstrapping shared test global address", config.UserAgent, 4*time.Minute)
if err != nil {
t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err)
}
}

address, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do()
if err != nil {
t.Errorf("Error getting shared test global address %q: %s", addressName, err)
}
if address == nil {
t.Fatalf("Error getting shared test global address %q: is nil", addressName)
}
return address.Name
}

// BootstrapSharedServiceNetworkingConnection will create a shared network
// if it hasn't been created in the test project, a global address
// if it hasn't been created in the test project, and a service networking connection
// if it hasn't been created in the test project.
//
// BootstrapSharedServiceNetworkingConnection returns a persistent compute network name
// for a test or set of tests.
//
// To delete a service networking conneciton, all of the service instances that use that connection
// must be deleted first. After the service instances are deleted, some service producers delay the deletion
// utnil a waiting period has passed. For example, after four days that you delete a SQL instance,
// the service networking connection can be deleted.
// That is the reason to use the shared service networking connection for thest resources.
// https://cloud.google.com/vpc/docs/configure-private-services-access#removing-connection
//
// testId specifies the test for which a shared network and a gobal address are used/initialized.
func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string) string {
parentService := "services/servicenetworking.googleapis.com"
project := envvar.GetTestProjectFromEnv()
projectNumber := envvar.GetTestProjectNumberFromEnv()

config := BootstrapConfig(t)
if config == nil {
return ""
}

networkName := BootstrapSharedTestNetwork(t, testId)
networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName)
globalAddressName := BootstrapSharedTestGlobalAddress(t, testId, networkId)

readCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.List(parentService).Network(networkId)
if config.UserProjectOverride {
readCall.Header().Add("X-Goog-User-Project", project)
}
response, err := readCall.Do()
if err != nil {
t.Errorf("Error getting shared test service networking connection: %s", err)
}

var connection *servicenetworking.Connection
for _, c := range response.Connections {
if c.Network == networkId {
connection = c
break
}
}

if connection == nil {
log.Printf("[DEBUG] Service networking connection not found, bootstrapping")

connection := &servicenetworking.Connection{
Network: networkId,
ReservedPeeringRanges: []string{globalAddressName},
}

createCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.Create(parentService, connection)
if config.UserProjectOverride {
createCall.Header().Add("X-Goog-User-Project", project)
}
op, err := createCall.Do()
if err != nil {
t.Fatalf("Error bootstrapping shared test service networking connection: %s", err)
}

log.Printf("[DEBUG] Waiting for service networking connection creation to finish")
if err := tpgservicenetworking.ServiceNetworkingOperationWaitTime(config, op, "Create Service Networking Connection", config.UserAgent, project, 4*time.Minute); err != nil {
t.Fatalf("Error bootstrapping shared test service networking connection: %s", err)
}
}

log.Printf("[DEBUG] Getting shared test service networking connection")

return networkName
}

var SharedServicePerimeterProjectPrefix = "tf-bootstrap-sp-"

func BootstrapServicePerimeterProjects(t *testing.T, desiredProjects int) []*cloudresourcemanager.Project {
Expand Down
108 changes: 41 additions & 67 deletions google-beta/services/alloydb/resource_alloydb_backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestAccAlloydbBackup_update(t *testing.T) {

random_suffix := acctest.RandString(t, 10)
context := map[string]interface{}{
"network_name": "tf-test-alloydb-network" + random_suffix,
"network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-update-1"),
"random_suffix": random_suffix,
}

Expand All @@ -24,7 +24,7 @@ func TestAccAlloydbBackup_update(t *testing.T) {
CheckDestroy: testAccCheckAlloydbBackupDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbBackup_alloydbBackupFullExample(context),
Config: testAccAlloydbBackup_alloydbBackupBasic(context),
},
{
ResourceName: "google_alloydb_backup.default",
Expand All @@ -45,8 +45,7 @@ func TestAccAlloydbBackup_update(t *testing.T) {
})
}

// Updates "label" field from testAccAlloydbBackup_alloydbBackupFullExample
func testAccAlloydbBackup_update(context map[string]interface{}) string {
func testAccAlloydbBackup_alloydbBackupBasic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_alloydb_backup" "default" {
location = "us-central1"
Expand All @@ -55,41 +54,58 @@ resource "google_alloydb_backup" "default" {
description = "example description"
labels = {
"label" = "updated_key"
"label2" = "updated_key2"
"label" = "key"
}
depends_on = [google_alloydb_instance.default]
}
resource "google_alloydb_cluster" "default" {
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
location = "us-central1"
network = google_compute_network.default.id
network = data.google_compute_network.default.id
}
resource "google_alloydb_instance" "default" {
cluster = google_alloydb_cluster.default.name
instance_id = "tf-test-alloydb-instance%{random_suffix}"
instance_type = "PRIMARY"
}
data "google_compute_network" "default" {
name = "%{network_name}"
}
`, context)
}

// Updates "label" field
func testAccAlloydbBackup_update(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_alloydb_backup" "default" {
location = "us-central1"
backup_id = "tf-test-alloydb-backup%{random_suffix}"
cluster_name = google_alloydb_cluster.default.name
depends_on = [google_service_networking_connection.vpc_connection]
description = "example description"
labels = {
"label" = "updated_key"
"label2" = "updated_key2"
}
depends_on = [google_alloydb_instance.default]
}
resource "google_compute_global_address" "private_ip_alloc" {
name = "tf-test-alloydb-cluster%{random_suffix}"
address_type = "INTERNAL"
purpose = "VPC_PEERING"
prefix_length = 16
network = google_compute_network.default.id
resource "google_alloydb_cluster" "default" {
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
location = "us-central1"
network = data.google_compute_network.default.id
}
resource "google_service_networking_connection" "vpc_connection" {
network = google_compute_network.default.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
resource "google_alloydb_instance" "default" {
cluster = google_alloydb_cluster.default.name
instance_id = "tf-test-alloydb-instance%{random_suffix}"
instance_type = "PRIMARY"
}
resource "google_compute_network" "default" {
data "google_compute_network" "default" {
name = "%{network_name}"
}
`, context)
Expand All @@ -101,7 +117,7 @@ func TestAccAlloydbBackup_createBackupWithMandatoryFields(t *testing.T) {

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
"network_name": "tf-test-" + acctest.RandString(t, 10),
"network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-mandatory-1"),
}

acctest.VcrTest(t, resource.TestCase{
Expand All @@ -128,45 +144,19 @@ resource "google_alloydb_backup" "default" {
resource "google_alloydb_cluster" "default" {
location = "us-central1"
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
network = google_compute_network.default.id
network = data.google_compute_network.default.id
}
data "google_project" "project" { }
resource "google_compute_network" "default" {
data "google_compute_network" "default" {
name = "%{network_name}"
}
resource "google_alloydb_instance" "default" {
cluster = google_alloydb_cluster.default.name
instance_id = "tf-test-alloydb-instance%{random_suffix}"
instance_type = "PRIMARY"
depends_on = [google_service_networking_connection.vpc_connection]
}
resource "google_compute_global_address" "private_ip_alloc" {
name = "tf-test-alloydb-cluster%{random_suffix}"
address_type = "INTERNAL"
purpose = "VPC_PEERING"
prefix_length = 16
network = google_compute_network.default.id
lifecycle {
ignore_changes = [
address,
creation_timestamp,
id,
network,
project,
self_link
]
}
}
resource "google_service_networking_connection" "vpc_connection" {
network = google_compute_network.default.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
}
`, context)
}
Expand All @@ -175,7 +165,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"network_name": "tf-test-" + acctest.RandString(t, 10),
"network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-cmek-1"),
"random_suffix": acctest.RandString(t, 10),
"key_name": "tf-test-key-" + acctest.RandString(t, 10),
}
Expand Down Expand Up @@ -218,32 +208,16 @@ resource "google_alloydb_backup" "default" {
resource "google_alloydb_cluster" "default" {
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
location = "us-central1"
network = google_compute_network.default.id
network = data.google_compute_network.default.id
}
resource "google_alloydb_instance" "default" {
cluster = google_alloydb_cluster.default.name
instance_id = "tf-test-alloydb-instance%{random_suffix}"
instance_type = "PRIMARY"
depends_on = [google_service_networking_connection.vpc_connection]
}
resource "google_compute_global_address" "private_ip_alloc" {
name = "tf-test-alloydb-cluster%{random_suffix}"
address_type = "INTERNAL"
purpose = "VPC_PEERING"
prefix_length = 16
network = google_compute_network.default.id
}
resource "google_service_networking_connection" "vpc_connection" {
network = google_compute_network.default.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
}
resource "google_compute_network" "default" {
data "google_compute_network" "default" {
name = "%{network_name}"
}
data "google_project" "project" {}
Expand Down
Loading

0 comments on commit f436492

Please sign in to comment.