From 51b28c7318d0c549dc200849f1526d9c27a8b59f Mon Sep 17 00:00:00 2001 From: Ty Larrabee Date: Fri, 6 Dec 2019 13:24:38 -0800 Subject: [PATCH 1/3] Add path_rules to UrlMap --- products/compute/api.yaml | 433 +++++++++++++++++- products/compute/terraform.yaml | 18 +- .../url_map_traffic_director_path.tf.erb | 103 +++++ ...l_map_traffic_director_path_partial.tf.erb | 73 +++ .../resource_compute_url_map_test.go.erb | 270 +++++++++++ 5 files changed, 870 insertions(+), 27 deletions(-) create mode 100644 templates/terraform/examples/url_map_traffic_director_path.tf.erb create mode 100644 templates/terraform/examples/url_map_traffic_director_path_partial.tf.erb diff --git a/products/compute/api.yaml b/products/compute/api.yaml index 0884d2c2976e..9edd64671d48 100644 --- a/products/compute/api.yaml +++ b/products/compute/api.yaml @@ -11711,29 +11711,6 @@ objects: description: | An optional description of this resource. Provide this property when you create the resource. - - !ruby/object:Api::Type::Array - name: 'pathRules' - description: 'The list of path rules.' - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::Array - name: 'paths' - required: true - item_type: Api::Type::String - description: | - The list of path patterns to match. Each must start with / - and the only place a * is allowed is at the end following - a /. The string fed to the path matcher does not include - any text after the first ? or #, and those chars are not - allowed here. - - !ruby/object:Api::Type::ResourceRef - name: 'service' - required: true - resource: 'BackendService' - imports: 'selfLink' - description: | - A reference to the BackendService resource if this rule is - matched. - !ruby/object:Api::Type::NestedObject name: 'headerAction' description: | @@ -11805,6 +11782,416 @@ objects: required: true description: | The name to which this PathMatcher is referred by the HostRule. + - !ruby/object:Api::Type::Array + name: 'pathRules' + description: | + The list of path rules. Use this list instead of routeRules when routing based + on simple path matching is all that's required. The order by which path rules + are specified does not matter. Matches are always done on the longest-path-first + basis. For example: a pathRule with a path /a/b/c/* will match before /a/b/* + irrespective of the order in which those paths appear in this list. Within a + given pathMatcher, only one of pathRules or routeRules must be set. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::ResourceRef + name: 'service' + resource: 'BackendService' + imports: 'selfLink' + description: | + The backend service resource to which traffic is + directed if this rule is matched. If routeAction is additionally specified, + advanced routing actions like URL Rewrites, etc. take effect prior to sending + the request to the backend. However, if service is specified, routeAction cannot + contain any weightedBackendService s. Conversely, if routeAction specifies any + weightedBackendServices, service must not be specified. Only one of urlRedirect, + service or routeAction.weightedBackendService must be set. + - !ruby/object:Api::Type::Array + name: 'paths' + required: true + item_type: Api::Type::String + description: | + The list of path patterns to match. Each must start with / and the only place a + * is allowed is at the end following a /. The string fed to the path matcher + does not include any text after the first ? or #, and those chars are not + allowed here. + - !ruby/object:Api::Type::NestedObject + name: 'routeAction' + description: | + In response to a matching path, the load balancer performs advanced routing + actions like URL rewrites, header transformations, etc. prior to forwarding the + request to the selected backend. If routeAction specifies any + weightedBackendServices, service must not be set. Conversely if service is set, + routeAction cannot contain any weightedBackendServices. Only one of routeAction + or urlRedirect must be set. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'corsPolicy' + description: | + The specification for allowing client side cross-origin requests. Please see W3C + Recommendation for Cross Origin Resource Sharing + properties: + - !ruby/object:Api::Type::Boolean + name: 'allowCredentials' + default_value: false + description: | + In response to a preflight request, setting this to true indicates that the + actual request can include user credentials. This translates to the Access- + Control-Allow-Credentials header. Defaults to false. + - !ruby/object:Api::Type::Array + name: 'allowHeaders' + item_type: Api::Type::String + description: | + Specifies the content for the Access-Control-Allow-Headers header. + - !ruby/object:Api::Type::Array + name: 'allowMethods' + item_type: Api::Type::String + description: | + Specifies the content for the Access-Control-Allow-Methods header. + - !ruby/object:Api::Type::Array + name: 'allowOriginRegexes' + item_type: Api::Type::String + description: | + Specifies the regualar expression patterns that match allowed origins. For + regular expression grammar please see en.cppreference.com/w/cpp/regex/ecmascript + An origin is allowed if it matches either allow_origins or allow_origin_regex. + - !ruby/object:Api::Type::Array + name: 'allowOrigins' + item_type: Api::Type::String + description: | + Specifies the list of origins that will be allowed to do CORS requests. An + origin is allowed if it matches either allow_origins or allow_origin_regex. + - !ruby/object:Api::Type::Boolean + name: 'disabled' + required: true + description: | + If true, specifies the CORS policy is disabled. + - !ruby/object:Api::Type::Array + name: 'exposeHeaders' + item_type: Api::Type::String + description: | + Specifies the content for the Access-Control-Expose-Headers header. + - !ruby/object:Api::Type::Integer + name: 'maxAge' + description: | + Specifies how long the results of a preflight request can be cached. This + translates to the content for the Access-Control-Max-Age header. + - !ruby/object:Api::Type::NestedObject + name: 'faultInjectionPolicy' + description: | + The specification for fault injection introduced into traffic to test the + resiliency of clients to backend service failure. As part of fault injection, + when clients send requests to a backend service, delays can be introduced by + Loadbalancer on a percentage of requests before sending those request to the + backend service. Similarly requests from clients can be aborted by the + Loadbalancer for a percentage of requests. timeout and retry_policy will be + ignored by clients that are configured with a fault_injection_policy. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'abort' + description: | + The specification for how client requests are aborted as part of fault + injection. + properties: + - !ruby/object:Api::Type::Integer + name: 'httpStatus' + required: true + description: | + The HTTP status code used to abort the request. The value must be between 200 + and 599 inclusive. + - !ruby/object:Api::Type::Double + name: 'percentage' + required: true + description: | + The percentage of traffic (connections/operations/requests) which will be + aborted as part of fault injection. The value must be between 0.0 and 100.0 + inclusive. + - !ruby/object:Api::Type::NestedObject + name: 'delay' + description: | + The specification for how client requests are delayed as part of fault + injection, before being sent to a backend service. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'fixedDelay' + required: true + description: | + Specifies the value of the fixed delay interval. + properties: + - !ruby/object:Api::Type::Integer + name: 'nanos' + description: | + Span of time that's a fraction of a second at nanosecond resolution. Durations + less than one second are represented with a 0 `seconds` field and a positive + `nanos` field. Must be from 0 to 999,999,999 inclusive. + - !ruby/object:Api::Type::String + name: 'seconds' + required: true + description: | + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + - !ruby/object:Api::Type::Double + name: 'percentage' + required: true + description: | + The percentage of traffic (connections/operations/requests) on which delay will + be introduced as part of fault injection. The value must be between 0.0 and + 100.0 inclusive. + - !ruby/object:Api::Type::NestedObject + name: 'requestMirrorPolicy' + description: | + Specifies the policy on how requests intended for the route's backends are + shadowed to a separate mirrored backend service. Loadbalancer does not wait for + responses from the shadow service. Prior to sending traffic to the shadow + service, the host / authority header is suffixed with -shadow. + properties: + - !ruby/object:Api::Type::ResourceRef + name: 'backendService' + required: true + resource: 'BackendService' + imports: 'selfLink' + description: | + The BackendService resource being mirrored to. + - !ruby/object:Api::Type::NestedObject + name: 'retryPolicy' + description: | + Specifies the retry policy associated with this route. + properties: + - !ruby/object:Api::Type::Integer + name: 'numRetries' + description: | + Specifies the allowed number retries. This number must be > 0. + - !ruby/object:Api::Type::NestedObject + name: 'perTryTimeout' + description: | + Specifies a non-zero timeout per retry attempt. + properties: + - !ruby/object:Api::Type::Integer + name: 'nanos' + description: | + Span of time that's a fraction of a second at nanosecond resolution. Durations + less than one second are represented with a 0 `seconds` field and a positive + `nanos` field. Must be from 0 to 999,999,999 inclusive. + - !ruby/object:Api::Type::String + name: 'seconds' + required: true + description: | + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + - !ruby/object:Api::Type::Array + name: 'retryConditions' + item_type: Api::Type::String + description: | + Specfies one or more conditions when this retry rule applies. Valid values are: + - 5xx: Loadbalancer will attempt a retry if the backend service responds with + any 5xx response code, or if the backend service does not respond at all, + example: disconnects, reset, read timeout, connection failure, and refused + streams. + - gateway-error: Similar to 5xx, but only applies to response codes + 502, 503 or 504. + - connect-failure: Loadbalancer will retry on failures + connecting to backend services, for example due to connection timeouts. + - retriable-4xx: Loadbalancer will retry for retriable 4xx response codes. + Currently the only retriable error supported is 409. + - refused-stream: Loadbalancer will retry if the backend service resets the stream with a + REFUSED_STREAM error code. This reset type indicates that it is safe to retry. + - cancelled: Loadbalancer will retry if the gRPC status code in the response + header is set to cancelled + - deadline-exceeded: Loadbalancer will retry if the + gRPC status code in the response header is set to deadline-exceeded + - resource-exhausted: Loadbalancer will retry if the gRPC status code in the response + header is set to resource-exhausted + - unavailable: Loadbalancer will retry if + the gRPC status code in the response header is set to unavailable + - !ruby/object:Api::Type::NestedObject + name: 'timeout' + description: | + Specifies the timeout for the selected route. Timeout is computed from the time + the request is has been fully processed (i.e. end-of-stream) up until the + response has been completely processed. Timeout includes all retries. If not + specified, the default value is 15 seconds. + properties: + - !ruby/object:Api::Type::Integer + name: 'nanos' + description: | + Span of time that's a fraction of a second at nanosecond resolution. Durations + less than one second are represented with a 0 `seconds` field and a positive + `nanos` field. Must be from 0 to 999,999,999 inclusive. + - !ruby/object:Api::Type::String + name: 'seconds' + required: true + description: | + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + - !ruby/object:Api::Type::NestedObject + name: 'urlRewrite' + description: | + The spec to modify the URL of the request, prior to forwarding the request to + the matched service + properties: + - !ruby/object:Api::Type::String + name: 'hostRewrite' + description: | + Prior to forwarding the request to the selected service, the request's host + header is replaced with contents of hostRewrite. The value must be between 1 and + 255 characters. + - !ruby/object:Api::Type::String + name: 'pathPrefixRewrite' + description: | + Prior to forwarding the request to the selected backend service, the matching + portion of the request's path is replaced by pathPrefixRewrite. The value must + be between 1 and 1024 characters. + - !ruby/object:Api::Type::Array + name: 'weightedBackendServices' + description: | + A list of weighted backend services to send traffic to when a route match + occurs. The weights determine the fraction of traffic that flows to their + corresponding backend service. If all traffic needs to go to a single backend + service, there must be one weightedBackendService with weight set to a non 0 + number. Once a backendService is identified and before forwarding the request to + the backend service, advanced routing actions like Url rewrites and header + transformations are applied depending on additional settings specified in this + HttpRouteAction. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::ResourceRef + name: 'backendService' + required: true + resource: 'BackendService' + imports: 'selfLink' + description: | + The default BackendService resource. Before + forwarding the request to backendService, the loadbalancer applies any relevant + headerActions specified as part of this backendServiceWeight. + - !ruby/object:Api::Type::NestedObject + name: 'headerAction' + description: | + Specifies changes to request and response headers that need to take effect for + the selected backendService. headerAction specified here take effect before + headerAction in the enclosing HttpRouteRule, PathMatcher and UrlMap. + properties: + - !ruby/object:Api::Type::Array + name: 'requestHeadersToAdd' + description: | + Headers to add to a matching request prior to forwarding the request to the + backendService. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'headerName' + required: true + description: | + The name of the header. + - !ruby/object:Api::Type::String + name: 'headerValue' + required: true + description: | + The value of the header to add. + - !ruby/object:Api::Type::Boolean + name: 'replace' + required: true + description: | + If false, headerValue is appended to any values that already exist for the + header. If true, headerValue is set for the header, discarding any values that + were set for that header. + - !ruby/object:Api::Type::Array + name: 'requestHeadersToRemove' + item_type: Api::Type::String + description: | + A list of header names for headers that need to be removed from the request + prior to forwarding the request to the backendService. + - !ruby/object:Api::Type::Array + name: 'responseHeadersToAdd' + description: | + Headers to add the response prior to sending the response back to the client. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'headerName' + required: true + description: | + The name of the header. + - !ruby/object:Api::Type::String + name: 'headerValue' + required: true + description: | + The value of the header to add. + - !ruby/object:Api::Type::Boolean + name: 'replace' + required: true + description: | + If false, headerValue is appended to any values that already exist for the + header. If true, headerValue is set for the header, discarding any values that + were set for that header. + - !ruby/object:Api::Type::Array + name: 'responseHeadersToRemove' + item_type: Api::Type::String + description: | + A list of header names for headers that need to be removed from the response + prior to sending the response back to the client. + - !ruby/object:Api::Type::Integer + name: 'weight' + description: | + Specifies the fraction of traffic sent to backendService, computed as weight / + (sum of all weightedBackendService weights in routeAction) . The selection of a + backend service is determined only for new traffic. Once a user's request has + been directed to a backendService, subsequent requests will be sent to the same + backendService as determined by the BackendService's session affinity policy. + The value must be between 0 and 1000 + - !ruby/object:Api::Type::NestedObject + name: 'urlRedirect' + description: | + When a path pattern is matched, the request is redirected to a URL specified by + urlRedirect. If urlRedirect is specified, service or routeAction must not be + set. + properties: + - !ruby/object:Api::Type::String + name: 'hostRedirect' + description: | + The host that will be used in the redirect response instead of the one that was + supplied in the request. The value must be between 1 and 255 characters. + - !ruby/object:Api::Type::Boolean + name: 'httpsRedirect' + default_value: false + description: | + If set to true, the URL scheme in the redirected request is set to https. If set + to false, the URL scheme of the redirected request will remain the same as that + of the request. This must only be set for UrlMaps used in TargetHttpProxys. + Setting this true for TargetHttpsProxy is not permitted. Defaults to false. + - !ruby/object:Api::Type::String + name: 'pathRedirect' + description: | + The path that will be used in the redirect response instead of the one that was + supplied in the request. Only one of pathRedirect or prefixRedirect must be + specified. The value must be between 1 and 1024 characters. + - !ruby/object:Api::Type::String + name: 'prefixRedirect' + description: | + The prefix that replaces the prefixMatch specified in the HttpRouteRuleMatch, + retaining the remaining portion of the URL before redirecting the request. + - !ruby/object:Api::Type::Enum + name: 'redirectResponseCode' + description: | + The HTTP Status code to use for this RedirectAction. Supported values are: + - MOVED_PERMANENTLY_DEFAULT, which is the default value and corresponds to 301. + - FOUND, which corresponds to 302. + - SEE_OTHER which corresponds to 303. + - TEMPORARY_REDIRECT, which corresponds to 307. In this case, the request method + will be retained. + - PERMANENT_REDIRECT, which corresponds to 308. In this case, + the request method will be retained. + values: + - :FOUND + - :MOVED_PERMANENTLY_DEFAULT + - :PERMANENT_REDIRECT + - :SEE_OTHER + - :TEMPORARY_REDIRECT + - !ruby/object:Api::Type::Boolean + name: 'stripQuery' + required: true + description: | + If set to true, any accompanying query portion of the original URL is removed + prior to redirecting the request. If set to false, the query portion of the + original URL is retained. - !ruby/object:Api::Type::Array name: 'routeRules' description: | diff --git a/products/compute/terraform.yaml b/products/compute/terraform.yaml index ee51b4a48a23..636d1f2fe75a 100644 --- a/products/compute/terraform.yaml +++ b/products/compute/terraform.yaml @@ -1988,8 +1988,6 @@ overrides: !ruby/object:Overrides::ResourceOverrides url_map_name: "urlmap" home_backend_service_name: "home" health_check_name: "health-check" - backend_bucket_name: "static-asset-backend-bucket" - storage_bucket_name: "static-asset-bucket" - !ruby/object:Provider::Terraform::Examples name: "url_map_traffic_director_route_partial" primary_resource_id: "urlmap" @@ -1997,8 +1995,20 @@ overrides: !ruby/object:Overrides::ResourceOverrides url_map_name: "urlmap" home_backend_service_name: "home" health_check_name: "health-check" - backend_bucket_name: "static-asset-backend-bucket" - storage_bucket_name: "static-asset-bucket" + - !ruby/object:Provider::Terraform::Examples + name: "url_map_traffic_director_path" + primary_resource_id: "urlmap" + vars: + url_map_name: "urlmap" + home_backend_service_name: "home" + health_check_name: "health-check" + - !ruby/object:Provider::Terraform::Examples + name: "url_map_traffic_director_path_partial" + primary_resource_id: "urlmap" + vars: + url_map_name: "urlmap" + home_backend_service_name: "home" + health_check_name: "health-check" properties: id: !ruby/object:Overrides::Terraform::PropertyOverride name: "map_id" diff --git a/templates/terraform/examples/url_map_traffic_director_path.tf.erb b/templates/terraform/examples/url_map_traffic_director_path.tf.erb new file mode 100644 index 000000000000..c034a77921a4 --- /dev/null +++ b/templates/terraform/examples/url_map_traffic_director_path.tf.erb @@ -0,0 +1,103 @@ +resource "google_compute_url_map" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['url_map_name'] %>" + 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 = false + } + 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 = "A replacement header" + path_prefix_rewrite = "A replacement path" + } + 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 = "<%= ctx[:vars]['home_backend_service_name'] %>" + 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 = "<%= ctx[:vars]['health_check_name'] %>" + http_health_check { + port = 80 + } +} diff --git a/templates/terraform/examples/url_map_traffic_director_path_partial.tf.erb b/templates/terraform/examples/url_map_traffic_director_path_partial.tf.erb new file mode 100644 index 000000000000..5bdfffee9e09 --- /dev/null +++ b/templates/terraform/examples/url_map_traffic_director_path_partial.tf.erb @@ -0,0 +1,73 @@ +resource "google_compute_url_map" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['url_map_name'] %>" + 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 = false + } + 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 = "<%= ctx[:vars]['home_backend_service_name'] %>" + 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 = "<%= ctx[:vars]['health_check_name'] %>" + http_health_check { + port = 80 + } +} + diff --git a/third_party/terraform/tests/resource_compute_url_map_test.go.erb b/third_party/terraform/tests/resource_compute_url_map_test.go.erb index 414b5837ce41..7d20134bffe9 100644 --- a/third_party/terraform/tests/resource_compute_url_map_test.go.erb +++ b/third_party/terraform/tests/resource_compute_url_map_test.go.erb @@ -156,6 +156,39 @@ func TestAccComputeUrlMap_trafficDirectorUpdate(t *testing.T) { }) } +func TestAccComputeUrlMap_trafficDirectorPathUpdate(t *testing.T) { + t.Parallel() + + randString := acctest.RandString(10) + + bsName := fmt.Sprintf("urlmap-test-%s", randString) + hcName := fmt.Sprintf("urlmap-test-%s", randString) + umName := fmt.Sprintf("urlmap-test-%s", randString) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeUrlMapDestroy, + 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() @@ -672,3 +705,240 @@ resource "google_compute_health_check" "default" { } `, 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 = "A replacement header" + path_prefix_rewrite = "A replacement path" + } + 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 = "A replacement header updated" + path_prefix_rewrite = "A replacement path 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) +} From 3eadb82dc36508bf31fb8cc4663ab78d5ba84128 Mon Sep 17 00:00:00 2001 From: Ty Larrabee Date: Mon, 9 Dec 2019 11:50:46 -0800 Subject: [PATCH 2/3] Make weight required --- products/compute/api.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/products/compute/api.yaml b/products/compute/api.yaml index 9edd64671d48..c92656ffcf48 100644 --- a/products/compute/api.yaml +++ b/products/compute/api.yaml @@ -12130,6 +12130,7 @@ objects: prior to sending the response back to the client. - !ruby/object:Api::Type::Integer name: 'weight' + required: true description: | Specifies the fraction of traffic sent to backendService, computed as weight / (sum of all weightedBackendService weights in routeAction) . The selection of a From a8c598038398f20acb9a3df7615277e8ba4c9d3a Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Mon, 9 Dec 2019 19:59:25 +0000 Subject: [PATCH 3/3] Update tracked submodules -> HEAD on Mon Dec 9 19:59:25 UTC 2019 Tracked submodules are build/terraform-beta build/terraform-mapper build/terraform build/ansible build/inspec. --- build/ansible | 2 +- build/inspec | 2 +- build/terraform | 2 +- build/terraform-beta | 2 +- build/terraform-mapper | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/ansible b/build/ansible index 561dddd734b7..4809c7f26ba6 160000 --- a/build/ansible +++ b/build/ansible @@ -1 +1 @@ -Subproject commit 561dddd734b758a02b6d018c1e4a42150d7f04c5 +Subproject commit 4809c7f26ba636b2c52a81e295b16ba8174ec49b diff --git a/build/inspec b/build/inspec index afd143c24ebc..7ff4744d93ba 160000 --- a/build/inspec +++ b/build/inspec @@ -1 +1 @@ -Subproject commit afd143c24ebc714729a9ede884cdf0ae8e2be45e +Subproject commit 7ff4744d93ba3732dca9de58e83784b97c1c60c7 diff --git a/build/terraform b/build/terraform index a391fe5f9ee7..dee259056f28 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit a391fe5f9ee79c8c9927015cff01b847e63366ca +Subproject commit dee259056f2872b18b268c41fa1723131469a493 diff --git a/build/terraform-beta b/build/terraform-beta index 67751699470b..6abcaa12cd87 160000 --- a/build/terraform-beta +++ b/build/terraform-beta @@ -1 +1 @@ -Subproject commit 67751699470b7f8ee1e61be76da1036c30e114d0 +Subproject commit 6abcaa12cd875435a6820bacd0740dc2601b983e diff --git a/build/terraform-mapper b/build/terraform-mapper index daa9a44fb16f..faa52548d023 160000 --- a/build/terraform-mapper +++ b/build/terraform-mapper @@ -1 +1 @@ -Subproject commit daa9a44fb16f74f116d633a57e92f24cce7c37a5 +Subproject commit faa52548d02395d47daae1d7204dc78d07914a91