Skip to content

Commit

Permalink
Support delete for network peering
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
chrisst authored and modular-magician committed Jul 11, 2019
1 parent 16071f7 commit b2d0bf1
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 26 deletions.
74 changes: 54 additions & 20 deletions google/resource_service_networking_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"regexp"
"strings"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/compute/v1"
"google.golang.org/api/servicenetworking/v1"
)

Expand All @@ -22,7 +24,7 @@ func resourceServiceNetworkingConnection() *schema.Resource {
},

Schema: map[string]*schema.Schema{
"network": {
"network": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
Expand All @@ -34,16 +36,20 @@ func resourceServiceNetworkingConnection() *schema.Resource {
// CLI's approach, calling the field "service" and accepting the same format as the CLI with the "."
// delimiter.
// See: https://cloud.google.com/vpc/docs/configure-private-services-access#creating-connection
"service": {
"service": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"reserved_peering_ranges": {
"reserved_peering_ranges": &schema.Schema{
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"peering": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand All @@ -54,7 +60,7 @@ func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta inte
network := d.Get("network").(string)
serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
if err != nil {
return fmt.Errorf("Failed to find Service Networking Connection, err: %s", err)
return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
}

connection := &servicenetworking.Connection{
Expand Down Expand Up @@ -86,18 +92,17 @@ func resourceServiceNetworkingConnectionRead(d *schema.ResourceData, meta interf

connectionId, err := parseConnectionId(d.Id())
if err != nil {
return fmt.Errorf("Failed to find Service Networking Connection, err: %s", err)
return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
}

serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, connectionId.Network)
if err != nil {
return fmt.Errorf("Failed to find Service Networking Connection, err: %s", err)
return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
}

parentService := formatParentService(connectionId.Service)
listCall := config.clientServiceNetworking.Services.Connections.List(parentService)
listCall.Network(serviceNetworkingNetworkName)
response, err := listCall.Do()
response, err := config.clientServiceNetworking.Services.Connections.List(parentService).
Network(serviceNetworkingNetworkName).Do()
if err != nil {
return err
}
Expand All @@ -111,11 +116,14 @@ func resourceServiceNetworkingConnectionRead(d *schema.ResourceData, meta interf
}

if connection == nil {
return fmt.Errorf("Failed to find Service Networking Connection, network: %s service: %s", connectionId.Network, connectionId.Service)
d.SetId("")
log.Printf("[WARNING] Failed to find Service Networking Connection, network: %s service: %s", connectionId.Network, connectionId.Service)
return nil
}

d.Set("network", connectionId.Network)
d.Set("service", connectionId.Service)
d.Set("peering", connection.Peering)
d.Set("reserved_peering_ranges", connection.ReservedPeeringRanges)
return nil
}
Expand All @@ -125,7 +133,7 @@ func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta inte

connectionId, err := parseConnectionId(d.Id())
if err != nil {
return fmt.Errorf("Failed to find Service Networking Connection, err: %s", err)
return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err)
}

parentService := formatParentService(connectionId.Service)
Expand All @@ -134,7 +142,7 @@ func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta inte
network := d.Get("network").(string)
serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
if err != nil {
return fmt.Errorf("Failed to find Service Networking Connection, err: %s", err)
return errwrap.Wrapf("Failed to find Service Networking Connection, err: {{err}}", err)
}

connection := &servicenetworking.Connection{
Expand All @@ -155,18 +163,44 @@ func resourceServiceNetworkingConnectionUpdate(d *schema.ResourceData, meta inte
return resourceServiceNetworkingConnectionRead(d, meta)
}

// NOTE(craigatgoogle): This resource doesn't have a defined Delete method, however an un-documented
// behavior is for the Connection to be deleted when its associated network is deleted. This is
// helpeful for acctest cleanup.
func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta interface{}) error {
connectionId, err := parseConnectionId(d.Id())
config := meta.(*Config)

network := d.Get("network").(string)
serviceNetworkingNetworkName, err := retrieveServiceNetworkingNetworkName(d, config, network)
if err != nil {
return err
}

log.Printf("[WARNING] Service Networking Connection resources cannot be deleted from GCP. This Connection (network: %s, service: %s) will be removed from Terraform state, but will still be present on the server.", connectionId.Network, connectionId.Service)
obj := make(map[string]interface{})
peering := d.Get("peering").(string)
obj["name"] = peering
url := fmt.Sprintf("%s%s/removePeering", config.ComputeBasePath, serviceNetworkingNetworkName)

res, err := sendRequestWithTimeout(config, "POST", url, obj, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("Error removing connection from network %s: %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.SetId("")
log.Printf("[INFO] Service network connection removed.")

return nil
}
Expand Down Expand Up @@ -202,14 +236,14 @@ func parseConnectionId(id string) (*connectionId, error) {

network, err := url.QueryUnescape(res[0])
if err != nil {
return nil, fmt.Errorf("Failed to parse service networking connection id, invalid network, err: %s", err)
return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid network, err: {{err}}", err)
} else if len(network) == 0 {
return nil, fmt.Errorf("Failed to parse service networking connection id, empty network")
}

service, err := url.QueryUnescape(res[1])
if err != nil {
return nil, fmt.Errorf("Failed to parse service networking connection id, invalid service, err: %s", err)
return nil, errwrap.Wrapf("Failed to parse service networking connection id, invalid service, err: {{err}}", err)
} else if len(service) == 0 {
return nil, fmt.Errorf("Failed to parse service networking connection id, empty service")
}
Expand All @@ -226,7 +260,7 @@ func parseConnectionId(id string) (*connectionId, error) {
func retrieveServiceNetworkingNetworkName(d *schema.ResourceData, config *Config, network string) (string, error) {
networkFieldValue, err := ParseNetworkFieldValue(network, d, config)
if err != nil {
return "", fmt.Errorf("Failed to retrieve network field value, err: %s", err)
return "", errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err)
}

pid := networkFieldValue.Project
Expand Down
82 changes: 76 additions & 6 deletions google/resource_service_networking_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"

)

func TestAccServiceNetworkingConnectionCreate(t *testing.T) {
Expand All @@ -15,23 +17,52 @@ func TestAccServiceNetworkingConnectionCreate(t *testing.T) {
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
resource.TestStep{
Config: testAccServiceNetworkingConnection(
fmt.Sprintf("tf-test-%s", acctest.RandString(10)),
fmt.Sprintf("tf-test-%s", acctest.RandString(10)),
"servicenetworking.googleapis.com",
),
},
{
resource.TestStep{
ResourceName: "google_service_networking_connection.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

// 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) {
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{
resource.TestStep{
Config: testAccServiceNetworkingConnection(
network,
addressRange,
"servicenetworking.googleapis.com",
),
},
resource.TestStep{
Config: testAccServiceNetworkingConnectionDestroy(network, addressRange),
Check: resource.ComposeTestCheckFunc(
testServiceNetworkingConnectionDestroy("servicenetworking.googleapis.com", network, getTestProjectFromEnv()),
),
},
},
})
}


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

Expand All @@ -40,26 +71,26 @@ func TestAccServiceNetworkingConnectionUpdate(t *testing.T) {
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
resource.TestStep{
Config: testAccServiceNetworkingConnection(
network,
fmt.Sprintf("tf-test-%s", acctest.RandString(10)),
"servicenetworking.googleapis.com",
),
},
{
resource.TestStep{
ResourceName: "google_service_networking_connection.foobar",
ImportState: true,
ImportStateVerify: true,
},
{
resource.TestStep{
Config: testAccServiceNetworkingConnection(
network,
fmt.Sprintf("tf-test-%s", acctest.RandString(10)),
"servicenetworking.googleapis.com",
),
},
{
resource.TestStep{
ResourceName: "google_service_networking_connection.foobar",
ImportState: true,
ImportStateVerify: true,
Expand All @@ -69,6 +100,29 @@ func TestAccServiceNetworkingConnectionUpdate(t *testing.T) {

}

func testServiceNetworkingConnectionDestroy(parent, network, project 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)


response, err := config.clientServiceNetworking.Services.Connections.List(parentService).
Network(networkName).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 string) string {
return fmt.Sprintf(`
resource "google_compute_network" "foobar" {
Expand All @@ -90,3 +144,19 @@ resource "google_service_networking_connection" "foobar" {
}
`, 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)
}
1 change: 1 addition & 0 deletions google/resource_sql_database_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"

sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

Expand Down

0 comments on commit b2d0bf1

Please sign in to comment.