Skip to content

Commit

Permalink
Added abandon policy (#9765) (#16944)
Browse files Browse the repository at this point in the history
* Added abandon policy

* Fixed linting errors on line 68 and 262

* added test coverage

* Fixed test case to pass if network is destroyed successfully

* Disabled testing for state import. Deletion policy isn't an API attribute so it will never import.

* Added documentation for the additional argument
[upstream:76d03c3ad1652dc12fb5f738a907719aa01e0d8e]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Jan 9, 2024
1 parent 301e338 commit dc9b041
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/9765.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
service: added field `deletion_policy` to `google_service_networking_connection`
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"google.golang.org/api/servicenetworking/v1"
)

Expand Down Expand Up @@ -60,6 +61,12 @@ func ResourceServiceNetworkingConnection() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Description: `Named IP address range(s) of PEERING type reserved for this service provider. Note that invoking this method with a different range when connection is already established will not reallocate already provisioned service producer subnetworks.`,
},
"deletion_policy": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"ABANDON", ""}, false),
Description: `When set to ABANDON, terraform will abandon management of the resource instead of deleting it. Prevents terraform apply failures with CloudSQL. Note: The resource will still exist.`,
},
"peering": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -250,6 +257,12 @@ func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta inte

func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)

if deletionPolicy := d.Get("deletion_policy"); deletionPolicy == "ABANDON" {
log.Printf("[WARN] The service networking connection has been abandoned")
return nil
}

userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ func TestAccServiceNetworkingConnection_create(t *testing.T) {
})
}

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

network := fmt.Sprintf("tf-test-service-networking-connection-abandon-%s", acctest.RandString(t, 10))
addr := 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: testServiceNetworkingConnectionDestroyAbandon(t, service, network),
Steps: []resource.TestStep{
{
Config: testAccServiceNetworkingConnectionToBeAbandoned(network, addr, "servicenetworking.googleapis.com", org_id, billing_account),
},
{
ResourceName: "google_service_networking_connection.foobar",
ImportState: true,
ImportStateVerify: false,
},
},
})
}

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

Expand Down Expand Up @@ -98,6 +124,30 @@ func testServiceNetworkingConnectionDestroy(t *testing.T, parent, network string
}
}

func testServiceNetworkingConnectionDestroyAbandon(t *testing.T, parent, network string) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := acctest.GoogleProviderConfig(t)
parentService := "services/" + parent
networkName := fmt.Sprintf("projects/%s/global/networks/%s", envvar.GetTestProjectFromEnv(), network)
listCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.List(parentService).Network(networkName)
if config.UserProjectOverride {
listCall.Header().Add("X-Goog-User-Project", envvar.GetTestProjectFromEnv())
}
response, err := listCall.Do()
if err != nil {
return err
}

for _, c := range response.Connections {
if c.Network == networkName {
return fmt.Errorf("Found %s which should have been destroyed.", networkName)
}
}

return nil
}
}

func testAccServiceNetworkingConnection(networkName, addressRangeName, serviceName, org_id, billing_account string) string {
return fmt.Sprintf(`
resource "google_project" "project" {
Expand Down Expand Up @@ -134,3 +184,41 @@ resource "google_service_networking_connection" "foobar" {
}
`, addressRangeName, addressRangeName, org_id, billing_account, networkName, addressRangeName, serviceName)
}

func testAccServiceNetworkingConnectionToBeAbandoned(networkName, addressRangeName, serviceName, org_id, billing_account string) 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_service_networking_connection" "foobar" {
network = google_compute_network.servicenet.self_link
service = "%s"
reserved_peering_ranges = [google_compute_global_address.foobar.name]
depends_on = [google_project_service.servicenetworking]
deletion_policy = "ABANDON"
}
`, addressRangeName, addressRangeName, org_id, billing_account, networkName, addressRangeName, serviceName)
}
2 changes: 2 additions & 0 deletions website/docs/r/service_networking_connection.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ The following arguments are supported:
this service provider. Note that invoking this method with a different range when connection
is already established will not reallocate already provisioned service producer subnetworks.

* `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.

## Attributes Reference

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

0 comments on commit dc9b041

Please sign in to comment.