From f1148b031e15684547a7a0046bb435ae15e1f091 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 24 Jun 2024 08:11:46 -0500 Subject: [PATCH] description-copy update and overall refresh --- GNUmakefile | 2 +- mmv1/description-copy.go | 31 +- mmv1/main.go | 4 +- mmv1/products/compute/Address.yaml | 1 - mmv1/products/compute/BackendService.yaml | 2 - mmv1/products/compute/ForwardingRule.yaml | 3 - .../compute/GlobalForwardingRule.yaml | 3 - mmv1/products/compute/HttpHealthCheck.yaml | 1 - mmv1/products/compute/HttpsHealthCheck.yaml | 1 - .../compute/ManagedSslCertificate.yaml | 1 - .../compute/RegionBackendService.yaml | 2 - .../compute/RegionSslCertificate.yaml | 1 - mmv1/products/compute/SslCertificate.yaml | 1 - mmv1/products/compute/go_Address.yaml | 1 - mmv1/products/compute/go_BackendService.yaml | 2 - mmv1/products/compute/go_Firewall.yaml | 6 +- mmv1/products/compute/go_ForwardingRule.yaml | 3 - .../compute/go_GlobalForwardingRule.yaml | 3 - mmv1/products/compute/go_HttpHealthCheck.yaml | 1 - .../products/compute/go_HttpsHealthCheck.yaml | 1 - .../compute/go_ManagedSslCertificate.yaml | 25 +- .../compute/go_RegionBackendService.yaml | 2 - .../compute/go_RegionSslCertificate.yaml | 7 +- mmv1/products/compute/go_Route.yaml | 10 +- mmv1/products/compute/go_RouterNat.yaml | 14 +- .../compute/go_ServiceAttachment.yaml | 2 +- mmv1/products/compute/go_SslCertificate.yaml | 7 +- .../products/compute/go_TargetHttpsProxy.yaml | 12 + mmv1/products/compute/go_UrlMap.yaml | 178 ++ mmv1/products/compute/go_VpnGateway.yaml | 6 +- mmv1/products/pubsub/go_Subscription.yaml | 37 +- ...r_serviceperimeters_custom_flatten.go.tmpl | 811 +++++++ ...l_map_custom_error_response_policy.tf.tmpl | 86 + ..._featureonlinestore_with_optimized.tf.tmpl | 21 + .../go/firebasehosting_site.go.tmpl | 27 + mmv1/templates/terraform/yaml_conversion.erb | 8 +- mmv1/third_party/terraform/go/go.mod | 2 +- .../go/resource_compute_instance.go.tmpl | 47 +- .../go/resource_compute_instance_test.go.tmpl | 143 ++ ...ce_compute_target_https_proxy_test.go.tmpl | 1 + .../go/resource_compute_url_map_test.go.tmpl | 1912 +++++++++++++++++ ...esource_firebase_hosting_site_test.go.tmpl | 46 + 42 files changed, 3379 insertions(+), 95 deletions(-) create mode 100644 mmv1/templates/terraform/custom_flatten/go/accesscontextmanager_serviceperimeters_custom_flatten.go.tmpl create mode 100644 mmv1/templates/terraform/examples/go/url_map_custom_error_response_policy.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/go/vertex_ai_featureonlinestore_with_optimized.tf.tmpl create mode 100644 mmv1/templates/terraform/pre_create/go/firebasehosting_site.go.tmpl create mode 100644 mmv1/third_party/terraform/services/compute/go/resource_compute_url_map_test.go.tmpl diff --git a/GNUmakefile b/GNUmakefile index e4e63fe494a8..a462c011415e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -137,5 +137,5 @@ doctor: refresh-go: cd mmv1;\ bundle exec compiler.rb -e terraform -o $(OUTPUT_PATH) -v $(VERSION) $(mmv1_compile) --go-yaml; \ - go run . --yaml --template + go run . --yaml --template; \ go run . --yaml --handwritten \ No newline at end of file diff --git a/mmv1/description-copy.go b/mmv1/description-copy.go index 6e5a97657eba..0294174e95c8 100644 --- a/mmv1/description-copy.go +++ b/mmv1/description-copy.go @@ -10,8 +10,24 @@ import ( "strings" ) +func CopyAllDescriptions() { + identifiers := []string{ + "description:", + "note:", + "set_hash_func:", + "warning:", + "required_properties:", + "optional_properties:", + "attributes:", + } + + for i, id := range identifiers { + CopyText(id, len(identifiers)-1 == i) + } +} + // Used to copy/paste text from Ruby -> Go YAML files -func CopyText(identifier string) { +func CopyText(identifier string, last bool) { var allProductFiles []string = make([]string, 0) files, err := filepath.Glob("products/**/go_product.yaml") if err != nil { @@ -92,16 +108,11 @@ func CopyText(identifier string) { for scanner.Scan() { line := scanner.Text() if firstLine { - if line == "NOT CONVERTED - RUN YAML MODE" { - firstLine = false - w.WriteString(fmt.Sprintf("%s\n", "NOT CONVERTED #2 - RUN YAML MODE")) - continue - } else if line == "NOT CONVERTED #2 - RUN YAML MODE" { - firstLine = false - w.WriteString(fmt.Sprintf("%s\n", "NOT CONVERTED #3 - RUN YAML MODE")) - continue - } else if line == "NOT CONVERTED #3 - RUN YAML MODE" { + if strings.Contains(line, "NOT CONVERTED - RUN YAML MODE") { firstLine = false + if !last { + w.WriteString(fmt.Sprintf("NOT CONVERTED - RUN YAML MODE\n")) + } continue } else { break diff --git a/mmv1/main.go b/mmv1/main.go index 7235b1324b9c..851f05737390 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -41,9 +41,7 @@ func main() { flag.Parse() if *yamlMode { - CopyText("description:") - CopyText("note:") - CopyText("set_hash_func:") + CopyAllDescriptions() } if *templateMode { diff --git a/mmv1/products/compute/Address.yaml b/mmv1/products/compute/Address.yaml index e137f2286548..de0f0398c124 100644 --- a/mmv1/products/compute/Address.yaml +++ b/mmv1/products/compute/Address.yaml @@ -165,7 +165,6 @@ properties: configure Private Service Connect. Only global internal addresses can use this purpose. - This should only be set when using an Internal address. default_from_api: true - !ruby/object:Api::Type::Enum diff --git a/mmv1/products/compute/BackendService.yaml b/mmv1/products/compute/BackendService.yaml index 150fa6c33361..5a7539e956ad 100644 --- a/mmv1/products/compute/BackendService.yaml +++ b/mmv1/products/compute/BackendService.yaml @@ -834,7 +834,6 @@ properties: UNAVAILABLE_WEIGHT. Otherwise, Load Balancing remains equal-weight. - This field is applicable to either: * A regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, @@ -844,7 +843,6 @@ properties: Load Balancing). Only MAGLEV and WEIGHTED_MAGLEV values are possible for External Network Load Balancing. The default is MAGLEV. - If session_affinity is not NONE, and this field is not set to MAGLEV, WEIGHTED_MAGLEV, or RING_HASH, session affinity settings will not take effect. diff --git a/mmv1/products/compute/ForwardingRule.yaml b/mmv1/products/compute/ForwardingRule.yaml index e2cfde7e7d5d..4e6f3b6655ab 100644 --- a/mmv1/products/compute/ForwardingRule.yaml +++ b/mmv1/products/compute/ForwardingRule.yaml @@ -286,7 +286,6 @@ properties: * When the `target` is a Private Service Connect Google APIs bundle, you must specify an `IPAddress`. - Otherwise, you can optionally specify an IP address that references an existing static (reserved) IP address resource. When omitted, Google Cloud assigns an ephemeral IP address. @@ -304,7 +303,6 @@ properties: * `global/addresses/address-name` * `address-name` - The forwarding rule's `target` or `backendService`, and in most cases, also the `loadBalancingScheme`, determine the type of IP address that you can use. For detailed information, see @@ -494,7 +492,6 @@ properties: * `vpc-sc` - [ APIs that support VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/supported-products). * `all-apis` - [All supported Google APIs](https://cloud.google.com/vpc/docs/private-service-connect#supported-apis). - For Private Service Connect forwarding rules that forward traffic to managed services, the target must be a service attachment. update_verb: :POST update_url: 'projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}/setTarget' diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index b287c5445545..af9a88d4d512 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -238,7 +238,6 @@ properties: * When the `target` is a Private Service Connect Google APIs bundle, you must specify an `IPAddress`. - Otherwise, you can optionally specify an IP address that references an existing static (reserved) IP address resource. When omitted, Google Cloud assigns an ephemeral IP address. @@ -256,7 +255,6 @@ properties: * `global/addresses/address-name` * `address-name` - The forwarding rule's `target`, and in most cases, also the `loadBalancingScheme`, determine the type of IP address that you can use. For detailed information, see @@ -479,7 +477,6 @@ properties: * `vpc-sc` - [ APIs that support VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/supported-products). * `all-apis` - [All supported Google APIs](https://cloud.google.com/vpc/docs/private-service-connect#supported-apis). - For Private Service Connect forwarding rules that forward traffic to managed services, the target must be a service attachment. update_verb: :POST update_url: 'projects/{{project}}/global/forwardingRules/{{name}}/setTarget' diff --git a/mmv1/products/compute/HttpHealthCheck.yaml b/mmv1/products/compute/HttpHealthCheck.yaml index a49f63feb4bc..e826da96bf2b 100644 --- a/mmv1/products/compute/HttpHealthCheck.yaml +++ b/mmv1/products/compute/HttpHealthCheck.yaml @@ -21,7 +21,6 @@ description: | An HttpHealthCheck resource. This resource defines a template for how individual VMs should be checked for health, via HTTP. - ~> **Note:** google_compute_http_health_check is a legacy health check. The newer [google_compute_health_check](/docs/providers/google/r/compute_health_check.html) should be preferred for all uses except diff --git a/mmv1/products/compute/HttpsHealthCheck.yaml b/mmv1/products/compute/HttpsHealthCheck.yaml index c8ca925f0989..aeb352b1f5f8 100644 --- a/mmv1/products/compute/HttpsHealthCheck.yaml +++ b/mmv1/products/compute/HttpsHealthCheck.yaml @@ -21,7 +21,6 @@ description: | An HttpsHealthCheck resource. This resource defines a template for how individual VMs should be checked for health, via HTTPS. - ~> **Note:** google_compute_https_health_check is a legacy health check. The newer [google_compute_health_check](/docs/providers/google/r/compute_health_check.html) should be preferred for all uses except diff --git a/mmv1/products/compute/ManagedSslCertificate.yaml b/mmv1/products/compute/ManagedSslCertificate.yaml index 106e07944520..1975c56387a5 100644 --- a/mmv1/products/compute/ManagedSslCertificate.yaml +++ b/mmv1/products/compute/ManagedSslCertificate.yaml @@ -117,7 +117,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. - !ruby/object:Api::Type::NestedObject name: 'managed' diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 4cb367ee521d..9b62faaad6f8 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -842,7 +842,6 @@ properties: UNAVAILABLE_WEIGHT. Otherwise, Load Balancing remains equal-weight. - This field is applicable to either: * A regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, @@ -852,7 +851,6 @@ properties: Load Balancing). Only MAGLEV and WEIGHTED_MAGLEV values are possible for External Network Load Balancing. The default is MAGLEV. - If session_affinity is not NONE, and this field is not set to MAGLEV, WEIGHTED_MAGLEV, or RING_HASH, session affinity settings will not take effect. diff --git a/mmv1/products/compute/RegionSslCertificate.yaml b/mmv1/products/compute/RegionSslCertificate.yaml index fc3e6c825658..ba2941812207 100644 --- a/mmv1/products/compute/RegionSslCertificate.yaml +++ b/mmv1/products/compute/RegionSslCertificate.yaml @@ -128,7 +128,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. default_from_api: true custom_expand: 'templates/terraform/custom_expand/name_or_name_prefix.go.erb' diff --git a/mmv1/products/compute/SslCertificate.yaml b/mmv1/products/compute/SslCertificate.yaml index 0329f36edfb4..f00bbfe1d91c 100644 --- a/mmv1/products/compute/SslCertificate.yaml +++ b/mmv1/products/compute/SslCertificate.yaml @@ -115,7 +115,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. default_from_api: true custom_expand: 'templates/terraform/custom_expand/name_or_name_prefix.go.erb' diff --git a/mmv1/products/compute/go_Address.yaml b/mmv1/products/compute/go_Address.yaml index a44d0393d9b2..beca1b1ebe45 100644 --- a/mmv1/products/compute/go_Address.yaml +++ b/mmv1/products/compute/go_Address.yaml @@ -158,7 +158,6 @@ properties: configure Private Service Connect. Only global internal addresses can use this purpose. - This should only be set when using an Internal address. default_from_api: true - name: 'networkTier' diff --git a/mmv1/products/compute/go_BackendService.yaml b/mmv1/products/compute/go_BackendService.yaml index 90a748f145cd..c13d11c4ee35 100644 --- a/mmv1/products/compute/go_BackendService.yaml +++ b/mmv1/products/compute/go_BackendService.yaml @@ -820,7 +820,6 @@ properties: UNAVAILABLE_WEIGHT. Otherwise, Load Balancing remains equal-weight. - This field is applicable to either: * A regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, @@ -830,7 +829,6 @@ properties: Load Balancing). Only MAGLEV and WEIGHTED_MAGLEV values are possible for External Network Load Balancing. The default is MAGLEV. - If session_affinity is not NONE, and this field is not set to MAGLEV, WEIGHTED_MAGLEV, or RING_HASH, session affinity settings will not take effect. diff --git a/mmv1/products/compute/go_Firewall.yaml b/mmv1/products/compute/go_Firewall.yaml index d67f8e1166ab..c28d906a27b9 100644 --- a/mmv1/products/compute/go_Firewall.yaml +++ b/mmv1/products/compute/go_Firewall.yaml @@ -33,9 +33,9 @@ references: 'Official Documentation': 'https://cloud.google.com/vpc/docs/firewalls' api: 'https://cloud.google.com/compute/docs/reference/v1/firewalls' docs: - optional_properties: '* `enable_logging` - (Optional, Deprecated) This field denotes whether to enable logging for a particular firewall rule. -If logging is enabled, logs will be exported to Stackdriver. Deprecated in favor of `log_config` -' + optional_properties: | + * `enable_logging` - (Optional, Deprecated) This field denotes whether to enable logging for a particular firewall rule. + If logging is enabled, logs will be exported to Stackdriver. Deprecated in favor of `log_config` base_url: 'projects/{{project}}/global/firewalls' has_self_link: true update_verb: 'PATCH' diff --git a/mmv1/products/compute/go_ForwardingRule.yaml b/mmv1/products/compute/go_ForwardingRule.yaml index 93399233a2fe..2b84b92a45a4 100644 --- a/mmv1/products/compute/go_ForwardingRule.yaml +++ b/mmv1/products/compute/go_ForwardingRule.yaml @@ -273,7 +273,6 @@ properties: * When the `target` is a Private Service Connect Google APIs bundle, you must specify an `IPAddress`. - Otherwise, you can optionally specify an IP address that references an existing static (reserved) IP address resource. When omitted, Google Cloud assigns an ephemeral IP address. @@ -291,7 +290,6 @@ properties: * `global/addresses/address-name` * `address-name` - The forwarding rule's `target` or `backendService`, and in most cases, also the `loadBalancingScheme`, determine the type of IP address that you can use. For detailed information, see @@ -476,7 +474,6 @@ properties: * `vpc-sc` - [ APIs that support VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/supported-products). * `all-apis` - [All supported Google APIs](https://cloud.google.com/vpc/docs/private-service-connect#supported-apis). - For Private Service Connect forwarding rules that forward traffic to managed services, the target must be a service attachment. update_url: 'projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}/setTarget' update_verb: 'POST' diff --git a/mmv1/products/compute/go_GlobalForwardingRule.yaml b/mmv1/products/compute/go_GlobalForwardingRule.yaml index 77c4f47f2e7a..c85cfd9c7525 100644 --- a/mmv1/products/compute/go_GlobalForwardingRule.yaml +++ b/mmv1/products/compute/go_GlobalForwardingRule.yaml @@ -229,7 +229,6 @@ properties: * When the `target` is a Private Service Connect Google APIs bundle, you must specify an `IPAddress`. - Otherwise, you can optionally specify an IP address that references an existing static (reserved) IP address resource. When omitted, Google Cloud assigns an ephemeral IP address. @@ -247,7 +246,6 @@ properties: * `global/addresses/address-name` * `address-name` - The forwarding rule's `target`, and in most cases, also the `loadBalancingScheme`, determine the type of IP address that you can use. For detailed information, see @@ -467,7 +465,6 @@ properties: * `vpc-sc` - [ APIs that support VPC Service Controls](https://cloud.google.com/vpc-service-controls/docs/supported-products). * `all-apis` - [All supported Google APIs](https://cloud.google.com/vpc/docs/private-service-connect#supported-apis). - For Private Service Connect forwarding rules that forward traffic to managed services, the target must be a service attachment. required: true update_url: 'projects/{{project}}/global/forwardingRules/{{name}}/setTarget' diff --git a/mmv1/products/compute/go_HttpHealthCheck.yaml b/mmv1/products/compute/go_HttpHealthCheck.yaml index f24acd5ea12c..dca967b94c9c 100644 --- a/mmv1/products/compute/go_HttpHealthCheck.yaml +++ b/mmv1/products/compute/go_HttpHealthCheck.yaml @@ -19,7 +19,6 @@ description: | An HttpHealthCheck resource. This resource defines a template for how individual VMs should be checked for health, via HTTP. - ~> **Note:** google_compute_http_health_check is a legacy health check. The newer [google_compute_health_check](/docs/providers/google/r/compute_health_check.html) should be preferred for all uses except diff --git a/mmv1/products/compute/go_HttpsHealthCheck.yaml b/mmv1/products/compute/go_HttpsHealthCheck.yaml index f08af7f264dd..a186293003ad 100644 --- a/mmv1/products/compute/go_HttpsHealthCheck.yaml +++ b/mmv1/products/compute/go_HttpsHealthCheck.yaml @@ -19,7 +19,6 @@ description: | An HttpsHealthCheck resource. This resource defines a template for how individual VMs should be checked for health, via HTTPS. - ~> **Note:** google_compute_https_health_check is a legacy health check. The newer [google_compute_health_check](/docs/providers/google/r/compute_health_check.html) should be preferred for all uses except diff --git a/mmv1/products/compute/go_ManagedSslCertificate.yaml b/mmv1/products/compute/go_ManagedSslCertificate.yaml index 2dd937bc54e6..5f1f840af51f 100644 --- a/mmv1/products/compute/go_ManagedSslCertificate.yaml +++ b/mmv1/products/compute/go_ManagedSslCertificate.yaml @@ -27,19 +27,19 @@ references: 'Official Documentation': 'https://cloud.google.com/load-balancing/docs/ssl-certificates' api: 'https://cloud.google.com/compute/docs/reference/rest/v1/sslCertificates' docs: - warning: 'This resource should be used with extreme caution! Provisioning an SSL -certificate is complex. Ensure that you understand the lifecycle of a -certificate before attempting complex tasks like cert rotation automatically. -This resource will "return" as soon as the certificate object is created, -but post-creation the certificate object will go through a "provisioning" -process. The provisioning process can complete only when the domain name -for which the certificate is created points to a target pool which, itself, -points at the certificate. Depending on your DNS provider, this may take -some time, and migrating from self-managed certificates to Google-managed -certificates may entail some downtime while the certificate provisions. + warning: | + This resource should be used with extreme caution! Provisioning an SSL + certificate is complex. Ensure that you understand the lifecycle of a + certificate before attempting complex tasks like cert rotation automatically. + This resource will "return" as soon as the certificate object is created, + but post-creation the certificate object will go through a "provisioning" + process. The provisioning process can complete only when the domain name + for which the certificate is created points to a target pool which, itself, + points at the certificate. Depending on your DNS provider, this may take + some time, and migrating from self-managed certificates to Google-managed + certificates may entail some downtime while the certificate provisions. -In conclusion: Be extremely cautious. -' + In conclusion: Be extremely cautious. base_url: 'projects/{{project}}/global/sslCertificates' has_self_link: true immutable: true @@ -107,7 +107,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. - name: 'managed' type: NestedObject diff --git a/mmv1/products/compute/go_RegionBackendService.yaml b/mmv1/products/compute/go_RegionBackendService.yaml index 13700c4f64c0..cab122136a1b 100644 --- a/mmv1/products/compute/go_RegionBackendService.yaml +++ b/mmv1/products/compute/go_RegionBackendService.yaml @@ -826,7 +826,6 @@ properties: UNAVAILABLE_WEIGHT. Otherwise, Load Balancing remains equal-weight. - This field is applicable to either: * A regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, @@ -836,7 +835,6 @@ properties: Load Balancing). Only MAGLEV and WEIGHTED_MAGLEV values are possible for External Network Load Balancing. The default is MAGLEV. - If session_affinity is not NONE, and this field is not set to MAGLEV, WEIGHTED_MAGLEV, or RING_HASH, session affinity settings will not take effect. diff --git a/mmv1/products/compute/go_RegionSslCertificate.yaml b/mmv1/products/compute/go_RegionSslCertificate.yaml index 21f77cac5d19..a365f1cacf13 100644 --- a/mmv1/products/compute/go_RegionSslCertificate.yaml +++ b/mmv1/products/compute/go_RegionSslCertificate.yaml @@ -24,9 +24,9 @@ references: 'Official Documentation': 'https://cloud.google.com/load-balancing/docs/ssl-certificates' api: 'https://cloud.google.com/compute/docs/reference/rest/v1/regionSslCertificates' docs: - optional_properties: '* `name_prefix` - (Optional) Creates a unique name beginning with the - specified prefix. Conflicts with `name`. -' + optional_properties: | + * `name_prefix` - (Optional) Creates a unique name beginning with the + specified prefix. Conflicts with `name`. base_url: 'projects/{{project}}/regions/{{region}}/sslCertificates' has_self_link: true immutable: true @@ -119,7 +119,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. default_from_api: true custom_expand: 'templates/terraform/custom_expand/go/name_or_name_prefix.go.tmpl' diff --git a/mmv1/products/compute/go_Route.yaml b/mmv1/products/compute/go_Route.yaml index f3f3ecfb2435..ef5b1a44c013 100644 --- a/mmv1/products/compute/go_Route.yaml +++ b/mmv1/products/compute/go_Route.yaml @@ -44,11 +44,11 @@ references: 'Using Routes': 'https://cloud.google.com/vpc/docs/using-routes' api: 'https://cloud.google.com/compute/docs/reference/rest/v1/routes' docs: - optional_properties: '* `next_hop_instance_zone` - (Optional when `next_hop_instance` is - specified) The zone of the instance specified in - `next_hop_instance`. Omit if `next_hop_instance` is specified as - a URL. -' + optional_properties: | + * `next_hop_instance_zone` - (Optional when `next_hop_instance` is + specified) The zone of the instance specified in + `next_hop_instance`. Omit if `next_hop_instance` is specified as + a URL. base_url: 'projects/{{project}}/global/routes' has_self_link: true immutable: true diff --git a/mmv1/products/compute/go_RouterNat.yaml b/mmv1/products/compute/go_RouterNat.yaml index 4ba216388bec..8e6afb9e5415 100644 --- a/mmv1/products/compute/go_RouterNat.yaml +++ b/mmv1/products/compute/go_RouterNat.yaml @@ -150,7 +150,7 @@ properties: is set to MANUAL_ONLY. is_set: true send_empty_value: true - set_hash_func: 'computeRouterNatIPsHash' + set_hash_func: computeRouterNatIPsHash custom_expand: 'templates/terraform/custom_expand/go/array_resourceref_with_validation.go.tmpl' item_type: name: 'address' @@ -198,7 +198,7 @@ properties: api_name: subnetworks is_set: true send_empty_value: true - set_hash_func: 'computeRouterNatSubnetworkHash' + set_hash_func: computeRouterNatSubnetworkHash item_type: type: NestedObject properties: @@ -323,7 +323,7 @@ properties: description: 'A list of rules associated with this NAT.' is_set: true send_empty_value: true - set_hash_func: 'computeRouterNatRulesHash' + set_hash_func: computeRouterNatRulesHash item_type: type: NestedObject properties: @@ -368,7 +368,7 @@ properties: These IP addresses must be valid static external IP addresses assigned to the project. This field is used for public NAT. is_set: true - set_hash_func: 'computeRouterNatIPsHash' + set_hash_func: computeRouterNatIPsHash custom_flatten: 'templates/terraform/custom_flatten/go/nat_rules_ip_set.tmpl' custom_expand: 'templates/terraform/custom_expand/go/array_resourceref_with_validation.go.tmpl' item_type: @@ -386,7 +386,7 @@ properties: These IPs should be used for updating/patching a NAT rule only. This field is used for public NAT. is_set: true - set_hash_func: 'computeRouterNatIPsHash' + set_hash_func: computeRouterNatIPsHash custom_flatten: 'templates/terraform/custom_flatten/go/nat_rules_ip_set.tmpl' custom_expand: 'templates/terraform/custom_expand/go/array_resourceref_with_validation.go.tmpl' item_type: @@ -404,7 +404,7 @@ properties: This field is used for private NAT. is_set: true min_version: 'beta' - set_hash_func: 'computeRouterNatRulesSubnetHash' + set_hash_func: computeRouterNatRulesSubnetHash custom_flatten: 'templates/terraform/custom_flatten/go/nat_rules_subnets_set.tmpl' custom_expand: 'templates/terraform/custom_expand/go/array_resourceref_with_validation.go.tmpl' item_type: @@ -422,7 +422,7 @@ properties: This field is used for private NAT. is_set: true min_version: 'beta' - set_hash_func: 'computeRouterNatRulesSubnetHash' + set_hash_func: computeRouterNatRulesSubnetHash custom_flatten: 'templates/terraform/custom_flatten/go/nat_rules_subnets_set.tmpl' custom_expand: 'templates/terraform/custom_expand/go/array_resourceref_with_validation.go.tmpl' item_type: diff --git a/mmv1/products/compute/go_ServiceAttachment.yaml b/mmv1/products/compute/go_ServiceAttachment.yaml index 39e46277bc81..6c7d3fc345de 100644 --- a/mmv1/products/compute/go_ServiceAttachment.yaml +++ b/mmv1/products/compute/go_ServiceAttachment.yaml @@ -211,7 +211,7 @@ properties: attachment. is_set: true send_empty_value: true - set_hash_func: 'computeServiceAttachmentConsumerAcceptListsHash' + set_hash_func: computeServiceAttachmentConsumerAcceptListsHash item_type: type: NestedObject properties: diff --git a/mmv1/products/compute/go_SslCertificate.yaml b/mmv1/products/compute/go_SslCertificate.yaml index 40808e930866..97bc3263f0a8 100644 --- a/mmv1/products/compute/go_SslCertificate.yaml +++ b/mmv1/products/compute/go_SslCertificate.yaml @@ -24,9 +24,9 @@ references: 'Official Documentation': 'https://cloud.google.com/load-balancing/docs/ssl-certificates' api: 'https://cloud.google.com/compute/docs/reference/rest/v1/sslCertificates' docs: - optional_properties: '* `name_prefix` - (Optional) Creates a unique name beginning with the - specified prefix. Conflicts with `name`. -' + optional_properties: | + * `name_prefix` - (Optional) Creates a unique name beginning with the + specified prefix. Conflicts with `name`. base_url: 'projects/{{project}}/global/sslCertificates' has_self_link: true immutable: true @@ -107,7 +107,6 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. - These are in the same namespace as the managed SSL certificates. default_from_api: true custom_expand: 'templates/terraform/custom_expand/go/name_or_name_prefix.go.tmpl' diff --git a/mmv1/products/compute/go_TargetHttpsProxy.yaml b/mmv1/products/compute/go_TargetHttpsProxy.yaml index d9ec4cdc7d50..0b758b752c8c 100644 --- a/mmv1/products/compute/go_TargetHttpsProxy.yaml +++ b/mmv1/products/compute/go_TargetHttpsProxy.yaml @@ -125,6 +125,18 @@ properties: - 'NONE' - 'ENABLE' - 'DISABLE' + - name: 'tlsEarlyData' + type: Enum + description: | + Specifies whether TLS 1.3 0-RTT Data (“Early Data”) should be accepted for this service. + Early Data allows a TLS resumption handshake to include the initial application payload + (a HTTP request) alongside the handshake, reducing the effective round trips to “zero”. + This applies to TLS 1.3 connections over TCP (HTTP/2) as well as over UDP (QUIC/h3). + default_from_api: true + enum_values: + - 'STRICT' + - 'PERMISSIVE' + - 'DISABLED' - name: 'certificateManagerCertificates' type: Array description: | diff --git a/mmv1/products/compute/go_UrlMap.yaml b/mmv1/products/compute/go_UrlMap.yaml index 38680546b572..dee0cd5963de 100644 --- a/mmv1/products/compute/go_UrlMap.yaml +++ b/mmv1/products/compute/go_UrlMap.yaml @@ -118,6 +118,15 @@ examples: http_health_check_name: 'health-check' backend_bucket_name: 'static-asset-backend-bucket' storage_bucket_name: 'static-asset-bucket' + - name: 'url_map_custom_error_response_policy' + primary_resource_id: 'urlmap' + min_version: 'beta' + vars: + url_map_name: 'urlmap' + backend_service_name: 'login' + http_health_check_name: 'health-check' + storage_bucket_name: 'static-asset-bucket' + error_backend_bucket_name: 'error-backend-bucket' parameters: properties: - name: 'creationTimestamp' @@ -301,6 +310,63 @@ properties: description: | An optional description of this resource. Provide this property when you create the resource. + - name: 'defaultCustomErrorResponsePolicy' + type: NestedObject + description: | + defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + + This policy takes effect at the PathMatcher level and applies only when no policy has been defined for the error code at lower levels like RouteRule and PathRule within this PathMatcher. If an error code does not have a policy defined in defaultCustomErrorResponsePolicy, then a policy defined for the error code in UrlMap.defaultCustomErrorResponsePolicy takes effect. + + For example, consider a UrlMap with the following configuration: + + UrlMap.defaultCustomErrorResponsePolicy is configured with policies for 5xx and 4xx errors + A RouteRule for /coming_soon/ is configured for the error code 404. + If the request is for www.myotherdomain.com and a 404 is encountered, the policy under UrlMap.defaultCustomErrorResponsePolicy takes effect. If a 404 response is encountered for the request www.example.com/current_events/, the pathMatcher's policy takes effect. If however, the request for www.example.com/coming_soon/ encounters a 404, the policy in RouteRule.customErrorResponsePolicy takes effect. If any of the requests in this example encounter a 500 error code, the policy at UrlMap.defaultCustomErrorResponsePolicy takes effect. + + When used in conjunction with pathMatcher.defaultRouteAction.retryPolicy, retries take precedence. Only once all retries are exhausted, the defaultCustomErrorResponsePolicy is applied. While attempting a retry, if load balancer is successful in reaching the service, the defaultCustomErrorResponsePolicy is ignored and the response from the service is returned to the client. + + defaultCustomErrorResponsePolicy is supported only for global external Application Load Balancers. + min_version: 'beta' + properties: + - name: 'errorResponseRule' + type: Array + description: | + Specifies rules for returning error responses. + In a given policy, if you specify rules for both a range of error codes as well as rules for specific error codes then rules with specific error codes have a higher priority. + For example, assume that you configure a rule for 401 (Un-authorized) code, and another for all 4 series error codes (4XX). + If the backend service returns a 401, then the rule for 401 will be applied. However if the backend service returns a 403, the rule for 4xx takes effect. + api_name: errorResponseRules + item_type: + type: NestedObject + properties: + - name: 'matchResponseCodes' + type: Array + description: | + Valid values include: + - A number between 400 and 599: For example 401 or 503, in which case the load balancer applies the policy if the error code exactly matches this value. + - 5xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 500 to 599. + - 4xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 400 to 499. + Values must be unique within matchResponseCodes and across all errorResponseRules of CustomErrorResponsePolicy. + item_type: + type: String + - name: 'path' + type: String + description: | + The full path to a file within backendBucket . For example: /errors/defaultError.html + path must start with a leading slash. path cannot have trailing slashes. + If the file is not available in backendBucket or the load balancer cannot reach the BackendBucket, a simple Not Found Error is returned to the client. + The value must be from 1 to 1024 characters + - name: 'overrideResponseCode' + type: Integer + description: | + The HTTP status code returned with the response containing the custom error content. + If overrideResponseCode is not supplied, the same response code returned by the original backend bucket or backend service is returned to the client. + - name: 'errorService' + type: ResourceRef + description: | + The full or partial URL to the BackendBucket resource that contains the custom error content. Examples are: + resource: 'BackendBucket' + imports: 'selfLink' - name: 'headerAction' type: NestedObject description: | @@ -406,6 +472,60 @@ properties: required: true item_type: type: String + - name: 'customErrorResponsePolicy' + type: NestedObject + description: | + customErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + If a policy for an error code is not configured for the PathRule, a policy for the error code configured in pathMatcher.defaultCustomErrorResponsePolicy is applied. If one is not specified in pathMatcher.defaultCustomErrorResponsePolicy, the policy configured in UrlMap.defaultCustomErrorResponsePolicy takes effect. + For example, consider a UrlMap with the following configuration: + UrlMap.defaultCustomErrorResponsePolicy are configured with policies for 5xx and 4xx errors + A PathRule for /coming_soon/ is configured for the error code 404. + If the request is for www.myotherdomain.com and a 404 is encountered, the policy under UrlMap.defaultCustomErrorResponsePolicy takes effect. If a 404 response is encountered for the request www.example.com/current_events/, the pathMatcher's policy takes effect. If however, the request for www.example.com/coming_soon/ encounters a 404, the policy in PathRule.customErrorResponsePolicy takes effect. If any of the requests in this example encounter a 500 error code, the policy at UrlMap.defaultCustomErrorResponsePolicy takes effect. + customErrorResponsePolicy is supported only for global external Application Load Balancers. + min_version: 'beta' + properties: + - name: 'errorResponseRule' + type: Array + description: | + Specifies rules for returning error responses. + In a given policy, if you specify rules for both a range of error codes as well as rules for specific error codes then rules with specific error codes have a higher priority. + For example, assume that you configure a rule for 401 (Un-authorized) code, and another for all 4 series error codes (4XX). + If the backend service returns a 401, then the rule for 401 will be applied. However if the backend service returns a 403, the rule for 4xx takes effect. + api_name: errorResponseRules + item_type: + type: NestedObject + properties: + - name: 'matchResponseCodes' + type: Array + description: | + Valid values include: + + - A number between 400 and 599: For example 401 or 503, in which case the load balancer applies the policy if the error code exactly matches this value. + - 5xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 500 to 599. + - 4xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 400 to 499. + + Values must be unique within matchResponseCodes and across all errorResponseRules of CustomErrorResponsePolicy. + item_type: + type: String + - name: 'path' + type: String + description: | + The full path to a file within backendBucket . For example: /errors/defaultError.html + path must start with a leading slash. path cannot have trailing slashes. + If the file is not available in backendBucket or the load balancer cannot reach the BackendBucket, a simple Not Found Error is returned to the client. + The value must be from 1 to 1024 characters + - name: 'overrideResponseCode' + type: Integer + description: | + The HTTP status code returned with the response containing the custom error content. + If overrideResponseCode is not supplied, the same response code returned by the original backend bucket or backend service is returned to the client. + - name: 'errorService' + type: ResourceRef + description: | + The full or partial URL to the BackendBucket resource that contains the custom error content. Examples are: + + resource: 'BackendBucket' + imports: 'selfLink' - name: 'routeAction' type: NestedObject description: | @@ -1910,6 +2030,64 @@ properties: The value must be between 0.0 and 100.0 inclusive. validation: function: 'validation.FloatBetween(0, 100)' + - name: 'defaultCustomErrorResponsePolicy' + type: NestedObject + description: | + defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + + This policy takes effect at the PathMatcher level and applies only when no policy has been defined for the error code at lower levels like RouteRule and PathRule within this PathMatcher. If an error code does not have a policy defined in defaultCustomErrorResponsePolicy, then a policy defined for the error code in UrlMap.defaultCustomErrorResponsePolicy takes effect. + + For example, consider a UrlMap with the following configuration: + + UrlMap.defaultCustomErrorResponsePolicy is configured with policies for 5xx and 4xx errors + A RouteRule for /coming_soon/ is configured for the error code 404. + If the request is for www.myotherdomain.com and a 404 is encountered, the policy under UrlMap.defaultCustomErrorResponsePolicy takes effect. If a 404 response is encountered for the request www.example.com/current_events/, the pathMatcher's policy takes effect. If however, the request for www.example.com/coming_soon/ encounters a 404, the policy in RouteRule.customErrorResponsePolicy takes effect. If any of the requests in this example encounter a 500 error code, the policy at UrlMap.defaultCustomErrorResponsePolicy takes effect. + + When used in conjunction with pathMatcher.defaultRouteAction.retryPolicy, retries take precedence. Only once all retries are exhausted, the defaultCustomErrorResponsePolicy is applied. While attempting a retry, if load balancer is successful in reaching the service, the defaultCustomErrorResponsePolicy is ignored and the response from the service is returned to the client. + + defaultCustomErrorResponsePolicy is supported only for global external Application Load Balancers. + min_version: 'beta' + properties: + - name: 'errorResponseRule' + type: Array + description: | + Specifies rules for returning error responses. + In a given policy, if you specify rules for both a range of error codes as well as rules for specific error codes then rules with specific error codes have a higher priority. + For example, assume that you configure a rule for 401 (Un-authorized) code, and another for all 4 series error codes (4XX). + If the backend service returns a 401, then the rule for 401 will be applied. However if the backend service returns a 403, the rule for 4xx takes effect. + api_name: errorResponseRules + item_type: + type: NestedObject + properties: + - name: 'matchResponseCodes' + type: Array + description: | + Valid values include: + - A number between 400 and 599: For example 401 or 503, in which case the load balancer applies the policy if the error code exactly matches this value. + - 5xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 500 to 599. + - 4xx: Load Balancer will apply the policy if the backend service responds with any response code in the range of 400 to 499. + Values must be unique within matchResponseCodes and across all errorResponseRules of CustomErrorResponsePolicy. + item_type: + type: String + - name: 'path' + type: String + description: | + The full path to a file within backendBucket. For example: /errors/defaultError.html + path must start with a leading slash. path cannot have trailing slashes. + If the file is not available in backendBucket or the load balancer cannot reach the BackendBucket, a simple Not Found Error is returned to the client. + The value must be from 1 to 1024 characters. + - name: 'overrideResponseCode' + type: Integer + description: | + The HTTP status code returned with the response containing the custom error content. + If overrideResponseCode is not supplied, the same response code returned by the original backend bucket or backend service is returned to the client. + - name: 'errorService' + type: ResourceRef + description: | + The full or partial URL to the BackendBucket resource that contains the custom error content. Examples are: + + resource: 'BackendBucket' + imports: 'selfLink' - name: 'test' type: Array description: | diff --git a/mmv1/products/compute/go_VpnGateway.yaml b/mmv1/products/compute/go_VpnGateway.yaml index 87e0c5d6dda6..07b33e5b2f78 100644 --- a/mmv1/products/compute/go_VpnGateway.yaml +++ b/mmv1/products/compute/go_VpnGateway.yaml @@ -22,9 +22,9 @@ references: guides: api: 'https://cloud.google.com/compute/docs/reference/rest/v1/targetVpnGateways' docs: - warning: 'Classic VPN is deprecating certain functionality on October 31, 2021. For more information, -see the [Classic VPN partial deprecation page](https://cloud.google.com/network-connectivity/docs/vpn/deprecations/classic-vpn-deprecation). -' + warning: | + Classic VPN is deprecating certain functionality on October 31, 2021. For more information, + see the [Classic VPN partial deprecation page](https://cloud.google.com/network-connectivity/docs/vpn/deprecations/classic-vpn-deprecation). base_url: 'projects/{{project}}/regions/{{region}}/targetVpnGateways' has_self_link: true immutable: true diff --git a/mmv1/products/pubsub/go_Subscription.yaml b/mmv1/products/pubsub/go_Subscription.yaml index 3ee6f3eb70fa..02ab2a488f57 100644 --- a/mmv1/products/pubsub/go_Subscription.yaml +++ b/mmv1/products/pubsub/go_Subscription.yaml @@ -75,6 +75,14 @@ examples: subscription_name: 'example-subscription' dataset_id: 'example_dataset' table_id: 'example_table' + - name: 'pubsub_subscription_push_bq_service_account' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + dataset_id: 'example_dataset' + table_id: 'example_table' + service_account_id: 'example-bqw' - name: 'pubsub_subscription_push_cloudstorage' primary_resource_id: 'example' vars: @@ -87,6 +95,13 @@ examples: topic_name: 'example-topic' subscription_name: 'example-subscription' bucket_name: 'example-bucket' + - name: 'pubsub_subscription_push_cloudstorage_service_account' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + bucket_name: 'example-bucket' + service_account_id: 'example-stw' parameters: properties: - name: 'name' @@ -133,17 +148,15 @@ properties: description: | When true, use the topic's schema as the columns to write to in BigQuery, if it exists. Only one of use_topic_schema and use_table_schema can be set. - # Not present in Ruby version - # conflicts: - # - use_table_schema + conflicts: + - use_table_schema - name: 'useTableSchema' type: Boolean description: | When true, use the BigQuery table's schema as the columns to write to in BigQuery. Messages must be published in JSON format. Only one of use_topic_schema and use_table_schema can be set. - # Not present in Ruby version - # conflicts: - # - use_topic_schema + conflicts: + - use_topic_schema - name: 'writeMetadata' type: Boolean description: | @@ -155,6 +168,12 @@ properties: When true and use_topic_schema or use_table_schema is true, any fields that are a part of the topic schema or message schema that are not part of the BigQuery table schema are dropped when writing to BigQuery. Otherwise, the schemas must be kept in sync and any messages with extra fields are not written and remain in the subscription's backlog. + - name: 'serviceAccountEmail' + type: String + description: | + The service account to use to write to BigQuery. If not specified, the Pub/Sub + [service agent](https://cloud.google.com/iam/docs/service-agents), + service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com, is used. - name: 'cloudStorageConfig' type: NestedObject description: | @@ -212,6 +231,12 @@ properties: type: Boolean description: | When true, write the subscription name, messageId, publishTime, attributes, and orderingKey as additional fields in the output. + - name: 'serviceAccountEmail' + type: String + description: | + The service account to use to write to Cloud Storage. If not specified, the Pub/Sub + [service agent](https://cloud.google.com/iam/docs/service-agents), + service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com, is used. - name: 'pushConfig' type: NestedObject description: | diff --git a/mmv1/templates/terraform/custom_flatten/go/accesscontextmanager_serviceperimeters_custom_flatten.go.tmpl b/mmv1/templates/terraform/custom_flatten/go/accesscontextmanager_serviceperimeters_custom_flatten.go.tmpl new file mode 100644 index 000000000000..231fc3f35c04 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/go/accesscontextmanager_serviceperimeters_custom_flatten.go.tmpl @@ -0,0 +1,811 @@ +func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + apiData := make([]map[string]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + continue + } + apiData = append(apiData, map[string]interface{}{ + "name": flattenAccessContextManagerServicePerimetersServicePerimetersName(original["name"], d, config), + "title": flattenAccessContextManagerServicePerimetersServicePerimetersTitle(original["title"], d, config), + "description": flattenAccessContextManagerServicePerimetersServicePerimetersDescription(original["description"], d, config), + "create_time": flattenAccessContextManagerServicePerimetersServicePerimetersCreateTime(original["createTime"], d, config), + "update_time": flattenAccessContextManagerServicePerimetersServicePerimetersUpdateTime(original["updateTime"], d, config), + "perimeter_type": flattenAccessContextManagerServicePerimetersServicePerimetersPerimeterType(original["perimeterType"], d, config), + "status": flattenAccessContextManagerServicePerimetersServicePerimetersStatus(original["status"], d, config), + "spec": flattenAccessContextManagerServicePerimetersServicePerimetersSpec(original["spec"], d, config), + "use_explicit_dry_run_spec": flattenAccessContextManagerServicePerimetersServicePerimetersUseExplicitDryRunSpec(original["useExplicitDryRunSpec"], d, config), + }) + } + configData := []map[string]interface{}{} + for _, item := range d.Get("service_perimeters").([]interface{}) { + configData = append(configData, item.(map[string]interface{})) + } + sorted, err := tpgresource.SortMapsByConfigOrder(configData, apiData, "name") + if err != nil { + log.Printf("[ERROR] Could not sort API response value: %s", err) + return v + } + + return sorted +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersTitle(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersPerimeterType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil || tpgresource.IsEmptyValue(reflect.ValueOf(v)) { + return "PERIMETER_TYPE_REGULAR" + } + + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatus(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusResources(original["resources"], d, config) + transformed["access_levels"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusAccessLevels(original["accessLevels"], d, config) + transformed["restricted_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusRestrictedServices(original["restrictedServices"], d, config) + transformed["vpc_accessible_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServices(original["vpcAccessibleServices"], d, config) + transformed["ingress_policies"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPolicies(original["ingressPolicies"], d, config) + transformed["egress_policies"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPolicies(original["egressPolicies"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusAccessLevels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusRestrictedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServices(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["enable_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServicesEnableRestriction(original["enableRestriction"], d, config) + transformed["allowed_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServicesAllowedServices(original["allowedServices"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServicesEnableRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusVpcAccessibleServicesAllowedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPolicies(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := schema.NewSet(schema.HashResource(accesscontextmanagerServicePerimetersServicePerimetersServicePerimetersStatusIngressPoliciesSchema()), []interface{}{}) + 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.Add(map[string]interface{}{ + "ingress_from": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFrom(original["ingressFrom"], d, config), + "ingress_to": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressTo(original["ingressTo"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFrom(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["identity_type"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromIdentityType(original["identityType"], d, config) + transformed["identities"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSources(original["sources"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSources(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{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSourcesAccessLevel(original["accessLevel"], d, config), + "resource": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSourcesResource(original["resource"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressFromSourcesResource(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressTo(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToResources(original["resources"], d, config) + transformed["operations"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperations(original["operations"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperations(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{}{ + "service_name": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsServiceName(original["serviceName"], d, config), + "method_selectors": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectors(original["methodSelectors"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectors(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{}{ + "method": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectorsMethod(original["method"], d, config), + "permission": flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectorsPermission(original["permission"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectorsMethod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusIngressPoliciesIngressToOperationsMethodSelectorsPermission(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPolicies(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{}{ + "egress_from": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFrom(original["egressFrom"], d, config), + "egress_to": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressTo(original["egressTo"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFrom(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["identity_type"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) + transformed["identities"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(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{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressTo(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToResources(original["resources"], d, config) + transformed["external_resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToExternalResources(original["externalResources"], d, config) + transformed["operations"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperations(original["operations"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToExternalResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperations(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{}{ + "service_name": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsServiceName(original["serviceName"], d, config), + "method_selectors": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectors(original["methodSelectors"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectors(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{}{ + "method": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectorsMethod(original["method"], d, config), + "permission": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectorsPermission(original["permission"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectorsMethod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressToOperationsMethodSelectorsPermission(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpec(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecResources(original["resources"], d, config) + transformed["access_levels"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecAccessLevels(original["accessLevels"], d, config) + transformed["restricted_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecRestrictedServices(original["restrictedServices"], d, config) + transformed["vpc_accessible_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServices(original["vpcAccessibleServices"], d, config) + transformed["ingress_policies"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPolicies(original["ingressPolicies"], d, config) + transformed["egress_policies"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPolicies(original["egressPolicies"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecAccessLevels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecRestrictedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServices(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["enable_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServicesEnableRestriction(original["enableRestriction"], d, config) + transformed["allowed_services"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServicesAllowedServices(original["allowedServices"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServicesEnableRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecVpcAccessibleServicesAllowedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPolicies(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{}{ + "ingress_from": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFrom(original["ingressFrom"], d, config), + "ingress_to": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressTo(original["ingressTo"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFrom(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["identity_type"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromIdentityType(original["identityType"], d, config) + transformed["identities"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSources(original["sources"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSources(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{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSourcesAccessLevel(original["accessLevel"], d, config), + "resource": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSourcesResource(original["resource"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressFromSourcesResource(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressTo(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToResources(original["resources"], d, config) + transformed["operations"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperations(original["operations"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperations(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{}{ + "service_name": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsServiceName(original["serviceName"], d, config), + "method_selectors": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectors(original["methodSelectors"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectors(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{}{ + "method": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectorsMethod(original["method"], d, config), + "permission": flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectorsPermission(original["permission"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectorsMethod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecIngressPoliciesIngressToOperationsMethodSelectorsPermission(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPolicies(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{}{ + "egress_from": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFrom(original["egressFrom"], d, config), + "egress_to": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressTo(original["egressTo"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFrom(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["identity_type"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) + transformed["identities"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(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{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressTo(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["resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToResources(original["resources"], d, config) + transformed["external_resources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToExternalResources(original["externalResources"], d, config) + transformed["operations"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperations(original["operations"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToExternalResources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperations(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{}{ + "service_name": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsServiceName(original["serviceName"], d, config), + "method_selectors": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectors(original["methodSelectors"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectors(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{}{ + "method": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectorsMethod(original["method"], d, config), + "permission": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectorsPermission(original["permission"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectorsMethod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressToOperationsMethodSelectorsPermission(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersUseExplicitDryRunSpec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/templates/terraform/examples/go/url_map_custom_error_response_policy.tf.tmpl b/mmv1/templates/terraform/examples/go/url_map_custom_error_response_policy.tf.tmpl new file mode 100644 index 000000000000..6b3a72411f47 --- /dev/null +++ b/mmv1/templates/terraform/examples/go/url_map_custom_error_response_policy.tf.tmpl @@ -0,0 +1,86 @@ +resource "google_compute_url_map" "{{$.PrimaryResourceId}}" { + provider = google-beta + name = "{{index $.Vars "url_map_name"}}" + description = "a description" + + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["5xx"] # All 5xx responses will be catched + path = "/*" + override_response_code = 502 + } + error_service = google_compute_backend_bucket.error.id + } + + host_rule { + hosts = ["mysite.com"] + path_matcher = "mysite" + } + + path_matcher { + name = "mysite" + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["4xx", "5xx"] # All 4xx and 5xx responses will be catched on path login + path = "/login" + override_response_code = 404 + } + error_response_rule { + match_response_codes = ["503"] # Only a 503 response will be catched on path example + path = "/example" + override_response_code = 502 + } + error_service = google_compute_backend_bucket.error.id + } + + path_rule { + paths = ["/*"] + service = google_compute_backend_service.example.id + + custom_error_response_policy { + error_response_rule { + match_response_codes = ["4xx"] + path = "/register" + override_response_code = 401 + } + error_service = google_compute_backend_bucket.error.id + } + } + } +} + +resource "google_compute_backend_service" "example" { + provider = google-beta + name = "{{index $.Vars "backend_service_name"}}" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_http_health_check.default.id] +} + +resource "google_compute_http_health_check" "default" { + provider = google-beta + name = "{{index $.Vars "http_health_check_name"}}" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_backend_bucket" "error" { + provider = google-beta + name = "{{index $.Vars "error_backend_bucket_name"}}" + bucket_name = google_storage_bucket.error.name + enable_cdn = true +} + +resource "google_storage_bucket" "error" { + provider = google-beta + name = "{{index $.Vars "storage_bucket_name"}}" + location = "US" +} diff --git a/mmv1/templates/terraform/examples/go/vertex_ai_featureonlinestore_with_optimized.tf.tmpl b/mmv1/templates/terraform/examples/go/vertex_ai_featureonlinestore_with_optimized.tf.tmpl new file mode 100644 index 000000000000..acbdcb5b461c --- /dev/null +++ b/mmv1/templates/terraform/examples/go/vertex_ai_featureonlinestore_with_optimized.tf.tmpl @@ -0,0 +1,21 @@ +resource "google_vertex_ai_feature_online_store" "{{$.PrimaryResourceId}}" { + provider = google + name = "{{index $.Vars "name"}}" + labels = { + foo = "bar" + } + region = "us-central1" + optimized {} + dedicated_serving_endpoint { + private_service_connect_config { + enable_private_service_connect = true + project_allowlist = [data.google_project.project.number] + } + } +} + +data "google_project" "project" { + provider = google +} + + diff --git a/mmv1/templates/terraform/pre_create/go/firebasehosting_site.go.tmpl b/mmv1/templates/terraform/pre_create/go/firebasehosting_site.go.tmpl new file mode 100644 index 000000000000..f31de67be01f --- /dev/null +++ b/mmv1/templates/terraform/pre_create/go/firebasehosting_site.go.tmpl @@ -0,0 +1,27 @@ + +// Check if the Firebase hostng site already exits. Do an update if so. + +getUrl, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}FirebaseHostingBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/sites/{{"{{"}}site_id{{"}}"}}") +if err != nil { + return err +} +_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: getUrl, + UserAgent: userAgent, + Headers: headers, +}) + +if err == nil { + // Hosting site already exists + log.Printf("[DEBUG] Firebase hosting site already exists %s", d.Get("site_id")) + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{"{{"}}project{{"}}"}}/sites/{{"{{"}}site_id{{"}}"}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + return resourceFirebaseHostingSiteUpdate(d, meta) +} \ No newline at end of file diff --git a/mmv1/templates/terraform/yaml_conversion.erb b/mmv1/templates/terraform/yaml_conversion.erb index a04c27fadbbb..e2f06c8688ff 100644 --- a/mmv1/templates/terraform/yaml_conversion.erb +++ b/mmv1/templates/terraform/yaml_conversion.erb @@ -60,19 +60,19 @@ references: <% unless object.docs.nil? -%> docs: <% unless object.docs.warning.nil? -%> - warning: '<%= object.docs.warning %>' + warning: <% end -%> <% unless object.docs.note.nil? -%> note: <% end -%> <% unless object.docs.required_properties.nil? -%> - required_properties: '<%= object.docs.required_properties %>' + required_properties: <% end -%> <% unless object.docs.optional_properties.nil? -%> - optional_properties: '<%= object.docs.optional_properties %>' + optional_properties: <% end -%> <% unless object.docs.attributes.nil? -%> - attributes: '<%= object.docs.attributes %>' + attributes: <% end -%> <% end -%> <% diff --git a/mmv1/third_party/terraform/go/go.mod b/mmv1/third_party/terraform/go/go.mod index 491855828e38..9aeb1b3967d5 100644 --- a/mmv1/third_party/terraform/go/go.mod +++ b/mmv1/third_party/terraform/go/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( cloud.google.com/go/bigtable v1.24.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.67.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.68.0 github.com/apparentlymart/go-cidr v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/dnaeon/go-vcr v1.0.1 diff --git a/mmv1/third_party/terraform/services/compute/go/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/go/resource_compute_instance.go.tmpl index 7c177d611d58..045b0be451fa 100644 --- a/mmv1/third_party/terraform/services/compute/go/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/go/resource_compute_instance.go.tmpl @@ -2474,7 +2474,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if d.HasChange("service_account.0.email") || scopesChange { sa := d.Get("service_account").([]interface{}) req := &compute.InstancesSetServiceAccountRequest{ForceSendFields: []string{"email"}} - if len(sa) > 0 && sa[0] != nil { + if !isEmptyServiceAccountBlock(d) && len(sa) > 0 && sa[0] != nil { saMap := sa[0].(map[string]interface{}) req.Email = saMap["email"].(string) req.Scopes = tpgresource.CanonicalizeServiceScopes(tpgresource.ConvertStringSet(saMap["scopes"].(*schema.Set))) @@ -3093,6 +3093,11 @@ func serviceAccountDiffSuppress(k, old, new string, d *schema.ResourceData) bool // suppress changes between { } and {scopes:[]} if l[0] != nil { contents := l[0].(map[string]interface{}) + email := contents["email"] + if email != "" { + // if email is non empty, don't suppress the diff + return false + } if scopes, ok := contents["scopes"]; ok { a := scopes.(*schema.Set).List() if a != nil && len(a) > 0 { @@ -3102,3 +3107,43 @@ func serviceAccountDiffSuppress(k, old, new string, d *schema.ResourceData) bool } return true } + +// isEmptyServiceAccountBlock is used to work around an issue when updating +// service accounts. Creating the instance with some scopes but without +// specifying a service account email, assigns default compute service account +// to the instance: +// +// service_account { +// scopes = ["some-scope"] +// } +// +// Then when updating the instance with empty service account: +// +// service_account { +// scopes = [] +// } +// +// the default Terraform behavior is to clear scopes without clearing the +// email. The email was previously computed to be the default service account +// and has not been modified, so the default plan is to leave it unchanged. +// However, when creating a new instance: +// +// service_account { +// scopes = [] +// } +// +// indicates an instance without any service account set. +// isEmptyServiceAccountBlock is used to detect empty service_account block +// and if it is, it is interpreted as no service account and no scopes. +// +func isEmptyServiceAccountBlock(d *schema.ResourceData) bool { + serviceAccountsConfig := d.GetRawConfig().GetAttr("service_account") + if serviceAccountsConfig.IsNull() || len(serviceAccountsConfig.AsValueSlice()) == 0 { + return true + } + serviceAccount := serviceAccountsConfig.AsValueSlice()[0] + if serviceAccount.GetAttr("email").IsNull() && len(serviceAccount.GetAttr("scopes").AsValueSlice()) == 0 { + return true + } + return false +} diff --git a/mmv1/third_party/terraform/services/compute/go/resource_compute_instance_test.go.tmpl b/mmv1/third_party/terraform/services/compute/go/resource_compute_instance_test.go.tmpl index 3a9d5d2bc89b..27e65e9281ec 100644 --- a/mmv1/third_party/terraform/services/compute/go/resource_compute_instance_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/go/resource_compute_instance_test.go.tmpl @@ -1109,6 +1109,54 @@ func TestAccComputeInstance_serviceAccount(t *testing.T) { }) } +func TestAccComputeInstance_noServiceAccount(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_noServiceAccount(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoServiceAccount(&instance), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + +func TestAccComputeInstance_serviceAccountEmail_0scopes(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_serviceAccountEmail_0scopes(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceMatchServiceAccount(&instance, "\\d+-compute@developer.gserviceaccount.com"), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + func TestAccComputeInstance_serviceAccount_updated(t *testing.T) { t.Parallel() @@ -1125,6 +1173,7 @@ func TestAccComputeInstance_serviceAccount_updated(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoServiceAccount(&instance), testAccCheckComputeInstanceScopes(&instance, 0), ), }, @@ -1134,6 +1183,7 @@ func TestAccComputeInstance_serviceAccount_updated(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoServiceAccount(&instance), testAccCheckComputeInstanceScopes(&instance, 0), ), }, @@ -1143,6 +1193,7 @@ func TestAccComputeInstance_serviceAccount_updated(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceMatchServiceAccount(&instance, "\\d+-compute@developer.gserviceaccount.com"), testAccCheckComputeInstanceScopes(&instance, 0), ), }, @@ -1152,6 +1203,7 @@ func TestAccComputeInstance_serviceAccount_updated(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceMatchServiceAccount(&instance, "\\d+-compute@developer.gserviceaccount.com"), testAccCheckComputeInstanceScopes(&instance, 3), ), }, @@ -1176,6 +1228,7 @@ func TestAccComputeInstance_serviceAccount_updated0to1to0scopes(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoServiceAccount(&instance), testAccCheckComputeInstanceScopes(&instance, 0), ), }, @@ -1185,6 +1238,7 @@ func TestAccComputeInstance_serviceAccount_updated0to1to0scopes(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceMatchServiceAccount(&instance, "\\d+-compute@developer.gserviceaccount.com"), testAccCheckComputeInstanceScopes(&instance, 1), ), }, @@ -1194,6 +1248,7 @@ func TestAccComputeInstance_serviceAccount_updated0to1to0scopes(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoServiceAccount(&instance), testAccCheckComputeInstanceScopes(&instance, 0), ), }, @@ -4083,6 +4138,30 @@ func testAccCheckComputeInstanceServiceAccount(instance *compute.Instance, scope } } +func testAccCheckComputeInstanceNoServiceAccount(instance *compute.Instance) resource.TestCheckFunc { + return func(s *terraform.State) error { + if count := len(instance.ServiceAccounts); count != 0 { + return fmt.Errorf("Wrong number of ServiceAccounts: expected 0, got %d", count) + } + return nil + } +} + +func testAccCheckComputeInstanceMatchServiceAccount(instance *compute.Instance, serviceAcctRegexp string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if count := len(instance.ServiceAccounts); count != 1 { + return fmt.Errorf("Wrong number of ServiceAccounts: expected 1, got %d", count) + } + + email := instance.ServiceAccounts[0].Email + if !regexp.MustCompile(serviceAcctRegexp).MatchString(email) { + return fmt.Errorf("ServiceAccount email didn't match:\"%s\", got \"%s\"", serviceAcctRegexp, email) + } + + return nil + } +} + func testAccCheckComputeInstanceScopes(instance *compute.Instance, scopeCount int) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -6115,6 +6194,70 @@ resource "google_compute_instance" "foobar" { `, instance) } +func testAccComputeInstance_noServiceAccount(instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + + service_account { + scopes = [] + } +} +`, instance) +} + +func testAccComputeInstance_serviceAccountEmail_0scopes(instance string) string { + return fmt.Sprintf(` +data "google_project" "project" {} + +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + + service_account { + email = data.google_compute_default_service_account.default.email + scopes = [] + } +} + +data "google_compute_default_service_account" "default" { +} +`, instance) +} + func testAccComputeInstance_serviceAccount_update0(instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/services/compute/go/resource_compute_target_https_proxy_test.go.tmpl b/mmv1/third_party/terraform/services/compute/go/resource_compute_target_https_proxy_test.go.tmpl index b66d344c9d48..7fc12c1b57e9 100644 --- a/mmv1/third_party/terraform/services/compute/go/resource_compute_target_https_proxy_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/go/resource_compute_target_https_proxy_test.go.tmpl @@ -225,6 +225,7 @@ resource "google_compute_target_https_proxy" "foobar" { google_compute_ssl_certificate.foobar2.self_link, ] quic_override = "ENABLE" + tls_early_data = "STRICT" } resource "google_compute_backend_service" "foobar" { diff --git a/mmv1/third_party/terraform/services/compute/go/resource_compute_url_map_test.go.tmpl b/mmv1/third_party/terraform/services/compute/go/resource_compute_url_map_test.go.tmpl new file mode 100644 index 000000000000..ce955dca24d1 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/go/resource_compute_url_map_test.go.tmpl @@ -0,0 +1,1912 @@ +package compute_test + +import ( + "fmt" + "testing" + "github.com/hashicorp/terraform-provider-google/google/acctest" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccComputeUrlMap_update_path_matcher(t *testing.T) { + t.Parallel() + + bsName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + hcName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + umName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_basic1(bsName, hcName, umName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + + { + Config: testAccComputeUrlMap_basic2(bsName, hcName, umName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + }, + }) +} + +func TestAccComputeUrlMap_advanced(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_advanced1(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + + { + Config: testAccComputeUrlMap_advanced2(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + }, + }) +} + +func TestAccComputeUrlMap_defaultRouteActionPathUrlRewrite(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_defaultRouteActionPathUrlRewrite(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + { + Config: testAccComputeUrlMap_defaultRouteActionPathUrlRewrite_update(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + }, + }) +} + +func TestAccComputeUrlMap_defaultRouteActionUrlRewrite(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_defaultRouteActionUrlRewrite(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + + { + Config: testAccComputeUrlMap_defaultRouteActionUrlRewrite_update(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + }, + }) +} + +func TestAccComputeUrlMap_noPathRulesWithUpdate(t *testing.T) { + t.Parallel() + + bsName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + hcName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + umName := fmt.Sprintf("urlmap-test-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_noPathRules(bsName, hcName, umName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + { + Config: testAccComputeUrlMap_basic1(bsName, hcName, umName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeUrlMapExists( + t, "google_compute_url_map.foobar"), + ), + }, + }, + }) +} + +func testAccCheckComputeUrlMapExists(t *testing.T, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := acctest.GoogleProviderConfig(t) + name := rs.Primary.Attributes["name"] + + found, err := config.NewComputeClient(config.UserAgent).UrlMaps.Get( + config.Project, name).Do() + if err != nil { + return err + } + + if found.Name != name { + return fmt.Errorf("Url map not found") + } + return nil + } +} + +func TestAccComputeUrlMap_defaultRouteActionTrafficDirectorPathUpdate(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(t, 10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_defaultRouteActionTrafficDirectorPath(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_defaultRouteActionTrafficDirectorPathUpdate(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_defaultRouteActionTrafficDirectorUpdate(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(t, 10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_defaultRouteActionTrafficDirector(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_defaultRouteActionTrafficDirectorUpdate(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_trafficDirectorUpdate(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(t, 10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_trafficDirector(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_trafficDirectorUpdate(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_trafficDirectorPathUpdate(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(t, 10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_trafficDirectorPath(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_trafficDirectorPathUpdate(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_trafficDirectorRemoveRouteRule(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(t, 10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_trafficDirector(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_trafficDirectorRemoveRouteRule(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_defaultUrlRedirect(t *testing.T) { + t.Parallel() + + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_defaultUrlRedirectConfig(randomSuffix), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +{{ if ne $.TargetVersionName `ga` -}} +func TestAccComputeUrlMap_urlMapCustomErrorResponsePolicyUpdate(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.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckComputeUrlMapDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_urlMapCustomErrorResponsePolicy(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"default_service"}, + }, + { + Config: testAccComputeUrlMap_urlMapCustomErrorResponsePolicyUpdate(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"default_service"}, + }, + }, + }) +} +{{- end }} + +func testAccComputeUrlMap_basic1(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "boop" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "boop" + + path_rule { + paths = ["/*"] + service = google_compute_backend_service.foobar.self_link + } + } + + test { + host = "mysite.com" + path = "/*" + service = google_compute_backend_service.foobar.self_link + } +} +`, bsName, hcName, umName) +} + +func testAccComputeUrlMap_basic2(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "blip" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blip" + + path_rule { + paths = ["/*", "/home"] + service = google_compute_backend_service.foobar.self_link + } + } + + test { + host = "mysite.com" + path = "/test" + service = google_compute_backend_service.foobar.self_link + } +} +`, bsName, hcName, umName) +} + +func testAccComputeUrlMap_advanced1(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "blop" + } + + host_rule { + hosts = ["myfavoritesite.com"] + path_matcher = "blip" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blop" + + path_rule { + paths = ["/*", "/home"] + service = google_compute_backend_service.foobar.self_link + } + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blip" + + path_rule { + paths = ["/*", "/home"] + service = google_compute_backend_service.foobar.self_link + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_advanced2(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "blep" + } + + host_rule { + hosts = ["myfavoritesite.com"] + path_matcher = "blip" + } + + host_rule { + hosts = ["myleastfavoritesite.com"] + path_matcher = "blub" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blep" + + path_rule { + paths = ["/home"] + service = google_compute_backend_service.foobar.self_link + } + + path_rule { + paths = ["/login"] + service = google_compute_backend_service.foobar.self_link + } + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blub" + + path_rule { + paths = ["/*", "/blub"] + service = google_compute_backend_service.foobar.self_link + } + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blip" + + path_rule { + paths = ["/*", "/home"] + service = google_compute_backend_service.foobar.self_link + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_defaultRouteActionPathUrlRewrite(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "blep" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blep" + + path_rule { + paths = ["/home"] + service = google_compute_backend_service.foobar.self_link + } + + path_rule { + paths = ["/login"] + service = google_compute_backend_service.foobar.self_link + } + + default_route_action { + url_rewrite { + host_rewrite = "dev.example.com" + path_prefix_rewrite = "/v1/api/" + } + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_defaultRouteActionPathUrlRewrite_update(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "blep" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "blep" + + path_rule { + paths = ["/home"] + service = google_compute_backend_service.foobar.self_link + } + + path_rule { + paths = ["/login"] + service = google_compute_backend_service.foobar.self_link + } + + default_route_action { + url_rewrite { + host_rewrite = "stage.example.com" # updated + path_prefix_rewrite = "/v2/api/" # updated + } + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_defaultRouteActionUrlRewrite(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + default_route_action { + url_rewrite { + host_rewrite = "dev.example.com" + path_prefix_rewrite = "/v1/api/" + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_defaultRouteActionUrlRewrite_update(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + default_route_action { + url_rewrite { + host_rewrite = "stage.example.com" # updated + path_prefix_rewrite = "/v2/api/" # updated + } + } +} +`, suffix, suffix, suffix) +} + +func testAccComputeUrlMap_noPathRules(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "foobar" { + name = "urlmap-test-%s" + health_checks = [google_compute_http_health_check.zero.self_link] +} + +resource "google_compute_http_health_check" "zero" { + name = "urlmap-test-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_service = google_compute_backend_service.foobar.self_link + + host_rule { + hosts = ["mysite.com", "myothersite.com"] + path_matcher = "boop" + } + + path_matcher { + default_service = google_compute_backend_service.foobar.self_link + name = "boop" + } + + test { + host = "mysite.com" + path = "/*" + service = google_compute_backend_service.foobar.self_link + } +} +`, bsName, hcName, umName) +} + +func testAccComputeUrlMap_trafficDirector(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths" + } + + path_matcher { + name = "allpaths" + default_service = "${google_compute_backend_service.home.self_link}" + + route_rules { + priority = 1 + header_action { + request_headers_to_remove = ["RemoveMe2"] + request_headers_to_add { + header_name = "AddSomethingElse" + header_value = "MyOtherValue" + replace = true + } + response_headers_to_remove = ["RemoveMe3"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + match_rules { + full_path_match = "a full path" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + ignore_case = true + metadata_filters { + filter_match_criteria = "MATCH_ANY" + filter_labels { + name = "PLANET" + value = "MARS" + } + } + query_parameter_matches { + name = "a query parameter" + present_match = true + } + } + url_redirect { + host_redirect = "A host" + https_redirect = false + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = true + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} + +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorUpdate(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home2.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + default_service = "${google_compute_backend_service.home2.self_link}" + + route_rules { + priority = 2 + header_action { + request_headers_to_remove = ["RemoveMe2", "AndMe"] + request_headers_to_add { + header_name = "AddSomethingElseUpdated" + header_value = "MyOtherValueUpdated" + replace = false + } + response_headers_to_remove = ["RemoveMe3", "AndMe4"] + } + match_rules { + full_path_match = "a full path to match" + header_matches { + header_name = "someheaderfoo" + exact_match = "match this exactly again" + invert_match = false + } + ignore_case = false + metadata_filters { + filter_match_criteria = "MATCH_ALL" + filter_labels { + name = "PLANET" + value = "EARTH" + } + } + } + url_redirect { + host_redirect = "A host again" + https_redirect = true + path_redirect = "some/path/twice" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = false + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorRemoveRouteRule(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home2.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + default_service = "${google_compute_backend_service.home2.self_link}" + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorPath(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths" + } + + path_matcher { + name = "allpaths" + default_service = "${google_compute_backend_service.home.self_link}" + + path_rule { + paths = ["/home"] + route_action { + cors_policy { + allow_credentials = true + allow_headers = ["Allowed content"] + allow_methods = ["GET"] + allow_origin_regexes = ["abc.*"] + allow_origins = ["Allowed origin"] + expose_headers = ["Exposed header"] + max_age = 30 + disabled = true + } + fault_injection_policy { + abort { + http_status = 234 + percentage = 5.6 + } + delay { + fixed_delay { + seconds = 0 + nanos = 50000 + } + percentage = 7.8 + } + } + request_mirror_policy { + backend_service = "${google_compute_backend_service.home.self_link}" + } + retry_policy { + num_retries = 4 + per_try_timeout { + seconds = 30 + } + retry_conditions = ["5xx", "deadline-exceeded"] + } + timeout { + seconds = 20 + nanos = 750000000 + } + url_rewrite { + host_rewrite = "dev.example.com" + path_prefix_rewrite = "/v1/api/" + } + weighted_backend_services { + backend_service = "${google_compute_backend_service.home.self_link}" + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMe"] + request_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = true + } + response_headers_to_remove = ["RemoveMe"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + } + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} + +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorPathUpdate(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home2.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + default_service = "${google_compute_backend_service.home.self_link}" + + path_rule { + paths = ["/homeupdated"] + route_action { + cors_policy { + allow_credentials = false + allow_headers = ["Allowed content updated"] + allow_methods = ["PUT"] + allow_origin_regexes = ["abcdef.*"] + allow_origins = ["Allowed origin updated"] + expose_headers = ["Exposed header updated"] + max_age = 31 + disabled = false + } + fault_injection_policy { + abort { + http_status = 235 + percentage = 6.7 + } + delay { + fixed_delay { + seconds = 1 + nanos = 40000 + } + percentage = 8.9 + } + } + request_mirror_policy { + backend_service = "${google_compute_backend_service.home.self_link}" + } + retry_policy { + num_retries = 5 + per_try_timeout { + seconds = 31 + } + retry_conditions = ["5xx"] + } + timeout { + seconds = 21 + nanos = 760000000 + } + url_rewrite { + host_rewrite = "stage.example.com" # updated + path_prefix_rewrite = "/v2/api/" # updated + } + weighted_backend_services { + backend_service = "${google_compute_backend_service.home.self_link}" + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMeUpdated"] + request_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = false + } + response_headers_to_remove = ["RemoveMeUpdated"] + response_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = true + } + } + } + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_defaultRouteActionTrafficDirectorPath(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = google_compute_backend_service.home.self_link + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths" + } + + path_matcher { + name = "allpaths" + + default_route_action { + cors_policy { + allow_credentials = true + allow_headers = ["Allowed content"] + allow_methods = ["GET"] + allow_origin_regexes = ["abc.*"] + allow_origins = ["Allowed origin"] + expose_headers = ["Exposed header"] + max_age = 30 + disabled = true + } + fault_injection_policy { + abort { + http_status = 234 + percentage = 5.6 + } + delay { + fixed_delay { + seconds = 0 + nanos = 50000 + } + percentage = 7.8 + } + } + request_mirror_policy { + backend_service = google_compute_backend_service.home.self_link + } + retry_policy { + num_retries = 4 + per_try_timeout { + seconds = 30 + } + retry_conditions = ["5xx", "deadline-exceeded"] + } + timeout { + seconds = 20 + nanos = 750000000 + } + url_rewrite { + host_rewrite = "dev.example.com" + path_prefix_rewrite = "/v1/api/" + } + weighted_backend_services { + backend_service = google_compute_backend_service.home.self_link + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMe"] + request_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = true + } + response_headers_to_remove = ["RemoveMe"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + } + } + } + + test { + service = google_compute_backend_service.home.self_link + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} + +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_defaultRouteActionTrafficDirectorPathUpdate(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = google_compute_backend_service.home2.self_link + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + + default_route_action { + cors_policy { + allow_credentials = false + allow_headers = ["Allowed content updated"] + allow_methods = ["PUT"] + allow_origin_regexes = ["abcdef.*"] + allow_origins = ["Allowed origin updated"] + expose_headers = ["Exposed header updated"] + max_age = 31 + disabled = false + } + fault_injection_policy { + abort { + http_status = 235 + percentage = 6.7 + } + delay { + fixed_delay { + seconds = 1 + nanos = 40000 + } + percentage = 8.9 + } + } + request_mirror_policy { + backend_service = google_compute_backend_service.home.self_link + } + retry_policy { + num_retries = 5 + per_try_timeout { + seconds = 31 + } + retry_conditions = ["5xx"] + } + timeout { + seconds = 21 + nanos = 760000000 + } + url_rewrite { + host_rewrite = "stage.example.com" # updated + path_prefix_rewrite = "/v2/api/" # updated + } + weighted_backend_services { + backend_service = google_compute_backend_service.home.self_link + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMeUpdated"] + request_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = false + } + response_headers_to_remove = ["RemoveMeUpdated"] + response_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = true + } + } + } + } + } + + test { + service = google_compute_backend_service.home.self_link + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + + +func testAccComputeUrlMap_defaultRouteActionTrafficDirector(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + + default_route_action { + cors_policy { + allow_credentials = true + allow_headers = ["Allowed content"] + allow_methods = ["GET"] + allow_origin_regexes = ["abc.*"] + allow_origins = ["Allowed origin"] + expose_headers = ["Exposed header"] + max_age = 30 + disabled = true + } + fault_injection_policy { + abort { + http_status = 234 + percentage = 5.6 + } + delay { + fixed_delay { + seconds = 0 + nanos = 50000 + } + percentage = 7.8 + } + } + request_mirror_policy { + backend_service = google_compute_backend_service.home.self_link + } + retry_policy { + num_retries = 4 + per_try_timeout { + seconds = 30 + } + retry_conditions = ["5xx", "deadline-exceeded"] + } + timeout { + seconds = 20 + nanos = 750000000 + } + url_rewrite { + host_rewrite = "dev.example.com" + path_prefix_rewrite = "/v1/api/" + } + weighted_backend_services { + backend_service = google_compute_backend_service.home.self_link + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMe"] + request_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = true + } + response_headers_to_remove = ["RemoveMe"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + } + } + + test { + service = google_compute_backend_service.home.self_link + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} + +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_defaultRouteActionTrafficDirectorUpdate(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + + default_route_action { + cors_policy { + allow_credentials = false + allow_headers = ["Allowed content updated"] + allow_methods = ["PUT"] + allow_origin_regexes = ["abcdef.*"] + allow_origins = ["Allowed origin updated"] + expose_headers = ["Exposed header updated"] + max_age = 31 + disabled = false + } + fault_injection_policy { + abort { + http_status = 235 + percentage = 6.7 + } + delay { + fixed_delay { + seconds = 1 + nanos = 40000 + } + percentage = 8.9 + } + } + request_mirror_policy { + backend_service = google_compute_backend_service.home2.self_link + } + retry_policy { + num_retries = 5 + per_try_timeout { + seconds = 31 + } + retry_conditions = ["5xx"] + } + timeout { + seconds = 21 + nanos = 760000000 + } + url_rewrite { + host_rewrite = "stage.example.com" # updated + path_prefix_rewrite = "/v2/api/" # updated + } + weighted_backend_services { + backend_service = google_compute_backend_service.home2.self_link + weight = 400 + header_action { + request_headers_to_remove = ["RemoveMeUpdated"] + request_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = false + } + response_headers_to_remove = ["RemoveMeUpdated"] + response_headers_to_add { + header_name = "AddMeUpdated" + header_value = "MyValueUpdated" + replace = true + } + } + } + } + + test { + service = google_compute_backend_service.home2.self_link + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_health_check.default.self_link] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_defaultUrlRedirectConfig(randomSuffix string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "urlmap-test-%s" + default_url_redirect { + https_redirect = true + strip_query = false + } +} +`, randomSuffix) +} + +{{ if ne $.TargetVersionName `ga` -}} +func testAccComputeUrlMap_urlMapCustomErrorResponsePolicy(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_url_map" "urlmap" { + provider = google-beta + name = "urlmap%{random_suffix}" + description = "a description" + + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["5xx"] # All 5xx responses will be catched + path = "/*" + override_response_code = 502 + } + error_service = google_compute_backend_bucket.error.id + } + + host_rule { + hosts = ["mysite.com"] + path_matcher = "mysite" + } + + path_matcher { + name = "mysite" + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["4xx", "5xx"] # All 4xx and 5xx responses will be catched on path login + path = "/login" + override_response_code = 404 + } + error_response_rule { + match_response_codes = ["503"] # Only a 503 response will be catched on path example + path = "/example" + override_response_code = 502 + } + error_service = google_compute_backend_bucket.error.id + } + + path_rule { + paths = ["/*"] + service = google_compute_backend_service.example.id + + custom_error_response_policy { + error_response_rule { + match_response_codes = ["4xx"] + path = "/register" + override_response_code = 401 + } + error_service = google_compute_backend_bucket.error.id + } + } + } +} + +resource "google_compute_backend_service" "example" { + provider = google-beta + name = "login%{random_suffix}" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_http_health_check.default.id] +} + +resource "google_compute_http_health_check" "default" { + provider = google-beta + name = "tf-test-health-check%{random_suffix}" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_backend_bucket" "error" { + provider = google-beta + name = "tf-test-error-backend-bucket%{random_suffix}" + bucket_name = google_storage_bucket.error.name + enable_cdn = true +} + +resource "google_storage_bucket" "error" { + provider = google-beta + name = "tf-test-static-asset-bucket%{random_suffix}" + location = "US" +} +`, context) +} +{{- end }} + +{{ if ne $.TargetVersionName `ga` -}} +func testAccComputeUrlMap_urlMapCustomErrorResponsePolicyUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_url_map" "urlmap" { + provider = google-beta + name = "urlmap%{random_suffix}" + description = "a description" + + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["5xx", "4xx"] # All 5xx responses will be catched + path = "/test/*" + override_response_code = 503 + } + error_service = google_compute_backend_bucket.error.id + } + + host_rule { + hosts = ["mysite.com"] + path_matcher = "mysite" + } + + path_matcher { + name = "mysite" + default_service = google_compute_backend_service.example.id + + default_custom_error_response_policy { + error_response_rule { + match_response_codes = ["5xx"] # All 4xx and 5xx responses will be catched on path login + path = "/*" + override_response_code = 502 + } + error_response_rule { + match_response_codes = ["4xx"] # Only a 503 response will be catched on path example + path = "/example/test" + override_response_code = 400 + } + error_service = google_compute_backend_bucket.error.id + } + + path_rule { + paths = ["/*"] + service = google_compute_backend_service.example.id + + custom_error_response_policy { + error_response_rule { + match_response_codes = ["5xx"] + path = "/register/example/*" + override_response_code = 403 + } + error_service = google_compute_backend_bucket.error.id + } + } + } +} + +resource "google_compute_backend_service" "example" { + provider = google-beta + name = "login%{random_suffix}" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_http_health_check.default.id] +} + +resource "google_compute_http_health_check" "default" { + provider = google-beta + name = "tf-test-health-check%{random_suffix}" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_backend_bucket" "error" { + provider = google-beta + name = "tf-test-error-backend-bucket-2%{random_suffix}" + bucket_name = google_storage_bucket.error.name + enable_cdn = true + + lifecycle { + create_before_destroy = true + } +} + +resource "google_storage_bucket" "error" { + provider = google-beta + name = "tf-test-static-asset-bucket-2%{random_suffix}" + location = "US" +} +`, context) +} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/firebasehosting/go/resource_firebase_hosting_site_test.go.tmpl b/mmv1/third_party/terraform/services/firebasehosting/go/resource_firebase_hosting_site_test.go.tmpl index e5a7d337eafb..cc0e77f6f4ee 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/go/resource_firebase_hosting_site_test.go.tmpl +++ b/mmv1/third_party/terraform/services/firebasehosting/go/resource_firebase_hosting_site_test.go.tmpl @@ -45,6 +45,34 @@ func TestAccFirebaseHostingSite_firebasehostingSiteUpdate(t *testing.T) { }) } +func TestAccFirebaseHostingSite_firebasehostingSiteUpsert(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + "site_id": "tf-test-site-upsert", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckFirebaseHostingSiteDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccFirebaseHostingSite_firebasehostingSiteUpsert(context), + }, + { + ResourceName: "google_firebase_hosting_site.create2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"site_id"}, + }, + }, + }) +} + + func testAccFirebaseHostingSite_firebasehostingSiteBeforeUpdate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_firebase_web_app" "before" { @@ -79,4 +107,22 @@ resource "google_firebase_hosting_site" "update" { `, context) } +func testAccFirebaseHostingSite_firebasehostingSiteUpsert(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_firebase_hosting_site" "create" { + provider = google-beta + project = "%{project_id}" + site_id = "%{site_id}%{random_suffix}" +} + +resource "google_firebase_hosting_site" "create2" { + provider = google-beta + project = "%{project_id}" + site_id = "%{site_id}%{random_suffix}" + + depends_on = [google_firebase_hosting_site.create] +} +`, context) +} + {{ end }} \ No newline at end of file