Skip to content

Commit

Permalink
Add a flag to use patch when creating a service networking connection…
Browse files Browse the repository at this point in the history
… fails (#11364)
  • Loading branch information
zli82016 authored Aug 7, 2024
1 parent 3aff522 commit 6af157e
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ func ResourceServiceNetworkingConnection() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"update_on_creation_fail": {
Type: schema.TypeBool,
Optional: true,
Description: `When set to true, enforce an update of the reserved peering ranges on the existing service networking connection in case of a new connection creation failure.`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -118,7 +123,21 @@ func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta inte
}

if err := ServiceNetworkingOperationWaitTimeHW(config, op, "Create Service Networking Connection", userAgent, project, d.Timeout(schema.TimeoutCreate)); err != nil {
return err
if strings.Contains(err.Error(), "Cannot modify allocated ranges in CreateConnection.") && d.Get("update_on_creation_fail").(bool) {
patchCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.Patch(parentService+"/connections/-", connection).UpdateMask("reservedPeeringRanges").Force(true)
if config.UserProjectOverride {
patchCall.Header().Add("X-Goog-User-Project", project)
}
op, err := patchCall.Do()
if err != nil {
return err
}
if err := ServiceNetworkingOperationWaitTimeHW(config, op, "Update Service Networking Connection", userAgent, project, d.Timeout(schema.TimeoutUpdate)); err != nil {
return err
}
} else {
return err
}
}

connectionId := &connectionId{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package servicenetworking_test

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
Expand Down Expand Up @@ -62,6 +63,38 @@ func TestAccServiceNetworkingConnection_abandon(t *testing.T) {
})
}

func TestAccServiceNetworkingConnection_updateOnCreationFail(t *testing.T) {
t.Parallel()

network := fmt.Sprintf("tf-test-service-networking-connection-update-%s", acctest.RandString(t, 10))
addr1 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
addr2 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
service := "servicenetworking.googleapis.com"
org_id := envvar.GetTestOrgFromEnv(t)
billing_account := envvar.GetTestBillingAccountFromEnv(t)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testServiceNetworkingConnectionDestroy(t, service, network),
Steps: []resource.TestStep{
{
Config: testAccServiceNetworkingConnections(network, addr1, addr2, "servicenetworking.googleapis.com", org_id, billing_account, false),
ExpectError: regexp.MustCompile("Cannot modify allocated ranges in CreateConnection. Please use UpdateConnection"),
},
{
Config: testAccServiceNetworkingConnections(network, addr1, addr2, "servicenetworking.googleapis.com", org_id, billing_account, true),
// google_service_networking_connection.foobar and google_service_networking_connection.foobar1 are the same service networking connection
// as they have the same network and service. When update_on_creation_fail is set to true, the service networking connection is updated
// with peering range google_compute_global_address.foobar1 successfully through google_service_networking_connection.foobar1.
// After refresh, google_service_networking_connection.foobar will also have the updated peering range google_compute_global_address.foobar1, so the plan is not empty.
ExpectNonEmptyPlan: true,
},
},
})

}

func TestAccServiceNetworkingConnection_update(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -183,6 +216,61 @@ resource "google_service_networking_connection" "foobar" {
`, addressRangeName, addressRangeName, org_id, billing_account, networkName, addressRangeName, serviceName)
}

func testAccServiceNetworkingConnections(networkName, addressRangeName, addressRangeName1, serviceName, org_id, billing_account string, update_on_creation_fail bool) string {
return fmt.Sprintf(`
resource "google_project" "project" {
project_id = "%s"
name = "%s"
org_id = "%s"
billing_account = "%s"
}
resource "google_project_service" "servicenetworking" {
project = google_project.project.project_id
service = "servicenetworking.googleapis.com"
}
resource "google_compute_network" "servicenet" {
name = "%s"
depends_on = [google_project_service.servicenetworking]
}
resource "google_compute_global_address" "foobar" {
name = "%s"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = google_compute_network.servicenet.self_link
depends_on = [google_project_service.servicenetworking]
}
resource "google_compute_global_address" "foobar1" {
name = "%s"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = google_compute_network.servicenet.self_link
depends_on = [google_project_service.servicenetworking]
}
resource "google_service_networking_connection" "foobar" {
network = google_compute_network.servicenet.self_link
service = "%s"
reserved_peering_ranges = [google_compute_global_address.foobar.name]
deletion_policy = "ABANDON"
depends_on = [google_project_service.servicenetworking]
}
resource "google_service_networking_connection" "foobar1" {
network = google_compute_network.servicenet.self_link
service = "%s"
reserved_peering_ranges = [google_compute_global_address.foobar1.name]
update_on_creation_fail = "%t"
depends_on = [google_service_networking_connection.foobar]
}
`, addressRangeName, addressRangeName, org_id, billing_account, networkName, addressRangeName, addressRangeName1, serviceName, serviceName, update_on_creation_fail)
}

func testAccServiceNetworkingConnectionToBeAbandoned(networkName, addressRangeName, serviceName, org_id, billing_account string) string {
return fmt.Sprintf(`
resource "google_project" "project" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ The following arguments are supported:

* `deletion_policy` - (Optional) The deletion policy for the service networking connection. Setting to ABANDON allows the resource to be abandoned rather than deleted. This will enable a successful terraform destroy when destroying CloudSQL instances. Use with care as it can lead to dangling resources.

* `update_on_creation_fail` - (Optional) When set to true, enforce an update of the reserved peering ranges on the existing service networking connection in case of a new connection creation failure.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are exported:
Expand Down

0 comments on commit 6af157e

Please sign in to comment.