From 684739a9b19ba805800501acccdd2f49d82554ef Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Mon, 24 Apr 2023 20:46:41 +0000 Subject: [PATCH] Add configuration for Endpoint policy (#7751) Co-authored-by: Riley Karson Co-authored-by: Madhura Phadnis Signed-off-by: Modular Magician --- .changelog/7751.txt | 3 + google-beta/provider.go | 5 +- ...source_network_services_endpoint_policy.go | 785 ++++++++++++++++++ ...services_endpoint_policy_generated_test.go | 157 ++++ ...k_services_endpoint_policy_sweeper_test.go | 124 +++ ...e_network_services_endpoint_policy_test.go | 86 ++ ...ork_services_endpoint_policy.html.markdown | 216 +++++ 7 files changed, 1374 insertions(+), 2 deletions(-) create mode 100644 .changelog/7751.txt create mode 100644 google-beta/resource_network_services_endpoint_policy.go create mode 100644 google-beta/resource_network_services_endpoint_policy_generated_test.go create mode 100644 google-beta/resource_network_services_endpoint_policy_sweeper_test.go create mode 100644 google-beta/resource_network_services_endpoint_policy_test.go create mode 100644 website/docs/r/network_services_endpoint_policy.html.markdown diff --git a/.changelog/7751.txt b/.changelog/7751.txt new file mode 100644 index 0000000000..29d7f94ee0 --- /dev/null +++ b/.changelog/7751.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_networkservices_endpoint_policy` +``` diff --git a/google-beta/provider.go b/google-beta/provider.go index ccee1b4d58..9dee90cbe5 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -801,9 +801,9 @@ func Provider() *schema.Provider { return provider } -// Generated resources: 330 +// Generated resources: 331 // Generated IAM resources: 219 -// Total generated resources: 549 +// Total generated resources: 550 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -1239,6 +1239,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_network_services_edge_cache_keyset": ResourceNetworkServicesEdgeCacheKeyset(), "google_network_services_edge_cache_origin": ResourceNetworkServicesEdgeCacheOrigin(), "google_network_services_edge_cache_service": ResourceNetworkServicesEdgeCacheService(), + "google_network_services_endpoint_policy": ResourceNetworkServicesEndpointPolicy(), "google_network_services_gateway": ResourceNetworkServicesGateway(), "google_network_services_http_route": ResourceNetworkServicesHttpRoute(), "google_network_services_mesh": ResourceNetworkServicesMesh(), diff --git a/google-beta/resource_network_services_endpoint_policy.go b/google-beta/resource_network_services_endpoint_policy.go new file mode 100644 index 0000000000..7a3ecbf29a --- /dev/null +++ b/google-beta/resource_network_services_endpoint_policy.go @@ -0,0 +1,785 @@ +// ---------------------------------------------------------------------------- +// +// *** 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 google + +import ( + "fmt" + "log" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +func ResourceNetworkServicesEndpointPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkServicesEndpointPolicyCreate, + Read: resourceNetworkServicesEndpointPolicyRead, + Update: resourceNetworkServicesEndpointPolicyUpdate, + Delete: resourceNetworkServicesEndpointPolicyDelete, + + Importer: &schema.ResourceImporter{ + State: resourceNetworkServicesEndpointPolicyImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "endpoint_matcher": { + Type: schema.TypeList, + Required: true, + Description: `Required. A matcher that selects endpoints to which the policies should be applied.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metadata_label_matcher": { + Type: schema.TypeList, + Required: true, + Description: `The matcher is based on node metadata presented by xDS clients.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metadata_label_match_criteria": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateEnum([]string{"MATCH_ANY", "MATCH_ALL"}), + Description: `Specifies how matching should be done. Possible values: ["MATCH_ANY", "MATCH_ALL"]`, + }, + "metadata_labels": { + Type: schema.TypeList, + Optional: true, + Description: `The list of label value pairs that must match labels in the provided metadata based on filterMatchCriteria`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "label_name": { + Type: schema.TypeString, + Required: true, + Description: `Required. Label name presented as key in xDS Node Metadata.`, + }, + "label_value": { + Type: schema.TypeString, + Required: true, + Description: `Required. Label value presented as value corresponding to the above key, in xDS Node Metadata.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name of the EndpointPolicy resource.`, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateEnum([]string{"SIDECAR_PROXY", "GRPC_SERVER"}), + Description: `The type of endpoint policy. This is primarily used to validate the configuration. Possible values: ["SIDECAR_PROXY", "GRPC_SERVER"]`, + }, + "authorization_policy": { + Type: schema.TypeString, + Optional: true, + Description: `This field specifies the URL of AuthorizationPolicy resource that applies authorization policies to the inbound traffic at the matched endpoints.`, + }, + "client_tls_policy": { + Type: schema.TypeString, + Optional: true, + Description: `A URL referring to a ClientTlsPolicy resource. ClientTlsPolicy can be set to specify the authentication for traffic from the proxy to the actual endpoints.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A free-text description of the resource. Max length 1024 characters.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `Set of label tags associated with the TcpRoute resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "server_tls_policy": { + Type: schema.TypeString, + Optional: true, + Description: `A URL referring to ServerTlsPolicy resource. ServerTlsPolicy is used to determine the authentication policy to be applied to terminate the inbound traffic at the identified backends.`, + }, + "traffic_port_selector": { + Type: schema.TypeList, + Optional: true, + Description: `Port selector for the (matched) endpoints. If no port selector is provided, the matched config is applied to all ports.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ports": { + Type: schema.TypeList, + Required: true, + Description: `List of ports. Can be port numbers or port range (example, [80-90] specifies all ports from 80 to 90, including 80 and 90) or named ports or * to specify all ports. If the list is empty, all ports are selected.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the TcpRoute was created in UTC.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time the TcpRoute was updated in UTC.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceNetworkServicesEndpointPolicyCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := generateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + labelsProp, err := expandNetworkServicesEndpointPolicyLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + descriptionProp, err := expandNetworkServicesEndpointPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + authorizationPolicyProp, err := expandNetworkServicesEndpointPolicyAuthorizationPolicy(d.Get("authorization_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("authorization_policy"); !isEmptyValue(reflect.ValueOf(authorizationPolicyProp)) && (ok || !reflect.DeepEqual(v, authorizationPolicyProp)) { + obj["authorizationPolicy"] = authorizationPolicyProp + } + serverTlsPolicyProp, err := expandNetworkServicesEndpointPolicyServerTlsPolicy(d.Get("server_tls_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("server_tls_policy"); !isEmptyValue(reflect.ValueOf(serverTlsPolicyProp)) && (ok || !reflect.DeepEqual(v, serverTlsPolicyProp)) { + obj["serverTlsPolicy"] = serverTlsPolicyProp + } + clientTlsPolicyProp, err := expandNetworkServicesEndpointPolicyClientTlsPolicy(d.Get("client_tls_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("client_tls_policy"); !isEmptyValue(reflect.ValueOf(clientTlsPolicyProp)) && (ok || !reflect.DeepEqual(v, clientTlsPolicyProp)) { + obj["clientTlsPolicy"] = clientTlsPolicyProp + } + typeProp, err := expandNetworkServicesEndpointPolicyType(d.Get("type"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("type"); !isEmptyValue(reflect.ValueOf(typeProp)) && (ok || !reflect.DeepEqual(v, typeProp)) { + obj["type"] = typeProp + } + trafficPortSelectorProp, err := expandNetworkServicesEndpointPolicyTrafficPortSelector(d.Get("traffic_port_selector"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("traffic_port_selector"); !isEmptyValue(reflect.ValueOf(trafficPortSelectorProp)) && (ok || !reflect.DeepEqual(v, trafficPortSelectorProp)) { + obj["trafficPortSelector"] = trafficPortSelectorProp + } + endpointMatcherProp, err := expandNetworkServicesEndpointPolicyEndpointMatcher(d.Get("endpoint_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("endpoint_matcher"); !isEmptyValue(reflect.ValueOf(endpointMatcherProp)) && (ok || !reflect.DeepEqual(v, endpointMatcherProp)) { + obj["endpointMatcher"] = endpointMatcherProp + } + + url, err := ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/global/endpointPolicies?endpointPolicyId={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new EndpointPolicy: %#v", obj) + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for EndpointPolicy: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := SendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating EndpointPolicy: %s", err) + } + + // Store the ID now + id, err := ReplaceVars(d, config, "projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = NetworkServicesOperationWaitTime( + config, res, project, "Creating EndpointPolicy", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create EndpointPolicy: %s", err) + } + + log.Printf("[DEBUG] Finished creating EndpointPolicy %q: %#v", d.Id(), res) + + return resourceNetworkServicesEndpointPolicyRead(d, meta) +} + +func resourceNetworkServicesEndpointPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := generateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for EndpointPolicy: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := SendRequest(config, "GET", billingProject, url, userAgent, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("NetworkServicesEndpointPolicy %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + + if err := d.Set("create_time", flattenNetworkServicesEndpointPolicyCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("update_time", flattenNetworkServicesEndpointPolicyUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("labels", flattenNetworkServicesEndpointPolicyLabels(res["labels"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("description", flattenNetworkServicesEndpointPolicyDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("authorization_policy", flattenNetworkServicesEndpointPolicyAuthorizationPolicy(res["authorizationPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("server_tls_policy", flattenNetworkServicesEndpointPolicyServerTlsPolicy(res["serverTlsPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("client_tls_policy", flattenNetworkServicesEndpointPolicyClientTlsPolicy(res["clientTlsPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("type", flattenNetworkServicesEndpointPolicyType(res["type"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("traffic_port_selector", flattenNetworkServicesEndpointPolicyTrafficPortSelector(res["trafficPortSelector"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + if err := d.Set("endpoint_matcher", flattenNetworkServicesEndpointPolicyEndpointMatcher(res["endpointMatcher"], d, config)); err != nil { + return fmt.Errorf("Error reading EndpointPolicy: %s", err) + } + + return nil +} + +func resourceNetworkServicesEndpointPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := generateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for EndpointPolicy: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + labelsProp, err := expandNetworkServicesEndpointPolicyLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } + descriptionProp, err := expandNetworkServicesEndpointPolicyDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + authorizationPolicyProp, err := expandNetworkServicesEndpointPolicyAuthorizationPolicy(d.Get("authorization_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("authorization_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, authorizationPolicyProp)) { + obj["authorizationPolicy"] = authorizationPolicyProp + } + serverTlsPolicyProp, err := expandNetworkServicesEndpointPolicyServerTlsPolicy(d.Get("server_tls_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("server_tls_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serverTlsPolicyProp)) { + obj["serverTlsPolicy"] = serverTlsPolicyProp + } + clientTlsPolicyProp, err := expandNetworkServicesEndpointPolicyClientTlsPolicy(d.Get("client_tls_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("client_tls_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, clientTlsPolicyProp)) { + obj["clientTlsPolicy"] = clientTlsPolicyProp + } + typeProp, err := expandNetworkServicesEndpointPolicyType(d.Get("type"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("type"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, typeProp)) { + obj["type"] = typeProp + } + trafficPortSelectorProp, err := expandNetworkServicesEndpointPolicyTrafficPortSelector(d.Get("traffic_port_selector"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("traffic_port_selector"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, trafficPortSelectorProp)) { + obj["trafficPortSelector"] = trafficPortSelectorProp + } + endpointMatcherProp, err := expandNetworkServicesEndpointPolicyEndpointMatcher(d.Get("endpoint_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("endpoint_matcher"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, endpointMatcherProp)) { + obj["endpointMatcher"] = endpointMatcherProp + } + + url, err := ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating EndpointPolicy %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("labels") { + updateMask = append(updateMask, "labels") + } + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("authorization_policy") { + updateMask = append(updateMask, "authorizationPolicy") + } + + if d.HasChange("server_tls_policy") { + updateMask = append(updateMask, "serverTlsPolicy") + } + + if d.HasChange("client_tls_policy") { + updateMask = append(updateMask, "clientTlsPolicy") + } + + if d.HasChange("type") { + updateMask = append(updateMask, "type") + } + + if d.HasChange("traffic_port_selector") { + updateMask = append(updateMask, "trafficPortSelector") + } + + if d.HasChange("endpoint_matcher") { + updateMask = append(updateMask, "endpointMatcher") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := SendRequestWithTimeout(config, "PATCH", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating EndpointPolicy %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating EndpointPolicy %q: %#v", d.Id(), res) + } + + err = NetworkServicesOperationWaitTime( + config, res, project, "Updating EndpointPolicy", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceNetworkServicesEndpointPolicyRead(d, meta) +} + +func resourceNetworkServicesEndpointPolicyDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := generateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := getProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for EndpointPolicy: %s", err) + } + billingProject = project + + url, err := ReplaceVars(d, config, "{{NetworkServicesBasePath}}projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting EndpointPolicy %q", d.Id()) + + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := SendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "EndpointPolicy") + } + + err = NetworkServicesOperationWaitTime( + config, res, project, "Deleting EndpointPolicy", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting EndpointPolicy %q: %#v", d.Id(), res) + return nil +} + +func resourceNetworkServicesEndpointPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := ParseImportId([]string{ + "projects/(?P[^/]+)/locations/global/endpointPolicies/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := ReplaceVars(d, config, "projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNetworkServicesEndpointPolicyCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyAuthorizationPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyServerTlsPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyClientTlsPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyTrafficPortSelector(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["ports"] = + flattenNetworkServicesEndpointPolicyTrafficPortSelectorPorts(original["ports"], d, config) + return []interface{}{transformed} +} +func flattenNetworkServicesEndpointPolicyTrafficPortSelectorPorts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyEndpointMatcher(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["metadata_label_matcher"] = + flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcher(original["metadataLabelMatcher"], d, config) + return []interface{}{transformed} +} +func flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcher(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["metadata_label_match_criteria"] = + flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelMatchCriteria(original["metadataLabelMatchCriteria"], d, config) + transformed["metadata_labels"] = + flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabels(original["metadataLabels"], d, config) + return []interface{}{transformed} +} +func flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelMatchCriteria(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "label_name": flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelName(original["labelName"], d, config), + "label_value": flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelValue(original["labelValue"], d, config), + }) + } + return transformed +} +func flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelValue(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNetworkServicesEndpointPolicyLabels(v interface{}, d 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 +} + +func expandNetworkServicesEndpointPolicyDescription(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyAuthorizationPolicy(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyServerTlsPolicy(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyClientTlsPolicy(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyType(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyTrafficPortSelector(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedPorts, err := expandNetworkServicesEndpointPolicyTrafficPortSelectorPorts(original["ports"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPorts); val.IsValid() && !isEmptyValue(val) { + transformed["ports"] = transformedPorts + } + + return transformed, nil +} + +func expandNetworkServicesEndpointPolicyTrafficPortSelectorPorts(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcher(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMetadataLabelMatcher, err := expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcher(original["metadata_label_matcher"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMetadataLabelMatcher); val.IsValid() && !isEmptyValue(val) { + transformed["metadataLabelMatcher"] = transformedMetadataLabelMatcher + } + + return transformed, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcher(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMetadataLabelMatchCriteria, err := expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelMatchCriteria(original["metadata_label_match_criteria"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMetadataLabelMatchCriteria); val.IsValid() && !isEmptyValue(val) { + transformed["metadataLabelMatchCriteria"] = transformedMetadataLabelMatchCriteria + } + + transformedMetadataLabels, err := expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabels(original["metadata_labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMetadataLabels); val.IsValid() && !isEmptyValue(val) { + transformed["metadataLabels"] = transformedMetadataLabels + } + + return transformed, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelMatchCriteria(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabels(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedLabelName, err := expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelName(original["label_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabelName); val.IsValid() && !isEmptyValue(val) { + transformed["labelName"] = transformedLabelName + } + + transformedLabelValue, err := expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelValue(original["label_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabelValue); val.IsValid() && !isEmptyValue(val) { + transformed["labelValue"] = transformedLabelValue + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelName(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetworkServicesEndpointPolicyEndpointMatcherMetadataLabelMatcherMetadataLabelsLabelValue(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google-beta/resource_network_services_endpoint_policy_generated_test.go b/google-beta/resource_network_services_endpoint_policy_generated_test.go new file mode 100644 index 0000000000..94d1e3dda2 --- /dev/null +++ b/google-beta/resource_network_services_endpoint_policy_generated_test.go @@ -0,0 +1,157 @@ +// ---------------------------------------------------------------------------- +// +// *** 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 google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyBasicExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": RandString(t, 10), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkServicesEndpointPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyBasicExample(context), + }, + { + ResourceName: "google_network_services_endpoint_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name"}, + }, + }, + }) +} + +func testAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyBasicExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_network_services_endpoint_policy" "default" { + provider = google-beta + name = "tf-test-my-endpoint-policy%{random_suffix}" + labels = { + foo = "bar" + } + description = "my description" + type = "SIDECAR_PROXY" + traffic_port_selector { + ports = ["8081"] + } + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ANY" + metadata_labels { + label_name = "foo" + label_value = "bar" + } + } + } +} + +`, context) +} + +func TestAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyEmptyMatchExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": RandString(t, 10), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkServicesEndpointPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyEmptyMatchExample(context), + }, + { + ResourceName: "google_network_services_endpoint_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name"}, + }, + }, + }) +} + +func testAccNetworkServicesEndpointPolicy_networkServicesEndpointPolicyEmptyMatchExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_network_services_endpoint_policy" "default" { + provider = google-beta + name = "tf-test-my-endpoint-policy%{random_suffix}" + labels = { + foo = "bar" + } + description = "my description" + type = "SIDECAR_PROXY" + traffic_port_selector { + ports = ["8081"] + } + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ANY" + } + } +} + +`, context) +} + +func testAccCheckNetworkServicesEndpointPolicyDestroyProducer(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_services_endpoint_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := GoogleProviderConfig(t) + + url, err := replaceVarsForTest(config, rs, "{{NetworkServicesBasePath}}projects/{{project}}/locations/global/endpointPolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = SendRequest(config, "GET", billingProject, url, config.UserAgent, nil) + if err == nil { + return fmt.Errorf("NetworkServicesEndpointPolicy still exists at %s", url) + } + } + + return nil + } +} diff --git a/google-beta/resource_network_services_endpoint_policy_sweeper_test.go b/google-beta/resource_network_services_endpoint_policy_sweeper_test.go new file mode 100644 index 0000000000..af9ef92cea --- /dev/null +++ b/google-beta/resource_network_services_endpoint_policy_sweeper_test.go @@ -0,0 +1,124 @@ +// ---------------------------------------------------------------------------- +// +// *** 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 google + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func init() { + resource.AddTestSweepers("NetworkServicesEndpointPolicy", &resource.Sweeper{ + Name: "NetworkServicesEndpointPolicy", + F: testSweepNetworkServicesEndpointPolicy, + }) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkServicesEndpointPolicy(region string) error { + resourceName := "NetworkServicesEndpointPolicy" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := 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 := GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://networkservices.googleapis.com/v1/projects/{{project}}/locations/global/endpointPolicies", "?")[0] + listUrl, err := ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := SendRequest(config, "GET", config.Project, listUrl, config.UserAgent, nil) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["endpointPolicies"] + 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 := GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://networkservices.googleapis.com/v1/projects/{{project}}/locations/global/endpointPolicies/{{name}}" + deleteUrl, err := 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 = SendRequest(config, "DELETE", config.Project, deleteUrl, config.UserAgent, nil) + 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/google-beta/resource_network_services_endpoint_policy_test.go b/google-beta/resource_network_services_endpoint_policy_test.go new file mode 100644 index 0000000000..56d6fabcf0 --- /dev/null +++ b/google-beta/resource_network_services_endpoint_policy_test.go @@ -0,0 +1,86 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccNetworkServicesEndpointPolicy_update(t *testing.T) { + t.Parallel() + + endpointPolicyName := fmt.Sprintf("tf-test-endpoint-policy-%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkServicesEndpointPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesEndpointPolicy_basic(endpointPolicyName), + }, + { + ResourceName: "google_network_services_endpoint_policy.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNetworkServicesEndpointPolicy_update(endpointPolicyName), + }, + { + ResourceName: "google_network_services_endpoint_policy.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNetworkServicesEndpointPolicy_basic(endpointPolicyName string) string { + return fmt.Sprintf(` +resource "google_network_services_endpoint_policy" "foobar" { + name = "%s" + labels = { + foo = "bar" + } + description = "my description" + type = "SIDECAR_PROXY" + traffic_port_selector { + ports = ["8081"] + } + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ANY" + metadata_labels { + label_name = "foo" + label_value = "bar" + } + } + } +} +`, endpointPolicyName) +} + +func testAccNetworkServicesEndpointPolicy_update(endpointPolicyName string) string { + return fmt.Sprintf(` +resource "google_network_services_endpoint_policy" "foobar" { + name = "%s" + labels = { + foo = "barbar" + baz = "qux" + } + description = "update description" + type = "GRPC_SERVER" + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ALL" + metadata_labels { + label_name = "baz" + label_value = "bux" + } + } + } +} +`, endpointPolicyName) +} diff --git a/website/docs/r/network_services_endpoint_policy.html.markdown b/website/docs/r/network_services_endpoint_policy.html.markdown new file mode 100644 index 0000000000..fc2ee65920 --- /dev/null +++ b/website/docs/r/network_services_endpoint_policy.html.markdown @@ -0,0 +1,216 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** 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 services" +description: |- + EndpointPolicy is a resource that helps apply desired configuration on the endpoints that match specific criteria. +--- + +# google\_network\_services\_endpoint\_policy + +EndpointPolicy is a resource that helps apply desired configuration on the endpoints that match specific criteria. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + +To get more information about EndpointPolicy, see: + +* [API documentation](https://cloud.google.com/traffic-director/docs/reference/network-services/rest/v1beta1/projects.locations.endpointPolicies) + + +## Example Usage - Network Services Endpoint Policy Basic + + +```hcl +resource "google_network_services_endpoint_policy" "default" { + provider = google-beta + name = "my-endpoint-policy" + labels = { + foo = "bar" + } + description = "my description" + type = "SIDECAR_PROXY" + traffic_port_selector { + ports = ["8081"] + } + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ANY" + metadata_labels { + label_name = "foo" + label_value = "bar" + } + } + } +} + +``` + +## Example Usage - Network Services Endpoint Policy Empty Match + + +```hcl +resource "google_network_services_endpoint_policy" "default" { + provider = google-beta + name = "my-endpoint-policy" + labels = { + foo = "bar" + } + description = "my description" + type = "SIDECAR_PROXY" + traffic_port_selector { + ports = ["8081"] + } + endpoint_matcher { + metadata_label_matcher { + metadata_label_match_criteria = "MATCH_ANY" + } + } +} + +``` + +## Argument Reference + +The following arguments are supported: + + +* `type` - + (Required) + The type of endpoint policy. This is primarily used to validate the configuration. + Possible values are: `SIDECAR_PROXY`, `GRPC_SERVER`. + +* `endpoint_matcher` - + (Required) + Required. A matcher that selects endpoints to which the policies should be applied. + Structure is [documented below](#nested_endpoint_matcher). + +* `name` - + (Required) + Name of the EndpointPolicy resource. + + +The `endpoint_matcher` block supports: + +* `metadata_label_matcher` - + (Required) + The matcher is based on node metadata presented by xDS clients. + Structure is [documented below](#nested_metadata_label_matcher). + + +The `metadata_label_matcher` block supports: + +* `metadata_label_match_criteria` - + (Required) + Specifies how matching should be done. + Possible values are: `MATCH_ANY`, `MATCH_ALL`. + +* `metadata_labels` - + (Optional) + The list of label value pairs that must match labels in the provided metadata based on filterMatchCriteria + Structure is [documented below](#nested_metadata_labels). + + +The `metadata_labels` block supports: + +* `label_name` - + (Required) + Required. Label name presented as key in xDS Node Metadata. + +* `label_value` - + (Required) + Required. Label value presented as value corresponding to the above key, in xDS Node Metadata. + +- - - + + +* `labels` - + (Optional) + Set of label tags associated with the TcpRoute resource. + +* `description` - + (Optional) + A free-text description of the resource. Max length 1024 characters. + +* `authorization_policy` - + (Optional) + This field specifies the URL of AuthorizationPolicy resource that applies authorization policies to the inbound traffic at the matched endpoints. + +* `server_tls_policy` - + (Optional) + A URL referring to ServerTlsPolicy resource. ServerTlsPolicy is used to determine the authentication policy to be applied to terminate the inbound traffic at the identified backends. + +* `client_tls_policy` - + (Optional) + A URL referring to a ClientTlsPolicy resource. ClientTlsPolicy can be set to specify the authentication for traffic from the proxy to the actual endpoints. + +* `traffic_port_selector` - + (Optional) + Port selector for the (matched) endpoints. If no port selector is provided, the matched config is applied to all ports. + Structure is [documented below](#nested_traffic_port_selector). + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `traffic_port_selector` block supports: + +* `ports` - + (Required) + List of ports. Can be port numbers or port range (example, [80-90] specifies all ports from 80 to 90, including 80 and 90) or named ports or * to specify all ports. If the list is empty, all ports are selected. + +## 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/global/endpointPolicies/{{name}}` + +* `create_time` - + Time the TcpRoute was created in UTC. + +* `update_time` - + Time the TcpRoute was updated in UTC. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 30 minutes. +- `update` - Default is 30 minutes. +- `delete` - Default is 30 minutes. + +## Import + + +EndpointPolicy can be imported using any of these accepted formats: + +``` +$ terraform import google_network_services_endpoint_policy.default projects/{{project}}/locations/global/endpointPolicies/{{name}} +$ terraform import google_network_services_endpoint_policy.default {{project}}/{{name}} +$ terraform import google_network_services_endpoint_policy.default {{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).