From a84b92da47122442524846aeab327f48bdd24743 Mon Sep 17 00:00:00 2001 From: The Magician Date: Thu, 2 May 2024 13:20:28 -0700 Subject: [PATCH] Ncc rep resource (#10573) (#7313) [upstream:07c06ecd2a0d5b9a5d040102eb4dc26676e6152b] Signed-off-by: Modular Magician --- .../provider/provider_mmv1_resources.go | 5 +- ..._network_connectivity_regional_endpoint.go | 535 ++++++++++++++++++ ...tivity_regional_endpoint_generated_test.go | 174 ++++++ ..._connectivity_regional_endpoint_sweeper.go | 139 +++++ ...nnectivity_regional_endpoint.html.markdown | 211 +++++++ 5 files changed, 1062 insertions(+), 2 deletions(-) create mode 100644 google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint.go create mode 100644 google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_generated_test.go create mode 100644 google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_sweeper.go create mode 100644 website/docs/r/network_connectivity_regional_endpoint.html.markdown diff --git a/google-beta/provider/provider_mmv1_resources.go b/google-beta/provider/provider_mmv1_resources.go index c0c440fe87..0109dbec7d 100644 --- a/google-beta/provider/provider_mmv1_resources.go +++ b/google-beta/provider/provider_mmv1_resources.go @@ -451,9 +451,9 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ } // Resources -// Generated resources: 462 +// Generated resources: 463 // Generated IAM resources: 267 -// Total generated resources: 729 +// Total generated resources: 730 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -1000,6 +1000,7 @@ var generatedResources = map[string]*schema.Resource{ "google_netapp_storage_pool": netapp.ResourceNetappstoragePool(), "google_network_connectivity_internal_range": networkconnectivity.ResourceNetworkConnectivityInternalRange(), "google_network_connectivity_policy_based_route": networkconnectivity.ResourceNetworkConnectivityPolicyBasedRoute(), + "google_network_connectivity_regional_endpoint": networkconnectivity.ResourceNetworkConnectivityRegionalEndpoint(), "google_network_connectivity_service_connection_policy": networkconnectivity.ResourceNetworkConnectivityServiceConnectionPolicy(), "google_network_management_connectivity_test": networkmanagement.ResourceNetworkManagementConnectivityTest(), "google_network_security_address_group": networksecurity.ResourceNetworkSecurityAddressGroup(), diff --git a/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint.go b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint.go new file mode 100644 index 0000000000..5f7aa8374e --- /dev/null +++ b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint.go @@ -0,0 +1,535 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networkconnectivity + +import ( + "fmt" + "log" + "net/http" + "reflect" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" +) + +func ResourceNetworkConnectivityRegionalEndpoint() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkConnectivityRegionalEndpointCreate, + Read: resourceNetworkConnectivityRegionalEndpointRead, + Update: resourceNetworkConnectivityRegionalEndpointUpdate, + Delete: resourceNetworkConnectivityRegionalEndpointDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkConnectivityRegionalEndpointImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "access_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"GLOBAL", "REGIONAL"}), + Description: `The access type of this regional endpoint. This field is reflected in the PSC Forwarding Rule configuration to enable global access. Possible values: ["GLOBAL", "REGIONAL"]`, + }, + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location of the RegionalEndpoint.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the RegionalEndpoint.`, + }, + "target_google_api": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The service endpoint this private regional endpoint connects to. Format: '{apiname}.{region}.p.rep.googleapis.com' Example: \"cloudkms.us-central1.p.rep.googleapis.com\".`, + }, + "address": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The IP Address of the Regional Endpoint. When no address is provided, an IP from the subnetwork is allocated. Use one of the following formats: * IPv4 address as in '10.0.0.1' * Address resource URI as in 'projects/{project}/regions/{region}/addresses/{address_name}' + +~> **Note:** This field accepts both a reference to a Compute Address resource, which is the resource name of which format is given in the description, and IP literal value. If the user chooses to input a reserved address value; they need to make sure that the reserved address is in IPv4 version, its purpose is GCE_ENDPOINT, its type is INTERNAL and its status is RESERVED. If the user chooses to input an IP literal, they need to make sure that it's a valid IPv4 address (x.x.x.x) within the subnetwork.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `A description of this resource.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `User-defined labels. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The name of the VPC network for this private regional endpoint. Format: 'projects/{project}/global/networks/{network}'`, + }, + "subnetwork": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The name of the subnetwork from which the IP address will be allocated. Format: 'projects/{project}/regions/{region}/subnetworks/{subnetwork}'`, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time when the RegionalEndpoint was created.`, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + ForceNew: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "psc_forwarding_rule": { + Type: schema.TypeString, + Computed: true, + Description: `The resource reference of the PSC Forwarding Rule created on behalf of the customer. Format: '//compute.googleapis.com/projects/{project}/regions/{region}/forwardingRules/{forwarding_rule_name}'`, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time when the RegionalEndpoint was updated.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkConnectivityRegionalEndpointCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + descriptionProp, err := expandNetworkConnectivityRegionalEndpointDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + targetGoogleApiProp, err := expandNetworkConnectivityRegionalEndpointTargetGoogleApi(d.Get("target_google_api"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("target_google_api"); !tpgresource.IsEmptyValue(reflect.ValueOf(targetGoogleApiProp)) && (ok || !reflect.DeepEqual(v, targetGoogleApiProp)) { + obj["targetGoogleApi"] = targetGoogleApiProp + } + networkProp, err := expandNetworkConnectivityRegionalEndpointNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !tpgresource.IsEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } + subnetworkProp, err := expandNetworkConnectivityRegionalEndpointSubnetwork(d.Get("subnetwork"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("subnetwork"); !tpgresource.IsEmptyValue(reflect.ValueOf(subnetworkProp)) && (ok || !reflect.DeepEqual(v, subnetworkProp)) { + obj["subnetwork"] = subnetworkProp + } + accessTypeProp, err := expandNetworkConnectivityRegionalEndpointAccessType(d.Get("access_type"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("access_type"); !tpgresource.IsEmptyValue(reflect.ValueOf(accessTypeProp)) && (ok || !reflect.DeepEqual(v, accessTypeProp)) { + obj["accessType"] = accessTypeProp + } + addressProp, err := expandNetworkConnectivityRegionalEndpointAddress(d.Get("address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("address"); !tpgresource.IsEmptyValue(reflect.ValueOf(addressProp)) && (ok || !reflect.DeepEqual(v, addressProp)) { + obj["address"] = addressProp + } + labelsProp, err := expandNetworkConnectivityRegionalEndpointEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkConnectivityBasePath}}projects/{{project}}/locations/{{location}}/regionalEndpoints?regional_endpoint_id={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new RegionalEndpoint: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RegionalEndpoint: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating RegionalEndpoint: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkConnectivityOperationWaitTime( + config, res, project, "Creating RegionalEndpoint", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create RegionalEndpoint: %s", err) + } + + log.Printf("[DEBUG] Finished creating RegionalEndpoint %q: %#v", d.Id(), res) + + return resourceNetworkConnectivityRegionalEndpointRead(d, meta) +} + +func resourceNetworkConnectivityRegionalEndpointRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkConnectivityBasePath}}projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RegionalEndpoint: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("NetworkConnectivityRegionalEndpoint %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + + if err := d.Set("create_time", flattenNetworkConnectivityRegionalEndpointCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("update_time", flattenNetworkConnectivityRegionalEndpointUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("labels", flattenNetworkConnectivityRegionalEndpointLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("description", flattenNetworkConnectivityRegionalEndpointDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("target_google_api", flattenNetworkConnectivityRegionalEndpointTargetGoogleApi(res["targetGoogleApi"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("network", flattenNetworkConnectivityRegionalEndpointNetwork(res["network"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("subnetwork", flattenNetworkConnectivityRegionalEndpointSubnetwork(res["subnetwork"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("access_type", flattenNetworkConnectivityRegionalEndpointAccessType(res["accessType"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("psc_forwarding_rule", flattenNetworkConnectivityRegionalEndpointPscForwardingRule(res["pscForwardingRule"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("address", flattenNetworkConnectivityRegionalEndpointAddress(res["address"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("terraform_labels", flattenNetworkConnectivityRegionalEndpointTerraformLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + if err := d.Set("effective_labels", flattenNetworkConnectivityRegionalEndpointEffectiveLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionalEndpoint: %s", err) + } + + return nil +} + +func resourceNetworkConnectivityRegionalEndpointUpdate(d *schema.ResourceData, meta interface{}) error { + // Only the root field "labels" and "terraform_labels" are mutable + return resourceNetworkConnectivityRegionalEndpointRead(d, meta) +} + +func resourceNetworkConnectivityRegionalEndpointDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RegionalEndpoint: %s", err) + } + billingProject = project + + url, err := tpgresource.ReplaceVars(d, config, "{{NetworkConnectivityBasePath}}projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting RegionalEndpoint %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "RegionalEndpoint") + } + + err = NetworkConnectivityOperationWaitTime( + config, res, project, "Deleting RegionalEndpoint", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting RegionalEndpoint %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkConnectivityRegionalEndpointImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/locations/(?P[^/]+)/regionalEndpoints/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkConnectivityRegionalEndpointCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkConnectivityRegionalEndpointDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointTargetGoogleApi(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointAccessType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointPscForwardingRule(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointAddress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkConnectivityRegionalEndpointTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("terraform_labels"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + + return transformed +} + +func flattenNetworkConnectivityRegionalEndpointEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkConnectivityRegionalEndpointDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointTargetGoogleApi(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointAccessType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointAddress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkConnectivityRegionalEndpointEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_generated_test.go b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_generated_test.go new file mode 100644 index 0000000000..4deaefc4c3 --- /dev/null +++ b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_generated_test.go @@ -0,0 +1,174 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networkconnectivity_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func TestAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointRegionalAccessExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkConnectivityRegionalEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointRegionalAccessExample(context), + }, + { + ResourceName: "google_network_connectivity_regional_endpoint.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointRegionalAccessExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "my_network" { + name = "tf-test-my-network%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "tf-test-my-subnetwork%{random_suffix}" + ip_cidr_range = "192.168.0.0/24" + region = "us-central1" + network = google_compute_network.my_network.id +} + +resource "google_network_connectivity_regional_endpoint" "default" { + name = "tf-test-my-rep%{random_suffix}" + location = "us-central1" + target_google_api = "boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + access_type = "REGIONAL" + address = "192.168.0.5" + network = google_compute_network.my_network.id + subnetwork = google_compute_subnetwork.my_subnetwork.id + description = "My RegionalEndpoint targeting Google API boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + labels = {env = "default"} +} +`, context) +} + +func TestAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointGlobalAccessExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkConnectivityRegionalEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointGlobalAccessExample(context), + }, + { + ResourceName: "google_network_connectivity_regional_endpoint.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkConnectivityRegionalEndpoint_networkConnectivityRegionalEndpointGlobalAccessExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "my_network" { + name = "tf-test-my-network%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "tf-test-my-subnetwork%{random_suffix}" + ip_cidr_range = "192.168.0.0/24" + region = "us-central1" + network = google_compute_network.my_network.id +} + +resource "google_network_connectivity_regional_endpoint" "default" { + name = "tf-test-my-rep%{random_suffix}" + location = "us-central1" + target_google_api = "boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + access_type = "GLOBAL" + address = "192.168.0.4" + network = google_compute_network.my_network.id + subnetwork = google_compute_subnetwork.my_subnetwork.id +} +`, context) +} + +func testAccCheckNetworkConnectivityRegionalEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_connectivity_regional_endpoint" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkConnectivityBasePath}}projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkConnectivityRegionalEndpoint still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_sweeper.go b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_sweeper.go new file mode 100644 index 0000000000..ee8c07bdb7 --- /dev/null +++ b/google-beta/services/networkconnectivity/resource_network_connectivity_regional_endpoint_sweeper.go @@ -0,0 +1,139 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package networkconnectivity + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/sweeper" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func init() { + sweeper.AddTestSweepers("NetworkConnectivityRegionalEndpoint", testSweepNetworkConnectivityRegionalEndpoint) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkConnectivityRegionalEndpoint(region string) error { + resourceName := "NetworkConnectivityRegionalEndpoint" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/{{location}}/regionalEndpoints", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["regionalEndpoints"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/website/docs/r/network_connectivity_regional_endpoint.html.markdown b/website/docs/r/network_connectivity_regional_endpoint.html.markdown new file mode 100644 index 0000000000..c5bf520159 --- /dev/null +++ b/website/docs/r/network_connectivity_regional_endpoint.html.markdown @@ -0,0 +1,211 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Network Connectivity" +description: |- + Regional Private Service Connect (PSC) endpoint resource. +--- + +# google\_network\_connectivity\_regional\_endpoint + +Regional Private Service Connect (PSC) endpoint resource. + + +To get more information about RegionalEndpoint, see: + +* [API documentation](https://cloud.google.com/network-connectivity/docs/reference/networkconnectivity/rest/v1/projects.locations.regionalEndpoints) +* How-to Guides + * [Access regional Google APIs through endpoints](https://cloud.google.com/vpc/docs/access-regional-google-apis-endpoints) + + +## Example Usage - Network Connectivity Regional Endpoint Regional Access + + +```hcl +resource "google_compute_network" "my_network" { + name = "my-network" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "my-subnetwork" + ip_cidr_range = "192.168.0.0/24" + region = "us-central1" + network = google_compute_network.my_network.id +} + +resource "google_network_connectivity_regional_endpoint" "default" { + name = "my-rep" + location = "us-central1" + target_google_api = "boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + access_type = "REGIONAL" + address = "192.168.0.5" + network = google_compute_network.my_network.id + subnetwork = google_compute_subnetwork.my_subnetwork.id + description = "My RegionalEndpoint targeting Google API boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + labels = {env = "default"} +} +``` + +## Example Usage - Network Connectivity Regional Endpoint Global Access + + +```hcl +resource "google_compute_network" "my_network" { + name = "my-network" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "my-subnetwork" + ip_cidr_range = "192.168.0.0/24" + region = "us-central1" + network = google_compute_network.my_network.id +} + +resource "google_network_connectivity_regional_endpoint" "default" { + name = "my-rep" + location = "us-central1" + target_google_api = "boqcodelabjaimin-pa.us-central1.p.rep.googleapis.com" + access_type = "GLOBAL" + address = "192.168.0.4" + network = google_compute_network.my_network.id + subnetwork = google_compute_subnetwork.my_subnetwork.id +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `target_google_api` - + (Required) + The service endpoint this private regional endpoint connects to. Format: `{apiname}.{region}.p.rep.googleapis.com` Example: \"cloudkms.us-central1.p.rep.googleapis.com\". + +* `access_type` - + (Required) + The access type of this regional endpoint. This field is reflected in the PSC Forwarding Rule configuration to enable global access. + Possible values are: `GLOBAL`, `REGIONAL`. + +* `name` - + (Required) + The name of the RegionalEndpoint. + +* `location` - + (Required) + The location of the RegionalEndpoint. + + +- - - + + +* `labels` - + (Optional) + User-defined labels. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field `effective_labels` for all of the labels present on the resource. + +* `description` - + (Optional) + A description of this resource. + +* `network` - + (Optional) + The name of the VPC network for this private regional endpoint. Format: `projects/{project}/global/networks/{network}` + +* `subnetwork` - + (Optional) + The name of the subnetwork from which the IP address will be allocated. Format: `projects/{project}/regions/{region}/subnetworks/{subnetwork}` + +* `address` - + (Optional) + The IP Address of the Regional Endpoint. When no address is provided, an IP from the subnetwork is allocated. Use one of the following formats: * IPv4 address as in `10.0.0.1` * Address resource URI as in `projects/{project}/regions/{region}/addresses/{address_name}` + ~> **Note:** This field accepts both a reference to a Compute Address resource, which is the resource name of which format is given in the description, and IP literal value. If the user chooses to input a reserved address value; they need to make sure that the reserved address is in IPv4 version, its purpose is GCE_ENDPOINT, its type is INTERNAL and its status is RESERVED. If the user chooses to input an IP literal, they need to make sure that it's a valid IPv4 address (x.x.x.x) within the subnetwork. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}` + +* `create_time` - + Time when the RegionalEndpoint was created. + +* `update_time` - + Time when the RegionalEndpoint was updated. + +* `psc_forwarding_rule` - + The resource reference of the PSC Forwarding Rule created on behalf of the customer. Format: `//compute.googleapis.com/projects/{project}/regions/{region}/forwardingRules/{forwarding_rule_name}` + +* `terraform_labels` - + The combination of labels configured directly on the resource + and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +RegionalEndpoint can be imported using any of these accepted formats: + +* `projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}` +* `{{project}}/{{location}}/{{name}}` +* `{{location}}/{{name}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import RegionalEndpoint using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}}" + to = google_network_connectivity_regional_endpoint.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), RegionalEndpoint can be imported using one of the formats above. For example: + +``` +$ terraform import google_network_connectivity_regional_endpoint.default projects/{{project}}/locations/{{location}}/regionalEndpoints/{{name}} +$ terraform import google_network_connectivity_regional_endpoint.default {{project}}/{{location}}/{{name}} +$ terraform import google_network_connectivity_regional_endpoint.default {{location}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).