From dee259056f2872b18b268c41fa1723131469a493 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 9 Dec 2019 11:55:57 -0800 Subject: [PATCH] Add path_rules to UrlMap (#5106) Signed-off-by: Modular Magician --- google/resource_compute_url_map.go | 5562 +++++++++++------ ...resource_compute_url_map_generated_test.go | 233 + google/resource_compute_url_map_test.go | 270 + website/docs/r/compute_url_map.html.markdown | 580 +- 4 files changed, 4712 insertions(+), 1933 deletions(-) diff --git a/google/resource_compute_url_map.go b/google/resource_compute_url_map.go index ee62879e772..97409b37d1d 100644 --- a/google/resource_compute_url_map.go +++ b/google/resource_compute_url_map.go @@ -267,810 +267,477 @@ prior to sending the response back to the client.`, }, }, "path_rule": { - Type: schema.TypeList, - Optional: true, - Description: `The list of path rules.`, + Type: schema.TypeList, + Optional: true, + 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.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "paths": { Type: schema.TypeSet, Required: true, - 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 + 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.`, Elem: &schema.Schema{ Type: schema.TypeString, }, Set: schema.HashString, }, - "service": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The backend service or backend bucket to use if any of the given paths match.`, - }, - }, - }, - }, - "route_rules": { - Type: schema.TypeList, - Optional: true, - Description: `The list of ordered HTTP route rules. Use this list instead of pathRules when -advanced route matching and routing actions are desired. The order of specifying -routeRules matters: the first rule that matches will cause its specified routing -action to take effect. Within a given pathMatcher, only one of pathRules or -routeRules must be set. routeRules are not supported in UrlMaps intended for -External load balancers.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "priority": { - Type: schema.TypeInt, - Required: true, - Description: `For routeRules within a given pathMatcher, priority determines the order -in which load balancer will interpret routeRules. RouteRules are evaluated -in order of priority, from the lowest to highest number. The priority of -a rule decreases as its number increases (1, 2, 3, N+1). The first rule -that matches the request is applied. - -You cannot configure two or more routeRules with the same priority. -Priority for each rule must be set to a number between 0 and -2147483647 inclusive. - -Priority numbers can have gaps, which enable you to add or remove rules -in the future without affecting the rest of the rules. For example, -1, 2, 3, 4, 5, 9, 12, 16 is a valid series of priority numbers to which -you could add rules numbered from 6 to 8, 10 to 11, and 13 to 15 in the -future without any impact on existing rules.`, - }, - "header_action": { + "route_action": { Type: schema.TypeList, Optional: true, - Description: `Specifies changes to request and response headers that need to take effect for -the selected backendService. The headerAction specified here are applied before -the matching pathMatchers[].headerAction and after pathMatchers[].routeRules[].r -outeAction.weightedBackendService.backendServiceWeightAction[].headerAction`, + 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.`, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "request_headers_to_add": { + "cors_policy": { Type: schema.TypeList, Optional: true, - Description: `Headers to add to a matching request prior to forwarding the request to the -backendService.`, + Description: `The specification for allowing client side cross-origin requests. Please see W3C +Recommendation for Cross Origin Resource Sharing`, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "header_name": { - Type: schema.TypeString, - Required: true, - Description: `The name of the header.`, - }, - "header_value": { - Type: schema.TypeString, + "disabled": { + Type: schema.TypeBool, Required: true, - Description: `The value of the header to add.`, + Description: `If true, specifies the CORS policy is disabled.`, }, - "replace": { + "allow_credentials": { Type: schema.TypeBool, - 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.`, + Optional: true, + 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.`, + Default: false, }, - }, - }, - }, - "request_headers_to_remove": { - Type: schema.TypeList, - Optional: true, - Description: `A list of header names for headers that need to be removed from the request -prior to forwarding the request to the backendService.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "response_headers_to_add": { - Type: schema.TypeList, - Optional: true, - Description: `Headers to add the response prior to sending the response back to the client.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "header_name": { - Type: schema.TypeString, - Required: true, - Description: `The name of the header.`, + "allow_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Allow-Headers header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - "header_value": { - Type: schema.TypeString, - Required: true, - Description: `The value of the header to add.`, + "allow_methods": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Allow-Methods header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - "replace": { - Type: schema.TypeBool, - 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.`, + "allow_origin_regexes": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "allow_origins": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "expose_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Expose-Headers header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "max_age": { + Type: schema.TypeInt, + Optional: true, + 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.`, }, }, }, }, - "response_headers_to_remove": { - Type: schema.TypeList, - Optional: true, - 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.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "match_rules": { - Type: schema.TypeList, - Optional: true, - Description: `The rules for determining a match.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "full_path_match": { - Type: schema.TypeString, - Optional: true, - Description: `For satifying the matchRule condition, the path of the request must exactly -match the value specified in fullPathMatch after removing any query parameters -and anchor that may be part of the original URL. FullPathMatch must be between 1 -and 1024 characters. Only one of prefixMatch, fullPathMatch or regexMatch must -be specified.`, - }, - "header_matches": { + "fault_injection_policy": { Type: schema.TypeList, Optional: true, - Description: `Specifies a list of header match criteria, all of which must match corresponding -headers in the request.`, + 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.`, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "header_name": { - Type: schema.TypeString, - Required: true, - Description: `The name of the HTTP header to match. For matching against the HTTP request's -authority, use a headerMatch with the header name ":authority". For matching a -request's method, use the headerName ":method".`, - }, - "exact_match": { - Type: schema.TypeString, - Optional: true, - Description: `The value should exactly match contents of exactMatch. Only one of exactMatch, -prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch must be set.`, - }, - "invert_match": { - Type: schema.TypeBool, - Optional: true, - Description: `If set to false, the headerMatch is considered a match if the match criteria -above are met. If set to true, the headerMatch is considered a match if the -match criteria above are NOT met. Defaults to false.`, - Default: false, - }, - "prefix_match": { - Type: schema.TypeString, - Optional: true, - Description: `The value of the header must start with the contents of prefixMatch. Only one of -exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch -must be set.`, - }, - "present_match": { - Type: schema.TypeBool, - Optional: true, - Description: `A header with the contents of headerName must exist. The match takes place -whether or not the request's header has a value or not. Only one of exactMatch, -prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch must be set.`, - }, - "range_match": { + "abort": { Type: schema.TypeList, Optional: true, - Description: `The header value must be an integer and its value must be in the range specified -in rangeMatch. If the header does not contain an integer, number or is empty, -the match fails. For example for a range [-5, 0] - -3 will match. - 0 will -not match. - 0.25 will not match. - -3someString will not match. Only one of -exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch -must be set.`, + Description: `The specification for how client requests are aborted as part of fault +injection.`, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "range_end": { - Type: schema.TypeInt, - Required: true, - Description: `The end of the range (exclusive).`, - }, - "range_start": { - Type: schema.TypeInt, - Required: true, - Description: `The start of the range (inclusive).`, + "http_status": { + Type: schema.TypeInt, + Required: true, + Description: `The HTTP status code used to abort the request. The value must be between 200 +and 599 inclusive.`, }, - }, + "percentage": { + Type: schema.TypeFloat, + 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.`, + }, + }, }, }, - "regex_match": { - Type: schema.TypeString, - Optional: true, - Description: `The value of the header must match the regualar expression specified in -regexMatch. For regular expression grammar, please see: -en.cppreference.com/w/cpp/regex/ecmascript For matching against a port -specified in the HTTP request, use a headerMatch with headerName set to PORT and -a regular expression that satisfies the RFC2616 Host header's port specifier. -Only one of exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or -rangeMatch must be set.`, - }, - "suffix_match": { - Type: schema.TypeString, + "delay": { + Type: schema.TypeList, Optional: true, - Description: `The value of the header must end with the contents of suffixMatch. Only one of -exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch -must be set.`, + Description: `The specification for how client requests are delayed as part of fault +injection, before being sent to a backend service.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "fixed_delay": { + Type: schema.TypeList, + Required: true, + Description: `Specifies the value of the fixed delay interval.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeString, + Required: true, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + 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.`, + }, + }, + }, + }, + "percentage": { + Type: schema.TypeFloat, + 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.`, + }, + }, + }, }, }, }, }, - "ignore_case": { - Type: schema.TypeBool, - Optional: true, - Description: `Specifies that prefixMatch and fullPathMatch matches are case sensitive. -Defaults to false.`, - Default: false, - }, - "metadata_filters": { + "request_mirror_policy": { Type: schema.TypeList, Optional: true, - Description: `Opaque filter criteria used by Loadbalancer to restrict routing configuration to -a limited set xDS compliant clients. In their xDS requests to Loadbalancer, xDS -clients present node metadata. If a match takes place, the relevant routing -configuration is made available to those proxies. For each metadataFilter in -this list, if its filterMatchCriteria is set to MATCH_ANY, at least one of the -filterLabels must match the corresponding label provided in the metadata. If its -filterMatchCriteria is set to MATCH_ALL, then all of its filterLabels must match -with corresponding labels in the provided metadata. metadataFilters specified -here can be overrides those specified in ForwardingRule that refers to this -UrlMap. metadataFilters only applies to Loadbalancers that have their -loadBalancingScheme set to INTERNAL_SELF_MANAGED.`, + 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.`, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "filter_labels": { - Type: schema.TypeList, - Required: true, - Description: `The list of label value pairs that must match labels in the provided metadata -based on filterMatchCriteria This list must not be empty and can have at the -most 64 entries.`, - MinItems: 1, - MaxItems: 64, + "backend_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The BackendService resource being mirrored to.`, + }, + }, + }, + }, + "retry_policy": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the retry policy associated with this route.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_retries": { + Type: schema.TypeInt, + Optional: true, + Description: `Specifies the allowed number retries. This number must be > 0.`, + }, + "per_try_timeout": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies a non-zero timeout per retry attempt.`, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { + "seconds": { Type: schema.TypeString, Required: true, - Description: `Name of metadata label. The name can have a maximum length of 1024 characters -and must be at least 1 character long.`, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, }, - "value": { - Type: schema.TypeString, - Required: true, - Description: `The value of the label must match the specified value. value can have a maximum -length of 1024 characters.`, + "nanos": { + Type: schema.TypeInt, + Optional: true, + 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.`, }, }, }, }, - "filter_match_criteria": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{"MATCH_ALL", "MATCH_ANY"}, false), - Description: `Specifies how individual filterLabel matches within the list of filterLabels -contribute towards the overall metadataFilter match. Supported values are: - - MATCH_ANY: At least one of the filterLabels must have a matching label in the -provided metadata. - - MATCH_ALL: All filterLabels must have matching labels in -the provided metadata.`, + "retry_conditions": { + Type: schema.TypeList, + Optional: true, + 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`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, }, }, }, - "prefix_match": { - Type: schema.TypeString, - Optional: true, - Description: `For satifying the matchRule condition, the request's path must begin with the -specified prefixMatch. prefixMatch must begin with a /. The value must be -between 1 and 1024 characters. Only one of prefixMatch, fullPathMatch or -regexMatch must be specified.`, - }, - "query_parameter_matches": { + "timeout": { Type: schema.TypeList, Optional: true, - Description: `Specifies a list of query parameter match criteria, all of which must match -corresponding query parameters in the request.`, + 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.`, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { + "seconds": { Type: schema.TypeString, Required: true, - Description: `The name of the query parameter to match. The query parameter must exist in the -request, in the absence of which the request match fails.`, - }, - "exact_match": { - Type: schema.TypeString, - Optional: true, - Description: `The queryParameterMatch matches if the value of the parameter exactly matches -the contents of exactMatch. Only one of presentMatch, exactMatch and regexMatch -must be set.`, - }, - "present_match": { - Type: schema.TypeBool, - Optional: true, - Description: `Specifies that the queryParameterMatch matches if the request contains the query -parameter, irrespective of whether the parameter has a value or not. Only one of -presentMatch, exactMatch and regexMatch must be set.`, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, }, - "regex_match": { - Type: schema.TypeString, + "nanos": { + Type: schema.TypeInt, Optional: true, - Description: `The queryParameterMatch matches if the value of the parameter matches the -regular expression specified by regexMatch. For the regular expression grammar, -please see en.cppreference.com/w/cpp/regex/ecmascript Only one of presentMatch, -exactMatch and regexMatch must be set.`, + 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.`, }, }, }, }, - "regex_match": { - Type: schema.TypeString, - Optional: true, - Description: `For satifying the matchRule condition, the path of the request must satisfy the -regular expression specified in regexMatch after removing any query parameters -and anchor supplied with the original URL. For regular expression grammar please -see en.cppreference.com/w/cpp/regex/ecmascript Only one of prefixMatch, -fullPathMatch or regexMatch must be specified.`, - }, - }, - }, - }, - "route_action": { - Type: schema.TypeList, - Optional: true, - Description: `In response to a matching matchRule, 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.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cors_policy": { + "url_rewrite": { Type: schema.TypeList, Optional: true, - Description: `The specification for allowing client side cross-origin requests. Please see W3C -Recommendation for Cross Origin Resource Sharing`, + Description: `The spec to modify the URL of the request, prior to forwarding the request to +the matched service`, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "allow_credentials": { - Type: schema.TypeBool, + "host_rewrite": { + Type: schema.TypeString, Optional: true, - 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.`, - Default: false, + 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.`, }, - "allow_headers": { - Type: schema.TypeList, - Optional: true, - Description: `Specifies the content for the Access-Control-Allow-Headers header.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "allow_methods": { - Type: schema.TypeList, - Optional: true, - Description: `Specifies the content for the Access-Control-Allow-Methods header.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "allow_origin_regexes": { - Type: schema.TypeList, - Optional: true, - 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.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "allow_origins": { - Type: schema.TypeList, - Optional: true, - 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.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "disabled": { - Type: schema.TypeBool, - Optional: true, - Description: `If true, specifies the CORS policy is disabled. -which indicates that the CORS policy is in effect. Defaults to false.`, - Default: false, - }, - "expose_headers": { - Type: schema.TypeList, - Optional: true, - Description: `Specifies the content for the Access-Control-Expose-Headers header.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "max_age": { - Type: schema.TypeInt, + "path_prefix_rewrite": { + Type: schema.TypeString, Optional: true, - 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.`, + 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.`, }, }, }, }, - "fault_injection_policy": { + "weighted_backend_services": { Type: schema.TypeList, Optional: true, - 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.`, - MaxItems: 1, + 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.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "abort": { + "backend_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The default BackendService resource. Before +forwarding the request to backendService, the loadbalancer applies any relevant +headerActions specified as part of this backendServiceWeight.`, + }, + "header_action": { Type: schema.TypeList, Optional: true, - Description: `The specification for how client requests are aborted as part of fault -injection.`, + 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.`, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "http_status": { - Type: schema.TypeInt, + "request_headers_to_add": { + Type: schema.TypeList, Optional: true, - Description: `The HTTP status code used to abort the request. The value must be between 200 -and 599 inclusive.`, + Description: `Headers to add to a matching request prior to forwarding the request to the +backendService.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, + }, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, + }, + }, + }, }, - "percentage": { - Type: schema.TypeFloat, + "request_headers_to_remove": { + Type: schema.TypeList, Optional: 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.`, + Description: `A list of header names for headers that need to be removed from the request +prior to forwarding the request to the backendService.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - }, - }, - }, - "delay": { - Type: schema.TypeList, - Optional: true, - Description: `The specification for how client requests are delayed as part of fault -injection, before being sent to a backend service.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fixed_delay": { + "response_headers_to_add": { Type: schema.TypeList, Optional: true, - Description: `Specifies the value of the fixed delay interval.`, - MaxItems: 1, + Description: `Headers to add the response prior to sending the response back to the client.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "seconds": { - Type: schema.TypeString, - Required: true, - Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 -inclusive.`, + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, }, - "nanos": { - Type: schema.TypeInt, - Optional: true, - 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.`, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, }, }, }, }, - "percentage": { - Type: schema.TypeFloat, + "response_headers_to_remove": { + Type: schema.TypeList, Optional: 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.`, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, }, }, }, + "weight": { + Type: schema.TypeInt, + Optional: true, + 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`, + }, }, }, }, - "request_mirror_policy": { - Type: schema.TypeList, + }, + }, + }, + "service": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The backend service or backend bucket to use if any of the given paths match.`, + }, + "url_redirect": { + Type: schema.TypeList, + Optional: true, + 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "strip_query": { + Type: schema.TypeBool, + 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.`, + }, + "host_redirect": { + Type: schema.TypeString, Optional: true, - 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.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "backend_service": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The BackendService resource being mirrored to.`, - }, - }, - }, - }, - "retry_policy": { - Type: schema.TypeList, - Optional: true, - Description: `Specifies the retry policy associated with this route.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "num_retries": { - Type: schema.TypeInt, - Required: true, - Description: `Specifies the allowed number retries. This number must be > 0.`, - }, - "per_try_timeout": { - Type: schema.TypeList, - Optional: true, - Description: `Specifies a non-zero timeout per retry attempt. -If not specified, will use the timeout set in HttpRouteAction. If timeout in HttpRouteAction -is not set, will use the largest timeout among all backend services associated with the route.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "seconds": { - Type: schema.TypeString, - Required: true, - Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 -inclusive.`, - }, - "nanos": { - Type: schema.TypeInt, - Optional: true, - 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.`, - }, - }, - }, - }, - "retry_conditions": { - Type: schema.TypeList, - Optional: true, - 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`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "timeout": { - Type: schema.TypeList, - Optional: true, - 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.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "seconds": { - Type: schema.TypeString, - Required: true, - Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 -inclusive.`, - }, - "nanos": { - Type: schema.TypeInt, - Optional: true, - 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.`, - }, - }, - }, - }, - "url_rewrite": { - Type: schema.TypeList, - Optional: true, - Description: `The spec to modify the URL of the request, prior to forwarding the request to -the matched service`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "host_rewrite": { - Type: schema.TypeString, - Optional: true, - 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.`, - }, - "path_prefix_rewrite": { - Type: schema.TypeString, - Optional: true, - 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.`, - }, - }, - }, - }, - "weighted_backend_services": { - Type: schema.TypeList, - Optional: true, - 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.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "backend_service": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The default BackendService resource. Before -forwarding the request to backendService, the loadbalancer applies any relevant -headerActions specified as part of this backendServiceWeight.`, - }, - "header_action": { - Type: schema.TypeList, - Optional: true, - 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.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "request_headers_to_add": { - Type: schema.TypeList, - Optional: true, - Description: `Headers to add to a matching request prior to forwarding the request to the -backendService.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "header_name": { - Type: schema.TypeString, - Required: true, - Description: `The name of the header.`, - }, - "header_value": { - Type: schema.TypeString, - Required: true, - Description: `The value of the header to add.`, - }, - "replace": { - Type: schema.TypeBool, - 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.`, - }, - }, - }, - }, - "request_headers_to_remove": { - Type: schema.TypeList, - Optional: true, - Description: `A list of header names for headers that need to be removed from the request -prior to forwarding the request to the backendService.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "response_headers_to_add": { - Type: schema.TypeList, - Optional: true, - Description: `Headers to add the response prior to sending the response back to the client.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "header_name": { - Type: schema.TypeString, - Required: true, - Description: `The name of the header.`, - }, - "header_value": { - Type: schema.TypeString, - Required: true, - Description: `The value of the header to add.`, - }, - "replace": { - Type: schema.TypeBool, - 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.`, - }, - }, - }, - }, - "response_headers_to_remove": { - Type: schema.TypeList, - Optional: true, - 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.`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "weight": { - Type: schema.TypeInt, - Optional: true, - 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`, - }, - }, - }, - }, - }, - }, - }, - "url_redirect": { - Type: schema.TypeList, - Optional: true, - Description: `When this rule is matched, the request is redirected to a URL specified by -urlRedirect. If urlRedirect is specified, service or routeAction must not be -set.`, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "host_redirect": { - Type: schema.TypeString, - Optional: true, - 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.`, + 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.`, }, "https_redirect": { Type: schema.TypeBool, @@ -1098,37 +765,856 @@ retaining the remaining portion of the URL before redirecting the request.`, Type: schema.TypeString, Optional: true, ValidateFunc: validation.StringInSlice([]string{"FOUND", "MOVED_PERMANENTLY_DEFAULT", "PERMANENT_REDIRECT", "SEE_OTHER", "TEMPORARY_REDIRECT", ""}, false), - 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, + 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.`, }, - "strip_query": { - Type: schema.TypeBool, - Optional: 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. Defaults to false.`, - Default: false, - }, }, }, }, }, }, }, - }, - }, - }, - "test": { - Type: schema.TypeList, - Optional: true, - Description: `The list of expected URL mapping tests. Request to update this UrlMap will -succeed only if all of the test cases pass. You can specify a maximum of 100 -tests per UrlMap.`, - Elem: &schema.Resource{ + "route_rules": { + Type: schema.TypeList, + Optional: true, + Description: `The list of ordered HTTP route rules. Use this list instead of pathRules when +advanced route matching and routing actions are desired. The order of specifying +routeRules matters: the first rule that matches will cause its specified routing +action to take effect. Within a given pathMatcher, only one of pathRules or +routeRules must be set. routeRules are not supported in UrlMaps intended for +External load balancers.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "priority": { + Type: schema.TypeInt, + Required: true, + Description: `For routeRules within a given pathMatcher, priority determines the order +in which load balancer will interpret routeRules. RouteRules are evaluated +in order of priority, from the lowest to highest number. The priority of +a rule decreases as its number increases (1, 2, 3, N+1). The first rule +that matches the request is applied. + +You cannot configure two or more routeRules with the same priority. +Priority for each rule must be set to a number between 0 and +2147483647 inclusive. + +Priority numbers can have gaps, which enable you to add or remove rules +in the future without affecting the rest of the rules. For example, +1, 2, 3, 4, 5, 9, 12, 16 is a valid series of priority numbers to which +you could add rules numbered from 6 to 8, 10 to 11, and 13 to 15 in the +future without any impact on existing rules.`, + }, + "header_action": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies changes to request and response headers that need to take effect for +the selected backendService. The headerAction specified here are applied before +the matching pathMatchers[].headerAction and after pathMatchers[].routeRules[].r +outeAction.weightedBackendService.backendServiceWeightAction[].headerAction`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "request_headers_to_add": { + Type: schema.TypeList, + Optional: true, + Description: `Headers to add to a matching request prior to forwarding the request to the +backendService.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, + }, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, + }, + }, + }, + }, + "request_headers_to_remove": { + Type: schema.TypeList, + Optional: true, + Description: `A list of header names for headers that need to be removed from the request +prior to forwarding the request to the backendService.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "response_headers_to_add": { + Type: schema.TypeList, + Optional: true, + Description: `Headers to add the response prior to sending the response back to the client.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, + }, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, + }, + }, + }, + }, + "response_headers_to_remove": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "match_rules": { + Type: schema.TypeList, + Optional: true, + Description: `The rules for determining a match.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "full_path_match": { + Type: schema.TypeString, + Optional: true, + Description: `For satifying the matchRule condition, the path of the request must exactly +match the value specified in fullPathMatch after removing any query parameters +and anchor that may be part of the original URL. FullPathMatch must be between 1 +and 1024 characters. Only one of prefixMatch, fullPathMatch or regexMatch must +be specified.`, + }, + "header_matches": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies a list of header match criteria, all of which must match corresponding +headers in the request.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the HTTP header to match. For matching against the HTTP request's +authority, use a headerMatch with the header name ":authority". For matching a +request's method, use the headerName ":method".`, + }, + "exact_match": { + Type: schema.TypeString, + Optional: true, + Description: `The value should exactly match contents of exactMatch. Only one of exactMatch, +prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch must be set.`, + }, + "invert_match": { + Type: schema.TypeBool, + Optional: true, + Description: `If set to false, the headerMatch is considered a match if the match criteria +above are met. If set to true, the headerMatch is considered a match if the +match criteria above are NOT met. Defaults to false.`, + Default: false, + }, + "prefix_match": { + Type: schema.TypeString, + Optional: true, + Description: `The value of the header must start with the contents of prefixMatch. Only one of +exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch +must be set.`, + }, + "present_match": { + Type: schema.TypeBool, + Optional: true, + Description: `A header with the contents of headerName must exist. The match takes place +whether or not the request's header has a value or not. Only one of exactMatch, +prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch must be set.`, + }, + "range_match": { + Type: schema.TypeList, + Optional: true, + Description: `The header value must be an integer and its value must be in the range specified +in rangeMatch. If the header does not contain an integer, number or is empty, +the match fails. For example for a range [-5, 0] - -3 will match. - 0 will +not match. - 0.25 will not match. - -3someString will not match. Only one of +exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch +must be set.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "range_end": { + Type: schema.TypeInt, + Required: true, + Description: `The end of the range (exclusive).`, + }, + "range_start": { + Type: schema.TypeInt, + Required: true, + Description: `The start of the range (inclusive).`, + }, + }, + }, + }, + "regex_match": { + Type: schema.TypeString, + Optional: true, + Description: `The value of the header must match the regualar expression specified in +regexMatch. For regular expression grammar, please see: +en.cppreference.com/w/cpp/regex/ecmascript For matching against a port +specified in the HTTP request, use a headerMatch with headerName set to PORT and +a regular expression that satisfies the RFC2616 Host header's port specifier. +Only one of exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or +rangeMatch must be set.`, + }, + "suffix_match": { + Type: schema.TypeString, + Optional: true, + Description: `The value of the header must end with the contents of suffixMatch. Only one of +exactMatch, prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch +must be set.`, + }, + }, + }, + }, + "ignore_case": { + Type: schema.TypeBool, + Optional: true, + Description: `Specifies that prefixMatch and fullPathMatch matches are case sensitive. +Defaults to false.`, + Default: false, + }, + "metadata_filters": { + Type: schema.TypeList, + Optional: true, + Description: `Opaque filter criteria used by Loadbalancer to restrict routing configuration to +a limited set xDS compliant clients. In their xDS requests to Loadbalancer, xDS +clients present node metadata. If a match takes place, the relevant routing +configuration is made available to those proxies. For each metadataFilter in +this list, if its filterMatchCriteria is set to MATCH_ANY, at least one of the +filterLabels must match the corresponding label provided in the metadata. If its +filterMatchCriteria is set to MATCH_ALL, then all of its filterLabels must match +with corresponding labels in the provided metadata. metadataFilters specified +here can be overrides those specified in ForwardingRule that refers to this +UrlMap. metadataFilters only applies to Loadbalancers that have their +loadBalancingScheme set to INTERNAL_SELF_MANAGED.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filter_labels": { + Type: schema.TypeList, + Required: true, + Description: `The list of label value pairs that must match labels in the provided metadata +based on filterMatchCriteria This list must not be empty and can have at the +most 64 entries.`, + MinItems: 1, + MaxItems: 64, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of metadata label. The name can have a maximum length of 1024 characters +and must be at least 1 character long.`, + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the label must match the specified value. value can have a maximum +length of 1024 characters.`, + }, + }, + }, + }, + "filter_match_criteria": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"MATCH_ALL", "MATCH_ANY"}, false), + Description: `Specifies how individual filterLabel matches within the list of filterLabels +contribute towards the overall metadataFilter match. Supported values are: + - MATCH_ANY: At least one of the filterLabels must have a matching label in the +provided metadata. + - MATCH_ALL: All filterLabels must have matching labels in +the provided metadata.`, + }, + }, + }, + }, + "prefix_match": { + Type: schema.TypeString, + Optional: true, + Description: `For satifying the matchRule condition, the request's path must begin with the +specified prefixMatch. prefixMatch must begin with a /. The value must be +between 1 and 1024 characters. Only one of prefixMatch, fullPathMatch or +regexMatch must be specified.`, + }, + "query_parameter_matches": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies a list of query parameter match criteria, all of which must match +corresponding query parameters in the request.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the query parameter to match. The query parameter must exist in the +request, in the absence of which the request match fails.`, + }, + "exact_match": { + Type: schema.TypeString, + Optional: true, + Description: `The queryParameterMatch matches if the value of the parameter exactly matches +the contents of exactMatch. Only one of presentMatch, exactMatch and regexMatch +must be set.`, + }, + "present_match": { + Type: schema.TypeBool, + Optional: true, + Description: `Specifies that the queryParameterMatch matches if the request contains the query +parameter, irrespective of whether the parameter has a value or not. Only one of +presentMatch, exactMatch and regexMatch must be set.`, + }, + "regex_match": { + Type: schema.TypeString, + Optional: true, + Description: `The queryParameterMatch matches if the value of the parameter matches the +regular expression specified by regexMatch. For the regular expression grammar, +please see en.cppreference.com/w/cpp/regex/ecmascript Only one of presentMatch, +exactMatch and regexMatch must be set.`, + }, + }, + }, + }, + "regex_match": { + Type: schema.TypeString, + Optional: true, + Description: `For satifying the matchRule condition, the path of the request must satisfy the +regular expression specified in regexMatch after removing any query parameters +and anchor supplied with the original URL. For regular expression grammar please +see en.cppreference.com/w/cpp/regex/ecmascript Only one of prefixMatch, +fullPathMatch or regexMatch must be specified.`, + }, + }, + }, + }, + "route_action": { + Type: schema.TypeList, + Optional: true, + Description: `In response to a matching matchRule, 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cors_policy": { + Type: schema.TypeList, + Optional: true, + Description: `The specification for allowing client side cross-origin requests. Please see W3C +Recommendation for Cross Origin Resource Sharing`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_credentials": { + Type: schema.TypeBool, + Optional: true, + 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.`, + Default: false, + }, + "allow_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Allow-Headers header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "allow_methods": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Allow-Methods header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "allow_origin_regexes": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "allow_origins": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "disabled": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, specifies the CORS policy is disabled. +which indicates that the CORS policy is in effect. Defaults to false.`, + Default: false, + }, + "expose_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the content for the Access-Control-Expose-Headers header.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "max_age": { + Type: schema.TypeInt, + Optional: true, + 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.`, + }, + }, + }, + }, + "fault_injection_policy": { + Type: schema.TypeList, + Optional: true, + 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "abort": { + Type: schema.TypeList, + Optional: true, + Description: `The specification for how client requests are aborted as part of fault +injection.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_status": { + Type: schema.TypeInt, + Optional: true, + Description: `The HTTP status code used to abort the request. The value must be between 200 +and 599 inclusive.`, + }, + "percentage": { + Type: schema.TypeFloat, + Optional: 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.`, + }, + }, + }, + }, + "delay": { + Type: schema.TypeList, + Optional: true, + Description: `The specification for how client requests are delayed as part of fault +injection, before being sent to a backend service.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "fixed_delay": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the value of the fixed delay interval.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeString, + Required: true, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + 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.`, + }, + }, + }, + }, + "percentage": { + Type: schema.TypeFloat, + Optional: 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.`, + }, + }, + }, + }, + }, + }, + }, + "request_mirror_policy": { + Type: schema.TypeList, + Optional: true, + 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backend_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The BackendService resource being mirrored to.`, + }, + }, + }, + }, + "retry_policy": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the retry policy associated with this route.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_retries": { + Type: schema.TypeInt, + Required: true, + Description: `Specifies the allowed number retries. This number must be > 0.`, + }, + "per_try_timeout": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies a non-zero timeout per retry attempt. +If not specified, will use the timeout set in HttpRouteAction. If timeout in HttpRouteAction +is not set, will use the largest timeout among all backend services associated with the route.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeString, + Required: true, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + 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.`, + }, + }, + }, + }, + "retry_conditions": { + Type: schema.TypeList, + Optional: true, + 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`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "timeout": { + Type: schema.TypeList, + Optional: true, + 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeString, + Required: true, + Description: `Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 +inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + 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.`, + }, + }, + }, + }, + "url_rewrite": { + Type: schema.TypeList, + Optional: true, + Description: `The spec to modify the URL of the request, prior to forwarding the request to +the matched service`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host_rewrite": { + Type: schema.TypeString, + Optional: true, + 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.`, + }, + "path_prefix_rewrite": { + Type: schema.TypeString, + Optional: true, + 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.`, + }, + }, + }, + }, + "weighted_backend_services": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backend_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The default BackendService resource. Before +forwarding the request to backendService, the loadbalancer applies any relevant +headerActions specified as part of this backendServiceWeight.`, + }, + "header_action": { + Type: schema.TypeList, + Optional: true, + 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.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "request_headers_to_add": { + Type: schema.TypeList, + Optional: true, + Description: `Headers to add to a matching request prior to forwarding the request to the +backendService.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, + }, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, + }, + }, + }, + }, + "request_headers_to_remove": { + Type: schema.TypeList, + Optional: true, + Description: `A list of header names for headers that need to be removed from the request +prior to forwarding the request to the backendService.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "response_headers_to_add": { + Type: schema.TypeList, + Optional: true, + Description: `Headers to add the response prior to sending the response back to the client.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the header.`, + }, + "header_value": { + Type: schema.TypeString, + Required: true, + Description: `The value of the header to add.`, + }, + "replace": { + Type: schema.TypeBool, + 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.`, + }, + }, + }, + }, + "response_headers_to_remove": { + Type: schema.TypeList, + Optional: true, + 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.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "weight": { + Type: schema.TypeInt, + Optional: true, + 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`, + }, + }, + }, + }, + }, + }, + }, + "url_redirect": { + Type: schema.TypeList, + Optional: true, + Description: `When this rule is matched, the request is redirected to a URL specified by +urlRedirect. If urlRedirect is specified, service or routeAction must not be +set.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host_redirect": { + Type: schema.TypeString, + Optional: true, + 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.`, + }, + "https_redirect": { + Type: schema.TypeBool, + Optional: true, + 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.`, + Default: false, + }, + "path_redirect": { + Type: schema.TypeString, + Optional: true, + 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.`, + }, + "prefix_redirect": { + Type: schema.TypeString, + Optional: true, + Description: `The prefix that replaces the prefixMatch specified in the HttpRouteRuleMatch, +retaining the remaining portion of the URL before redirecting the request.`, + }, + "redirect_response_code": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"FOUND", "MOVED_PERMANENTLY_DEFAULT", "PERMANENT_REDIRECT", "SEE_OTHER", "TEMPORARY_REDIRECT", ""}, false), + 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.`, + }, + "strip_query": { + Type: schema.TypeBool, + Optional: 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. Defaults to false.`, + Default: false, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "test": { + Type: schema.TypeList, + Optional: true, + Description: `The list of expected URL mapping tests. Request to update this UrlMap will +succeed only if all of the test cases pass. You can specify a maximum of 100 +tests per UrlMap.`, + Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "host": { Type: schema.TypeString, @@ -1184,334 +1670,1352 @@ field is used in optimistic locking.`, } } -func computeUrlMapHostRuleSchema() *schema.Resource { - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - "hosts": { - Type: schema.TypeSet, - Required: true, - Description: `The list of host patterns to match. They must be valid hostnames, except * will -match any string of ([a-z0-9-.]*). In that case, * must be the first character -and must be followed in the pattern by either - or ..`, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Set: schema.HashString, - }, - "path_matcher": { - Type: schema.TypeString, - Required: true, - Description: `The name of the PathMatcher to use to match the path portion of the URL if the -hostRule matches the URL's host portion.`, - }, - "description": { - Type: schema.TypeString, - Optional: true, - Description: `An optional description of this resource. Provide this property when you create -the resource.`, - }, - }, +func computeUrlMapHostRuleSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hosts": { + Type: schema.TypeSet, + Required: true, + Description: `The list of host patterns to match. They must be valid hostnames, except * will +match any string of ([a-z0-9-.]*). In that case, * must be the first character +and must be followed in the pattern by either - or ..`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + }, + "path_matcher": { + Type: schema.TypeString, + Required: true, + Description: `The name of the PathMatcher to use to match the path portion of the URL if the +hostRule matches the URL's host portion.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `An optional description of this resource. Provide this property when you create +the resource.`, + }, + }, + } +} + +func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(defaultServiceProp)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { + obj["defaultService"] = defaultServiceProp + } + descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } + headerActionProp, err := expandComputeUrlMapHeaderAction(d.Get("header_action"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("header_action"); !isEmptyValue(reflect.ValueOf(headerActionProp)) && (ok || !reflect.DeepEqual(v, headerActionProp)) { + obj["headerAction"] = headerActionProp + } + hostRulesProp, err := expandComputeUrlMapHostRule(d.Get("host_rule"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(hostRulesProp)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { + obj["hostRules"] = hostRulesProp + } + nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + pathMatchersProp, err := expandComputeUrlMapPathMatcher(d.Get("path_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(pathMatchersProp)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { + obj["pathMatchers"] = pathMatchersProp + } + testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(testsProp)) && (ok || !reflect.DeepEqual(v, testsProp)) { + obj["tests"] = testsProp + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new UrlMap: %#v", obj) + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating UrlMap: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = computeOperationWaitTime( + config, res, project, "Creating UrlMap", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create UrlMap: %s", err) + } + + log.Printf("[DEBUG] Finished creating UrlMap %q: %#v", d.Id(), res) + + return resourceComputeUrlMapRead(d, meta) +} + +func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("ComputeUrlMap %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + + if err := d.Set("creation_timestamp", flattenComputeUrlMapCreationTimestamp(res["creationTimestamp"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("default_service", flattenComputeUrlMapDefaultService(res["defaultService"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("description", flattenComputeUrlMapDescription(res["description"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("map_id", flattenComputeUrlMapMapId(res["id"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("fingerprint", flattenComputeUrlMapFingerprint(res["fingerprint"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("header_action", flattenComputeUrlMapHeaderAction(res["headerAction"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("host_rule", flattenComputeUrlMapHostRule(res["hostRules"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("name", flattenComputeUrlMapName(res["name"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("path_matcher", flattenComputeUrlMapPathMatcher(res["pathMatchers"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("test", flattenComputeUrlMapTest(res["tests"], d)); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + + return nil +} + +func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { + obj["defaultService"] = defaultServiceProp + } + descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } + headerActionProp, err := expandComputeUrlMapHeaderAction(d.Get("header_action"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("header_action"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, headerActionProp)) { + obj["headerAction"] = headerActionProp + } + hostRulesProp, err := expandComputeUrlMapHostRule(d.Get("host_rule"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { + obj["hostRules"] = hostRulesProp + } + nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + pathMatchersProp, err := expandComputeUrlMapPathMatcher(d.Get("path_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { + obj["pathMatchers"] = pathMatchersProp + } + testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, testsProp)) { + obj["tests"] = testsProp + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating UrlMap %q: %#v", d.Id(), obj) + res, err := sendRequestWithTimeout(config, "PUT", project, url, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating UrlMap %q: %s", d.Id(), err) + } + + err = computeOperationWaitTime( + config, res, project, "Updating UrlMap", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) + + if err != nil { + return err + } + + return resourceComputeUrlMapRead(d, meta) +} + +func resourceComputeUrlMapDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting UrlMap %q", d.Id()) + + res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "UrlMap") + } + + err = computeOperationWaitTime( + config, res, project, "Deleting UrlMap", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting UrlMap %q: %#v", d.Id(), res) + return nil +} + +func resourceComputeUrlMapImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/global/urlMaps/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeUrlMapCreationTimestamp(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapDefaultService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapMapId(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeUrlMapFingerprint(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["request_headers_to_add"] = + flattenComputeUrlMapHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) + transformed["request_headers_to_remove"] = + flattenComputeUrlMapHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) + transformed["response_headers_to_add"] = + flattenComputeUrlMapHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) + transformed["response_headers_to_remove"] = + flattenComputeUrlMapHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ + "header_name": flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapHeaderActionRequestHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ + "header_name": flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapHeaderActionResponseHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHostRule(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := schema.NewSet(schema.HashResource(computeUrlMapHostRuleSchema()), []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{}{ + "description": flattenComputeUrlMapHostRuleDescription(original["description"], d), + "hosts": flattenComputeUrlMapHostRuleHosts(original["hosts"], d), + "path_matcher": flattenComputeUrlMapHostRulePathMatcher(original["pathMatcher"], d), + }) + } + return transformed +} +func flattenComputeUrlMapHostRuleDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapHostRuleHosts(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenComputeUrlMapHostRulePathMatcher(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcher(v interface{}, d *schema.ResourceData) 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{}{ + "default_service": flattenComputeUrlMapPathMatcherDefaultService(original["defaultService"], d), + "description": flattenComputeUrlMapPathMatcherDescription(original["description"], d), + "header_action": flattenComputeUrlMapPathMatcherHeaderAction(original["headerAction"], d), + "name": flattenComputeUrlMapPathMatcherName(original["name"], d), + "path_rule": flattenComputeUrlMapPathMatcherPathRule(original["pathRules"], d), + "route_rules": flattenComputeUrlMapPathMatcherRouteRules(original["routeRules"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherDefaultService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapPathMatcherDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["request_headers_to_add"] = + flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) + transformed["request_headers_to_remove"] = + flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) + transformed["response_headers_to_add"] = + flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) + transformed["response_headers_to_remove"] = + flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ + "header_name": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ + "header_name": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRule(v interface{}, d *schema.ResourceData) 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": flattenComputeUrlMapPathMatcherPathRuleService(original["service"], d), + "paths": flattenComputeUrlMapPathMatcherPathRulePaths(original["paths"], d), + "route_action": flattenComputeUrlMapPathMatcherPathRuleRouteAction(original["routeAction"], d), + "url_redirect": flattenComputeUrlMapPathMatcherPathRuleUrlRedirect(original["urlRedirect"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherPathRuleService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapPathMatcherPathRulePaths(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["cors_policy"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicy(original["corsPolicy"], d) + transformed["fault_injection_policy"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicy(original["faultInjectionPolicy"], d) + transformed["request_mirror_policy"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicy(original["requestMirrorPolicy"], d) + transformed["retry_policy"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicy(original["retryPolicy"], d) + transformed["timeout"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeout(original["timeout"], d) + transformed["url_rewrite"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewrite(original["urlRewrite"], d) + transformed["weighted_backend_services"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServices(original["weightedBackendServices"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } + transformed := make(map[string]interface{}) + transformed["allow_credentials"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowCredentials(original["allowCredentials"], d) + transformed["allow_headers"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowHeaders(original["allowHeaders"], d) + transformed["allow_methods"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowMethods(original["allowMethods"], d) + transformed["allow_origin_regexes"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOriginRegexes(original["allowOriginRegexes"], d) + transformed["allow_origins"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOrigins(original["allowOrigins"], d) + transformed["disabled"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyDisabled(original["disabled"], d) + transformed["expose_headers"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyExposeHeaders(original["exposeHeaders"], d) + transformed["max_age"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyMaxAge(original["maxAge"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowCredentials(v interface{}, d *schema.ResourceData) interface{} { + return v } -func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowHeaders(v interface{}, d *schema.ResourceData) interface{} { + return v +} - obj := make(map[string]interface{}) - defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(defaultServiceProp)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { - obj["defaultService"] = defaultServiceProp +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowMethods(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOriginRegexes(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOrigins(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyDisabled(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyExposeHeaders(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyMaxAge(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } - descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { - obj["description"] = descriptionProp + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { - obj["fingerprint"] = fingerprintProp + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - headerActionProp, err := expandComputeUrlMapHeaderAction(d.Get("header_action"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("header_action"); !isEmptyValue(reflect.ValueOf(headerActionProp)) && (ok || !reflect.DeepEqual(v, headerActionProp)) { - obj["headerAction"] = headerActionProp + transformed := make(map[string]interface{}) + transformed["abort"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbort(original["abort"], d) + transformed["delay"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelay(original["delay"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbort(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - hostRulesProp, err := expandComputeUrlMapHostRule(d.Get("host_rule"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(hostRulesProp)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { - obj["hostRules"] = hostRulesProp + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { - obj["name"] = nameProp + transformed := make(map[string]interface{}) + transformed["http_status"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortHttpStatus(original["httpStatus"], d) + transformed["percentage"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortPercentage(original["percentage"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortHttpStatus(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } - pathMatchersProp, err := expandComputeUrlMapPathMatcher(d.Get("path_matcher"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(pathMatchersProp)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { - obj["pathMatchers"] = pathMatchersProp + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelay(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(testsProp)) && (ok || !reflect.DeepEqual(v, testsProp)) { - obj["tests"] = testsProp + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps") - if err != nil { - return err + transformed := make(map[string]interface{}) + transformed["fixed_delay"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelay(original["fixedDelay"], d) + transformed["percentage"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayPercentage(original["percentage"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelay(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - - log.Printf("[DEBUG] Creating new UrlMap: %#v", obj) - project, err := getProject(d, config) - if err != nil { - return err + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate)) - if err != nil { - return fmt.Errorf("Error creating UrlMap: %s", err) + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelayNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(original["seconds"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelayNanos(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } + return v +} - // Store the ID now - id, err := replaceVars(d, config, "projects/{{project}}/global/urlMaps/{{name}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} - err = computeOperationWaitTime( - config, res, project, "Creating UrlMap", - int(d.Timeout(schema.TimeoutCreate).Minutes())) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayPercentage(v interface{}, d *schema.ResourceData) interface{} { + return v +} - if err != nil { - // The resource didn't actually create - d.SetId("") - return fmt.Errorf("Error waiting to create UrlMap: %s", err) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["backend_service"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicyBackendService(original["backendService"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicyBackendService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["num_retries"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyNumRetries(original["numRetries"], d) + transformed["per_try_timeout"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeout(original["perTryTimeout"], d) + transformed["retry_conditions"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyRetryConditions(original["retryConditions"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyNumRetries(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } + return v +} - log.Printf("[DEBUG] Finished creating UrlMap %q: %#v", d.Id(), res) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeout(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutSeconds(original["seconds"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} - return resourceComputeUrlMapRead(d, meta) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { + return v } -func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyRetryConditions(v interface{}, d *schema.ResourceData) interface{} { + return v +} - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") - if err != nil { - return err +func flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeout(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - - project, err := getProject(d, config) - if err != nil { - return err + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - res, err := sendRequest(config, "GET", project, url, nil) - if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("ComputeUrlMap %q", d.Id())) + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeoutNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeoutSeconds(original["seconds"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } + return v +} - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) - } +func flattenComputeUrlMapPathMatcherPathRuleRouteActionTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} - if err := d.Set("creation_timestamp", flattenComputeUrlMapCreationTimestamp(res["creationTimestamp"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewrite(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - if err := d.Set("default_service", flattenComputeUrlMapDefaultService(res["defaultService"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - if err := d.Set("description", flattenComputeUrlMapDescription(res["description"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + transformed := make(map[string]interface{}) + transformed["host_rewrite"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewriteHostRewrite(original["hostRewrite"], d) + transformed["path_prefix_rewrite"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewritePathPrefixRewrite(original["pathPrefixRewrite"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewriteHostRewrite(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionUrlRewritePathPrefixRewrite(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServices(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - if err := d.Set("map_id", flattenComputeUrlMapMapId(res["id"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + 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{}{ + "backend_service": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesBackendService(original["backendService"], d), + "header_action": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderAction(original["headerAction"], d), + "weight": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesWeight(original["weight"], d), + }) } - if err := d.Set("fingerprint", flattenComputeUrlMapFingerprint(res["fingerprint"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + return transformed +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesBackendService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - if err := d.Set("header_action", flattenComputeUrlMapHeaderAction(res["headerAction"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - if err := d.Set("host_rule", flattenComputeUrlMapHostRule(res["hostRules"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - if err := d.Set("name", flattenComputeUrlMapName(res["name"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + transformed := make(map[string]interface{}) + transformed["request_headers_to_add"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) + transformed["request_headers_to_remove"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) + transformed["response_headers_to_add"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) + transformed["response_headers_to_remove"] = + flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - if err := d.Set("path_matcher", flattenComputeUrlMapPathMatcher(res["pathMatchers"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + 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{}{ + "header_name": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d), + }) } - if err := d.Set("test", flattenComputeUrlMapTest(res["tests"], d)); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + return transformed +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { - return fmt.Errorf("Error reading UrlMap: %s", err) + 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{}{ + "header_name": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(original["replace"], d), + }) } + return transformed +} +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} - return nil +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v } -func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} - project, err := getProject(d, config) - if err != nil { - return err +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesWeight(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } + return v +} - obj := make(map[string]interface{}) - defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { - obj["defaultService"] = defaultServiceProp +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirect(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { - obj["description"] = descriptionProp + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { - obj["fingerprint"] = fingerprintProp + transformed := make(map[string]interface{}) + transformed["host_redirect"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectHostRedirect(original["hostRedirect"], d) + transformed["https_redirect"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectHttpsRedirect(original["httpsRedirect"], d) + transformed["path_redirect"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectPathRedirect(original["pathRedirect"], d) + transformed["prefix_redirect"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectPrefixRedirect(original["prefixRedirect"], d) + transformed["redirect_response_code"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectRedirectResponseCode(original["redirectResponseCode"], d) + transformed["strip_query"] = + flattenComputeUrlMapPathMatcherPathRuleUrlRedirectStripQuery(original["stripQuery"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectHostRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectHttpsRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectPathRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectPrefixRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectRedirectResponseCode(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherPathRuleUrlRedirectStripQuery(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRules(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - headerActionProp, err := expandComputeUrlMapHeaderAction(d.Get("header_action"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("header_action"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, headerActionProp)) { - obj["headerAction"] = headerActionProp + 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{}{ + "priority": flattenComputeUrlMapPathMatcherRouteRulesPriority(original["priority"], d), + "header_action": flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(original["headerAction"], d), + "match_rules": flattenComputeUrlMapPathMatcherRouteRulesMatchRules(original["matchRules"], d), + "route_action": flattenComputeUrlMapPathMatcherRouteRulesRouteAction(original["routeAction"], d), + "url_redirect": flattenComputeUrlMapPathMatcherRouteRulesUrlRedirect(original["urlRedirect"], d), + }) } - hostRulesProp, err := expandComputeUrlMapHostRule(d.Get("host_rule"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { - obj["hostRules"] = hostRulesProp + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesPriority(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } - nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { - obj["name"] = nameProp + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - pathMatchersProp, err := expandComputeUrlMapPathMatcher(d.Get("path_matcher"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { - obj["pathMatchers"] = pathMatchersProp + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, testsProp)) { - obj["tests"] = testsProp + transformed := make(map[string]interface{}) + transformed["request_headers_to_add"] = + flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) + transformed["request_headers_to_remove"] = + flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) + transformed["response_headers_to_add"] = + flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) + transformed["response_headers_to_remove"] = + flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") - if err != nil { - return err + 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{}{ + "header_name": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(original["replace"], d), + }) } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} - log.Printf("[DEBUG] Updating UrlMap %q: %#v", d.Id(), obj) - res, err := sendRequestWithTimeout(config, "PUT", project, url, obj, d.Timeout(schema.TimeoutUpdate)) +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} - if err != nil { - return fmt.Errorf("Error updating UrlMap %q: %s", d.Id(), err) - } +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} - err = computeOperationWaitTime( - config, res, project, "Updating UrlMap", - int(d.Timeout(schema.TimeoutUpdate).Minutes())) +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} - if err != nil { - return err +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ + "header_name": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(original["replace"], d), + }) } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} - return resourceComputeUrlMapRead(d, meta) +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v } -func resourceComputeUrlMapDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} - project, err := getProject(d, config) - if err != nil { - return err - } +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/urlMaps/{{name}}") - if err != nil { - return err +func flattenComputeUrlMapPathMatcherRouteRulesMatchRules(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - - var obj map[string]interface{} - log.Printf("[DEBUG] Deleting UrlMap %q", d.Id()) - - res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return handleNotFoundError(err, d, "UrlMap") + 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{}{ + "full_path_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(original["fullPathMatch"], d), + "header_matches": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(original["headerMatches"], d), + "ignore_case": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(original["ignoreCase"], d), + "metadata_filters": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(original["metadataFilters"], d), + "prefix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(original["prefixMatch"], d), + "query_parameter_matches": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(original["queryParameterMatches"], d), + "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(original["regexMatch"], d), + }) } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} - err = computeOperationWaitTime( - config, res, project, "Deleting UrlMap", - int(d.Timeout(schema.TimeoutDelete).Minutes())) - - if err != nil { - return err +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v } - - log.Printf("[DEBUG] Finished deleting UrlMap %q: %#v", d.Id(), res) - return nil + 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{}{ + "exact_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(original["exactMatch"], d), + "header_name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(original["headerName"], d), + "invert_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(original["invertMatch"], d), + "prefix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(original["prefixMatch"], d), + "present_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(original["presentMatch"], d), + "range_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(original["rangeMatch"], d), + "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(original["regexMatch"], d), + "suffix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(original["suffixMatch"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(v interface{}, d *schema.ResourceData) interface{} { + return v } -func resourceComputeUrlMapImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - config := meta.(*Config) - if err := parseImportId([]string{ - "projects/(?P[^/]+)/global/urlMaps/(?P[^/]+)", - "(?P[^/]+)/(?P[^/]+)", - "(?P[^/]+)", - }, d, config); err != nil { - return nil, err - } +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} - // Replace import id for the resource id - id, err := replaceVars(d, config, "projects/{{project}}/global/urlMaps/{{name}}") - if err != nil { - return nil, fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} - return []*schema.ResourceData{d}, nil +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapCreationTimestamp(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapDefaultService(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - return ConvertSelfLinkToV1(v.(string)) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["range_end"] = + flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(original["rangeEnd"], d) + transformed["range_start"] = + flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(original["rangeStart"], d) + return []interface{}{transformed} } - -func flattenComputeUrlMapDescription(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } return v } -func flattenComputeUrlMapMapId(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(v interface{}, d *schema.ResourceData) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -1521,30 +3025,19 @@ func flattenComputeUrlMapMapId(v interface{}, d *schema.ResourceData) interface{ return v } -func flattenComputeUrlMapFingerprint(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHeaderAction(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["request_headers_to_add"] = - flattenComputeUrlMapHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) - transformed["request_headers_to_remove"] = - flattenComputeUrlMapHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) - transformed["response_headers_to_add"] = - flattenComputeUrlMapHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) - transformed["response_headers_to_remove"] = - flattenComputeUrlMapHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) - return []interface{}{transformed} +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -1557,30 +3050,13 @@ func flattenComputeUrlMapHeaderActionRequestHeadersToAdd(v interface{}, d *schem continue } transformed = append(transformed, map[string]interface{}{ - "header_name": flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapHeaderActionRequestHeadersToAddReplace(original["replace"], d), + "filter_labels": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(original["filterLabels"], d), + "filter_match_criteria": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(original["filterMatchCriteria"], d), }) } return transformed } -func flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -1593,136 +3069,204 @@ func flattenComputeUrlMapHeaderActionResponseHeadersToAdd(v interface{}, d *sche continue } transformed = append(transformed, map[string]interface{}{ - "header_name": flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapHeaderActionResponseHeadersToAddReplace(original["replace"], d), + "name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(original["name"], d), + "value": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(original["value"], d), }) } return transformed } -func flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHostRule(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } l := v.([]interface{}) - transformed := schema.NewSet(schema.HashResource(computeUrlMapHostRuleSchema()), []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.Add(map[string]interface{}{ - "description": flattenComputeUrlMapHostRuleDescription(original["description"], d), - "hosts": flattenComputeUrlMapHostRuleHosts(original["hosts"], d), - "path_matcher": flattenComputeUrlMapHostRulePathMatcher(original["pathMatcher"], d), + transformed = append(transformed, map[string]interface{}{ + "exact_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(original["exactMatch"], d), + "name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(original["name"], d), + "present_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(original["presentMatch"], d), + "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(original["regexMatch"], d), }) } return transformed } -func flattenComputeUrlMapHostRuleDescription(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapHostRuleHosts(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - return schema.NewSet(schema.HashString, v.([]interface{})) +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapHostRulePathMatcher(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcher(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteAction(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - 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{}{ - "default_service": flattenComputeUrlMapPathMatcherDefaultService(original["defaultService"], d), - "description": flattenComputeUrlMapPathMatcherDescription(original["description"], d), - "path_rule": flattenComputeUrlMapPathMatcherPathRule(original["pathRules"], d), - "header_action": flattenComputeUrlMapPathMatcherHeaderAction(original["headerAction"], d), - "name": flattenComputeUrlMapPathMatcherName(original["name"], d), - "route_rules": flattenComputeUrlMapPathMatcherRouteRules(original["routeRules"], d), - }) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - return transformed + transformed := make(map[string]interface{}) + transformed["cors_policy"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(original["corsPolicy"], d) + transformed["fault_injection_policy"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(original["faultInjectionPolicy"], d) + transformed["request_mirror_policy"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(original["requestMirrorPolicy"], d) + transformed["retry_policy"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(original["retryPolicy"], d) + transformed["timeout"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(original["timeout"], d) + transformed["url_rewrite"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(original["urlRewrite"], d) + transformed["weighted_backend_services"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(original["weightedBackendServices"], d) + return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherDefaultService(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - return ConvertSelfLinkToV1(v.(string)) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["allow_credentials"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(original["allowCredentials"], d) + transformed["allow_headers"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(original["allowHeaders"], d) + transformed["allow_methods"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(original["allowMethods"], d) + transformed["allow_origin_regexes"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(original["allowOriginRegexes"], d) + transformed["allow_origins"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(original["allowOrigins"], d) + transformed["disabled"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(original["disabled"], d) + transformed["expose_headers"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(original["exposeHeaders"], d) + transformed["max_age"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(original["maxAge"], d) + return []interface{}{transformed} +} +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapPathMatcherDescription(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherPathRule(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - 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{}{ - "paths": flattenComputeUrlMapPathMatcherPathRulePaths(original["paths"], d), - "service": flattenComputeUrlMapPathMatcherPathRuleService(original["service"], d), - }) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - return transformed + transformed := make(map[string]interface{}) + transformed["abort"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(original["abort"], d) + transformed["delay"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(original["delay"], d) + return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherPathRulePaths(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - return schema.NewSet(schema.HashString, v.([]interface{})) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["http_status"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(original["httpStatus"], d) + transformed["percentage"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(original["percentage"], d) + return []interface{}{transformed} } - -func flattenComputeUrlMapPathMatcherPathRuleService(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. } - return ConvertSelfLinkToV1(v.(string)) + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapPathMatcherHeaderAction(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return nil } @@ -1731,115 +3275,141 @@ func flattenComputeUrlMapPathMatcherHeaderAction(v interface{}, d *schema.Resour return nil } transformed := make(map[string]interface{}) - transformed["request_headers_to_add"] = - flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) - transformed["request_headers_to_remove"] = - flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) - transformed["response_headers_to_add"] = - flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) - transformed["response_headers_to_remove"] = - flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + transformed["fixed_delay"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(original["fixedDelay"], d) + transformed["percentage"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(original["percentage"], d) return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - 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{}{ - "header_name": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(original["replace"], d), - }) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - return transformed + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(original["seconds"], d) + return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } return v } -func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { - return v +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["backend_service"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(original["backendService"], d) + return []interface{}{transformed} } - -func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(v interface{}, d *schema.ResourceData) 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{}{ - "header_name": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(original["replace"], d), - }) + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil } - return transformed + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["num_retries"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(original["numRetries"], d) + transformed["per_try_timeout"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(original["perTryTimeout"], d) + transformed["retry_conditions"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(original["retryConditions"], d) + return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } return v } -func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(original["seconds"], d) + return []interface{}{transformed} } - -func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } return v } -func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRules(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(v interface{}, d *schema.ResourceData) interface{} { if v == nil { - return v + return nil } - 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{}{ - "priority": flattenComputeUrlMapPathMatcherRouteRulesPriority(original["priority"], d), - "header_action": flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(original["headerAction"], d), - "match_rules": flattenComputeUrlMapPathMatcherRouteRulesMatchRules(original["matchRules"], d), - "route_action": flattenComputeUrlMapPathMatcherRouteRulesRouteAction(original["routeAction"], d), - "url_redirect": flattenComputeUrlMapPathMatcherRouteRulesUrlRedirect(original["urlRedirect"], d), - }) + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil } - return transformed + transformed := make(map[string]interface{}) + transformed["nanos"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(original["nanos"], d) + transformed["seconds"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(original["seconds"], d) + return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherRouteRulesPriority(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { @@ -1849,7 +3419,11 @@ func flattenComputeUrlMapPathMatcherRouteRulesPriority(v interface{}, d *schema. return v } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return nil } @@ -1858,53 +3432,21 @@ func flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(v interface{}, d *sch return nil } transformed := make(map[string]interface{}) - transformed["request_headers_to_add"] = - flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) - transformed["request_headers_to_remove"] = - flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) - transformed["response_headers_to_add"] = - flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) - transformed["response_headers_to_remove"] = - flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + transformed["host_rewrite"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(original["hostRewrite"], d) + transformed["path_prefix_rewrite"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(original["pathPrefixRewrite"], d) return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) 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{}{ - "header_name": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(original["replace"], d), - }) - } - return transformed -} -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -1917,30 +3459,40 @@ func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(v continue } transformed = append(transformed, map[string]interface{}{ - "header_name": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(original["replace"], d), + "backend_service": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(original["backendService"], d), + "header_action": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(original["headerAction"], d), + "weight": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(original["weight"], d), }) } return transformed } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { - return v +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) } -func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { - return v +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["request_headers_to_add"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) + transformed["request_headers_to_remove"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) + transformed["response_headers_to_add"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) + transformed["response_headers_to_remove"] = + flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) + return []interface{}{transformed} } - -func flattenComputeUrlMapPathMatcherRouteRulesMatchRules(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -1953,22 +3505,30 @@ func flattenComputeUrlMapPathMatcherRouteRulesMatchRules(v interface{}, d *schem continue } transformed = append(transformed, map[string]interface{}{ - "full_path_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(original["fullPathMatch"], d), - "header_matches": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(original["headerMatches"], d), - "ignore_case": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(original["ignoreCase"], d), - "metadata_filters": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(original["metadataFilters"], d), - "prefix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(original["prefixMatch"], d), - "query_parameter_matches": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(original["queryParameterMatches"], d), - "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(original["regexMatch"], d), + "header_name": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d), }) } return transformed } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -1981,39 +3541,40 @@ func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(v interfac continue } transformed = append(transformed, map[string]interface{}{ - "exact_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(original["exactMatch"], d), - "header_name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(original["headerName"], d), - "invert_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(original["invertMatch"], d), - "prefix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(original["prefixMatch"], d), - "present_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(original["presentMatch"], d), - "range_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(original["rangeMatch"], d), - "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(original["regexMatch"], d), - "suffix_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(original["suffixMatch"], d), + "header_name": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(original["replace"], d), }) } return transformed } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirect(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return nil } @@ -2022,64 +3583,45 @@ func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch( return nil } transformed := make(map[string]interface{}) - transformed["range_end"] = - flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(original["rangeEnd"], d) - transformed["range_start"] = - flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(original["rangeStart"], d) + transformed["host_redirect"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(original["hostRedirect"], d) + transformed["https_redirect"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(original["httpsRedirect"], d) + transformed["path_redirect"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(original["pathRedirect"], d) + transformed["prefix_redirect"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(original["prefixRedirect"], d) + transformed["redirect_response_code"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(original["redirectResponseCode"], d) + transformed["strip_query"] = + flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(original["stripQuery"], d) return []interface{}{transformed} } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(v interface{}, d *schema.ResourceData) 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{}{ - "filter_labels": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(original["filterLabels"], d), - "filter_match_criteria": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(original["filterMatchCriteria"], d), - }) - } - return transformed +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(v interface{}, d *schema.ResourceData) interface{} { + return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(v interface{}, d *schema.ResourceData) interface{} { + +func flattenComputeUrlMapTest(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } @@ -2092,611 +3634,670 @@ func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLab continue } transformed = append(transformed, map[string]interface{}{ - "name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(original["name"], d), - "value": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(original["value"], d), + "description": flattenComputeUrlMapTestDescription(original["description"], d), + "host": flattenComputeUrlMapTestHost(original["host"], d), + "path": flattenComputeUrlMapTestPath(original["path"], d), + "service": flattenComputeUrlMapTestService(original["service"], d), }) } return transformed } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapTestDescription(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapTestHost(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapTestPath(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapTestService(v interface{}, d *schema.ResourceData) 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{}{ - "exact_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(original["exactMatch"], d), - "name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(original["name"], d), - "present_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(original["presentMatch"], d), - "regex_match": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(original["regexMatch"], d), - }) - } - return transformed -} -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(v interface{}, d *schema.ResourceData) interface{} { - return v + return ConvertSelfLinkToV1(v.(string)) } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteAction(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil +func expandComputeUrlMapHeaderAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil } + raw := l[0] + original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformed["cors_policy"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(original["corsPolicy"], d) - transformed["fault_injection_policy"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(original["faultInjectionPolicy"], d) - transformed["request_mirror_policy"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(original["requestMirrorPolicy"], d) - transformed["retry_policy"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(original["retryPolicy"], d) - transformed["timeout"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(original["timeout"], d) - transformed["url_rewrite"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(original["urlRewrite"], d) - transformed["weighted_backend_services"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(original["weightedBackendServices"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil + + transformedRequestHeadersToAdd, err := expandComputeUrlMapHeaderActionRequestHeadersToAdd(original["request_headers_to_add"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeadersToAdd); val.IsValid() && !isEmptyValue(val) { + transformed["requestHeadersToAdd"] = transformedRequestHeadersToAdd } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil + + transformedRequestHeadersToRemove, err := expandComputeUrlMapHeaderActionRequestHeadersToRemove(original["request_headers_to_remove"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeadersToRemove); val.IsValid() && !isEmptyValue(val) { + transformed["requestHeadersToRemove"] = transformedRequestHeadersToRemove } - transformed := make(map[string]interface{}) - transformed["allow_credentials"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(original["allowCredentials"], d) - transformed["allow_headers"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(original["allowHeaders"], d) - transformed["allow_methods"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(original["allowMethods"], d) - transformed["allow_origin_regexes"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(original["allowOriginRegexes"], d) - transformed["allow_origins"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(original["allowOrigins"], d) - transformed["disabled"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(original["disabled"], d) - transformed["expose_headers"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(original["exposeHeaders"], d) - transformed["max_age"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(original["maxAge"], d) - return []interface{}{transformed} + + transformedResponseHeadersToAdd, err := expandComputeUrlMapHeaderActionResponseHeadersToAdd(original["response_headers_to_add"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeadersToAdd); val.IsValid() && !isEmptyValue(val) { + transformed["responseHeadersToAdd"] = transformedResponseHeadersToAdd + } + + transformedResponseHeadersToRemove, err := expandComputeUrlMapHeaderActionResponseHeadersToRemove(original["response_headers_to_remove"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeadersToRemove); val.IsValid() && !isEmptyValue(val) { + transformed["responseHeadersToRemove"] = transformedResponseHeadersToRemove + } + + return transformed, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(v interface{}, d *schema.ResourceData) interface{} { - return v + +func expandComputeUrlMapHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + transformedHeaderValue, err := expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue + } + + transformedReplace, err := expandComputeUrlMapHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { + transformed["replace"] = transformedReplace + } + + req = append(req, transformed) + } + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + transformedHeaderValue, err := expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue + } + + transformedReplace, err := expandComputeUrlMapHeaderActionResponseHeadersToAddReplace(original["replace"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { + transformed["replace"] = transformedReplace + } + + req = append(req, transformed) + } + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v +func expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["abort"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(original["abort"], d) - transformed["delay"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(original["delay"], d) - return []interface{}{transformed} +func expandComputeUrlMapHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["http_status"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(original["httpStatus"], d) - transformed["percentage"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(original["percentage"], d) - return []interface{}{transformed} + +func expandComputeUrlMapHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. + +func expandComputeUrlMapHostRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDescription, err := expandComputeUrlMapHostRuleDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription + } + + transformedHosts, err := expandComputeUrlMapHostRuleHosts(original["hosts"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHosts); val.IsValid() && !isEmptyValue(val) { + transformed["hosts"] = transformedHosts + } + + transformedPathMatcher, err := expandComputeUrlMapHostRulePathMatcher(original["path_matcher"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPathMatcher); val.IsValid() && !isEmptyValue(val) { + transformed["pathMatcher"] = transformedPathMatcher + } + + req = append(req, transformed) } - return v + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapHostRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["fixed_delay"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(original["fixedDelay"], d) - transformed["percentage"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(original["percentage"], d) - return []interface{}{transformed} +func expandComputeUrlMapHostRuleHosts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["nanos"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(original["nanos"], d) - transformed["seconds"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(original["seconds"], d) - return []interface{}{transformed} + +func expandComputeUrlMapHostRulePathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v + +func expandComputeUrlMapName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d *schema.ResourceData) interface{} { - return v -} +func expandComputeUrlMapPathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDefaultService, err := expandComputeUrlMapPathMatcherDefaultService(original["default_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDefaultService); val.IsValid() && !isEmptyValue(val) { + transformed["defaultService"] = transformedDefaultService + } + + transformedDescription, err := expandComputeUrlMapPathMatcherDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription + } + + transformedHeaderAction, err := expandComputeUrlMapPathMatcherHeaderAction(original["header_action"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderAction); val.IsValid() && !isEmptyValue(val) { + transformed["headerAction"] = transformedHeaderAction + } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(v interface{}, d *schema.ResourceData) interface{} { - return v -} + transformedName, err := expandComputeUrlMapPathMatcherName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { + transformed["name"] = transformedName + } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["backend_service"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(original["backendService"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) -} + transformedPathRule, err := expandComputeUrlMapPathMatcherPathRule(original["path_rule"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPathRule); val.IsValid() && !isEmptyValue(val) { + transformed["pathRules"] = transformedPathRule + } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["num_retries"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(original["numRetries"], d) - transformed["per_try_timeout"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(original["perTryTimeout"], d) - transformed["retry_conditions"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(original["retryConditions"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v -} + transformedRouteRules, err := expandComputeUrlMapPathMatcherRouteRules(original["route_rules"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRouteRules); val.IsValid() && !isEmptyValue(val) { + transformed["routeRules"] = transformedRouteRules + } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["nanos"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(original["nanos"], d) - transformed["seconds"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(original["seconds"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. + req = append(req, transformed) } - return v + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil +func expandComputeUrlMapPathMatcherHeaderAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil } + raw := l[0] + original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformed["nanos"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(original["nanos"], d) - transformed["seconds"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(original["seconds"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. + + transformedRequestHeadersToAdd, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(original["request_headers_to_add"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeadersToAdd); val.IsValid() && !isEmptyValue(val) { + transformed["requestHeadersToAdd"] = transformedRequestHeadersToAdd } - return v -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { - return v -} + transformedRequestHeadersToRemove, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(original["request_headers_to_remove"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeadersToRemove); val.IsValid() && !isEmptyValue(val) { + transformed["requestHeadersToRemove"] = transformedRequestHeadersToRemove + } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil + transformedResponseHeadersToAdd, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(original["response_headers_to_add"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeadersToAdd); val.IsValid() && !isEmptyValue(val) { + transformed["responseHeadersToAdd"] = transformedResponseHeadersToAdd } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil + + transformedResponseHeadersToRemove, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(original["response_headers_to_remove"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeadersToRemove); val.IsValid() && !isEmptyValue(val) { + transformed["responseHeadersToRemove"] = transformedResponseHeadersToRemove } - transformed := make(map[string]interface{}) - transformed["host_rewrite"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(original["hostRewrite"], d) - transformed["path_prefix_rewrite"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(original["pathPrefixRewrite"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(v interface{}, d *schema.ResourceData) interface{} { - return v -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(v interface{}, d *schema.ResourceData) interface{} { - return v + return transformed, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) + req := 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 + if raw == nil { continue } - transformed = append(transformed, map[string]interface{}{ - "backend_service": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(original["backendService"], d), - "header_action": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(original["headerAction"], d), - "weight": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(original["weight"], d), - }) + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + transformedHeaderValue, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue + } + + transformedReplace, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { + transformed["replace"] = transformedReplace + } + + req = append(req, transformed) } - return transformed + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) + +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["request_headers_to_add"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(original["requestHeadersToAdd"], d) - transformed["request_headers_to_remove"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(original["requestHeadersToRemove"], d) - transformed["response_headers_to_add"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(original["responseHeadersToAdd"], d) - transformed["response_headers_to_remove"] = - flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(original["responseHeadersToRemove"], d) - return []interface{}{transformed} +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) + req := 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 + if raw == nil { continue } - transformed = append(transformed, map[string]interface{}{ - "header_name": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d), - }) + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + transformedHeaderValue, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue + } + + transformedReplace, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(original["replace"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { + transformed["replace"] = transformedReplace + } + + req = append(req, transformed) } - return transformed + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { - return v + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } +func expandComputeUrlMapPathMatcherName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) + req := 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 + if raw == nil { continue } - transformed = append(transformed, map[string]interface{}{ - "header_name": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), - "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), - "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(original["replace"], d), - }) + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedService, err := expandComputeUrlMapPathMatcherPathRuleService(original["service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedService); val.IsValid() && !isEmptyValue(val) { + transformed["service"] = transformedService + } + + transformedPaths, err := expandComputeUrlMapPathMatcherPathRulePaths(original["paths"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPaths); val.IsValid() && !isEmptyValue(val) { + transformed["paths"] = transformedPaths + } + + transformedRouteAction, err := expandComputeUrlMapPathMatcherPathRuleRouteAction(original["route_action"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRouteAction); val.IsValid() && !isEmptyValue(val) { + transformed["routeAction"] = transformedRouteAction + } + + transformedUrlRedirect, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirect(original["url_redirect"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUrlRedirect); val.IsValid() && !isEmptyValue(val) { + transformed["urlRedirect"] = transformedUrlRedirect + } + + req = append(req, transformed) } - return transformed -} -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { - return v + return req, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRuleService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRulePaths(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + return v, nil } -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { - return v -} +func expandComputeUrlMapPathMatcherPathRuleRouteAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) -func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. + transformedCorsPolicy, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicy(original["cors_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCorsPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["corsPolicy"] = transformedCorsPolicy } - return v -} -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirect(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil + transformedFaultInjectionPolicy, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicy(original["fault_injection_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFaultInjectionPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["faultInjectionPolicy"] = transformedFaultInjectionPolicy } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil + + transformedRequestMirrorPolicy, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicy(original["request_mirror_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestMirrorPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["requestMirrorPolicy"] = transformedRequestMirrorPolicy } - transformed := make(map[string]interface{}) - transformed["host_redirect"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(original["hostRedirect"], d) - transformed["https_redirect"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(original["httpsRedirect"], d) - transformed["path_redirect"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(original["pathRedirect"], d) - transformed["prefix_redirect"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(original["prefixRedirect"], d) - transformed["redirect_response_code"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(original["redirectResponseCode"], d) - transformed["strip_query"] = - flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(original["stripQuery"], d) - return []interface{}{transformed} -} -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(v interface{}, d *schema.ResourceData) interface{} { - return v -} -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(v interface{}, d *schema.ResourceData) interface{} { - return v -} + transformedRetryPolicy, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicy(original["retry_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetryPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["retryPolicy"] = transformedRetryPolicy + } -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(v interface{}, d *schema.ResourceData) interface{} { - return v + transformedTimeout, err := expandComputeUrlMapPathMatcherPathRuleRouteActionTimeout(original["timeout"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTimeout); val.IsValid() && !isEmptyValue(val) { + transformed["timeout"] = transformedTimeout + } + + transformedUrlRewrite, err := expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewrite(original["url_rewrite"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUrlRewrite); val.IsValid() && !isEmptyValue(val) { + transformed["urlRewrite"] = transformedUrlRewrite + } + + transformedWeightedBackendServices, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServices(original["weighted_backend_services"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedWeightedBackendServices); val.IsValid() && !isEmptyValue(val) { + transformed["weightedBackendServices"] = transformedWeightedBackendServices + } + + return transformed, nil } -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(v interface{}, d *schema.ResourceData) interface{} { - return v -} +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAllowCredentials, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowCredentials(original["allow_credentials"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowCredentials); val.IsValid() && !isEmptyValue(val) { + transformed["allowCredentials"] = transformedAllowCredentials + } + + transformedAllowHeaders, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowHeaders(original["allow_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowHeaders); val.IsValid() && !isEmptyValue(val) { + transformed["allowHeaders"] = transformedAllowHeaders + } + + transformedAllowMethods, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowMethods(original["allow_methods"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowMethods); val.IsValid() && !isEmptyValue(val) { + transformed["allowMethods"] = transformedAllowMethods + } + + transformedAllowOriginRegexes, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOriginRegexes(original["allow_origin_regexes"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowOriginRegexes); val.IsValid() && !isEmptyValue(val) { + transformed["allowOriginRegexes"] = transformedAllowOriginRegexes + } + + transformedAllowOrigins, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOrigins(original["allow_origins"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowOrigins); val.IsValid() && !isEmptyValue(val) { + transformed["allowOrigins"] = transformedAllowOrigins + } + + transformedDisabled, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyDisabled(original["disabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDisabled); val.IsValid() && !isEmptyValue(val) { + transformed["disabled"] = transformedDisabled + } + + transformedExposeHeaders, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyExposeHeaders(original["expose_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExposeHeaders); val.IsValid() && !isEmptyValue(val) { + transformed["exposeHeaders"] = transformedExposeHeaders + } + + transformedMaxAge, err := expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyMaxAge(original["max_age"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMaxAge); val.IsValid() && !isEmptyValue(val) { + transformed["maxAge"] = transformedMaxAge + } -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(v interface{}, d *schema.ResourceData) interface{} { - return v + return transformed, nil } -func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowCredentials(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapTest(v interface{}, d *schema.ResourceData) 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{}{ - "description": flattenComputeUrlMapTestDescription(original["description"], d), - "host": flattenComputeUrlMapTestHost(original["host"], d), - "path": flattenComputeUrlMapTestPath(original["path"], d), - "service": flattenComputeUrlMapTestService(original["service"], d), - }) - } - return transformed -} -func flattenComputeUrlMapTestDescription(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowHeaders(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapTestHost(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowMethods(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapTestPath(v interface{}, d *schema.ResourceData) interface{} { - return v +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOriginRegexes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func flattenComputeUrlMapTestService(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyAllowOrigins(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } -func expandComputeUrlMapDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyExposeHeaders(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionCorsPolicyMaxAge(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { return nil, nil @@ -2705,261 +4306,292 @@ func expandComputeUrlMapHeaderAction(v interface{}, d TerraformResourceData, con original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedRequestHeadersToAdd, err := expandComputeUrlMapHeaderActionRequestHeadersToAdd(original["request_headers_to_add"], d, config) + transformedAbort, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbort(original["abort"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedRequestHeadersToAdd); val.IsValid() && !isEmptyValue(val) { - transformed["requestHeadersToAdd"] = transformedRequestHeadersToAdd + } else if val := reflect.ValueOf(transformedAbort); val.IsValid() && !isEmptyValue(val) { + transformed["abort"] = transformedAbort } - transformedRequestHeadersToRemove, err := expandComputeUrlMapHeaderActionRequestHeadersToRemove(original["request_headers_to_remove"], d, config) + transformedDelay, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelay(original["delay"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedRequestHeadersToRemove); val.IsValid() && !isEmptyValue(val) { - transformed["requestHeadersToRemove"] = transformedRequestHeadersToRemove + } else if val := reflect.ValueOf(transformedDelay); val.IsValid() && !isEmptyValue(val) { + transformed["delay"] = transformedDelay } - transformedResponseHeadersToAdd, err := expandComputeUrlMapHeaderActionResponseHeadersToAdd(original["response_headers_to_add"], d, config) + return transformed, nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHttpStatus, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortHttpStatus(original["http_status"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedResponseHeadersToAdd); val.IsValid() && !isEmptyValue(val) { - transformed["responseHeadersToAdd"] = transformedResponseHeadersToAdd + } else if val := reflect.ValueOf(transformedHttpStatus); val.IsValid() && !isEmptyValue(val) { + transformed["httpStatus"] = transformedHttpStatus } - transformedResponseHeadersToRemove, err := expandComputeUrlMapHeaderActionResponseHeadersToRemove(original["response_headers_to_remove"], d, config) + transformedPercentage, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortPercentage(original["percentage"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedResponseHeadersToRemove); val.IsValid() && !isEmptyValue(val) { - transformed["responseHeadersToRemove"] = transformedResponseHeadersToRemove + } else if val := reflect.ValueOf(transformedPercentage); val.IsValid() && !isEmptyValue(val) { + transformed["percentage"] = transformedPercentage } return transformed, nil } -func expandComputeUrlMapHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortHttpStatus(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelay(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) - transformedHeaderName, err := expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { - transformed["headerName"] = transformedHeaderName - } + transformedFixedDelay, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelay(original["fixed_delay"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFixedDelay); val.IsValid() && !isEmptyValue(val) { + transformed["fixedDelay"] = transformedFixedDelay + } - transformedHeaderValue, err := expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { - transformed["headerValue"] = transformedHeaderValue - } + transformedPercentage, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayPercentage(original["percentage"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPercentage); val.IsValid() && !isEmptyValue(val) { + transformed["percentage"] = transformedPercentage + } - transformedReplace, err := expandComputeUrlMapHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { - transformed["replace"] = transformedReplace - } + return transformed, nil +} - req = append(req, transformed) +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelay(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil } - return req, nil + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNanos, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelayNanos(original["nanos"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !isEmptyValue(val) { + transformed["nanos"] = transformedNanos + } + + transformedSeconds, err := expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(original["seconds"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !isEmptyValue(val) { + transformed["seconds"] = transformedSeconds + } + + return transformed, nil } -func expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelayNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionFaultInjectionPolicyDelayPercentage(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil +func expandComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedBackendService, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicyBackendService(original["backend_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedBackendService); val.IsValid() && !isEmptyValue(val) { + transformed["backendService"] = transformedBackendService + } + + return transformed, nil } -func expandComputeUrlMapHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionRequestMirrorPolicyBackendService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("backendServices", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for backend_service: %s", err) + } + return f.RelativeLink(), nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) - transformedHeaderName, err := expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(original["header_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { - transformed["headerName"] = transformedHeaderName - } + transformedNumRetries, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyNumRetries(original["num_retries"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNumRetries); val.IsValid() && !isEmptyValue(val) { + transformed["numRetries"] = transformedNumRetries + } - transformedHeaderValue, err := expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { - transformed["headerValue"] = transformedHeaderValue - } + transformedPerTryTimeout, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeout(original["per_try_timeout"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPerTryTimeout); val.IsValid() && !isEmptyValue(val) { + transformed["perTryTimeout"] = transformedPerTryTimeout + } - transformedReplace, err := expandComputeUrlMapHeaderActionResponseHeadersToAddReplace(original["replace"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { - transformed["replace"] = transformedReplace - } + transformedRetryConditions, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyRetryConditions(original["retry_conditions"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetryConditions); val.IsValid() && !isEmptyValue(val) { + transformed["retryConditions"] = transformedRetryConditions + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyNumRetries(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeout(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNanos, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutNanos(original["nanos"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !isEmptyValue(val) { + transformed["nanos"] = transformedNanos + } - req = append(req, transformed) + transformedSeconds, err := expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutSeconds(original["seconds"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !isEmptyValue(val) { + transformed["seconds"] = transformedSeconds } - return req, nil -} -func expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil + return transformed, nil } -func expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionRetryPolicyRetryConditions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapHostRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - v = v.(*schema.Set).List() +func expandComputeUrlMapPathMatcherPathRuleRouteActionTimeout(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedDescription, err := expandComputeUrlMapHostRuleDescription(original["description"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { - transformed["description"] = transformedDescription - } - - transformedHosts, err := expandComputeUrlMapHostRuleHosts(original["hosts"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHosts); val.IsValid() && !isEmptyValue(val) { - transformed["hosts"] = transformedHosts - } - - transformedPathMatcher, err := expandComputeUrlMapHostRulePathMatcher(original["path_matcher"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPathMatcher); val.IsValid() && !isEmptyValue(val) { - transformed["pathMatcher"] = transformedPathMatcher - } + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) - req = append(req, transformed) + transformedNanos, err := expandComputeUrlMapPathMatcherPathRuleRouteActionTimeoutNanos(original["nanos"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !isEmptyValue(val) { + transformed["nanos"] = transformedNanos } - return req, nil -} -func expandComputeUrlMapHostRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + transformedSeconds, err := expandComputeUrlMapPathMatcherPathRuleRouteActionTimeoutSeconds(original["seconds"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !isEmptyValue(val) { + transformed["seconds"] = transformedSeconds + } -func expandComputeUrlMapHostRuleHosts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - v = v.(*schema.Set).List() - return v, nil + return transformed, nil } -func expandComputeUrlMapHostRulePathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionTimeoutNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionTimeoutSeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewrite(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedDefaultService, err := expandComputeUrlMapPathMatcherDefaultService(original["default_service"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedDefaultService); val.IsValid() && !isEmptyValue(val) { - transformed["defaultService"] = transformedDefaultService - } - - transformedDescription, err := expandComputeUrlMapPathMatcherDescription(original["description"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { - transformed["description"] = transformedDescription - } - - transformedPathRule, err := expandComputeUrlMapPathMatcherPathRule(original["path_rule"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPathRule); val.IsValid() && !isEmptyValue(val) { - transformed["pathRules"] = transformedPathRule - } - - transformedHeaderAction, err := expandComputeUrlMapPathMatcherHeaderAction(original["header_action"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHeaderAction); val.IsValid() && !isEmptyValue(val) { - transformed["headerAction"] = transformedHeaderAction - } - - transformedName, err := expandComputeUrlMapPathMatcherName(original["name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { - transformed["name"] = transformedName - } + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) - transformedRouteRules, err := expandComputeUrlMapPathMatcherRouteRules(original["route_rules"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedRouteRules); val.IsValid() && !isEmptyValue(val) { - transformed["routeRules"] = transformedRouteRules - } + transformedHostRewrite, err := expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewriteHostRewrite(original["host_rewrite"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHostRewrite); val.IsValid() && !isEmptyValue(val) { + transformed["hostRewrite"] = transformedHostRewrite + } - req = append(req, transformed) + transformedPathPrefixRewrite, err := expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewritePathPrefixRewrite(original["path_prefix_rewrite"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPathPrefixRewrite); val.IsValid() && !isEmptyValue(val) { + transformed["pathPrefixRewrite"] = transformedPathPrefixRewrite } - return req, nil + + return transformed, nil } -func expandComputeUrlMapPathMatcherDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewriteHostRewrite(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionUrlRewritePathPrefixRewrite(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServices(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -2969,18 +4601,25 @@ func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceDa original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedPaths, err := expandComputeUrlMapPathMatcherPathRulePaths(original["paths"], d, config) + transformedBackendService, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesBackendService(original["backend_service"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedPaths); val.IsValid() && !isEmptyValue(val) { - transformed["paths"] = transformedPaths + } else if val := reflect.ValueOf(transformedBackendService); val.IsValid() && !isEmptyValue(val) { + transformed["backendService"] = transformedBackendService } - transformedService, err := expandComputeUrlMapPathMatcherPathRuleService(original["service"], d, config) + transformedHeaderAction, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderAction(original["header_action"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedService); val.IsValid() && !isEmptyValue(val) { - transformed["service"] = transformedService + } else if val := reflect.ValueOf(transformedHeaderAction); val.IsValid() && !isEmptyValue(val) { + transformed["headerAction"] = transformedHeaderAction + } + + transformedWeight, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesWeight(original["weight"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedWeight); val.IsValid() && !isEmptyValue(val) { + transformed["weight"] = transformedWeight } req = append(req, transformed) @@ -2988,16 +4627,15 @@ func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceDa return req, nil } -func expandComputeUrlMapPathMatcherPathRulePaths(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - v = v.(*schema.Set).List() - return v, nil -} - -func expandComputeUrlMapPathMatcherPathRuleService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesBackendService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("backendServices", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for backend_service: %s", err) + } + return f.RelativeLink(), nil } -func expandComputeUrlMapPathMatcherHeaderAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderAction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { return nil, nil @@ -3006,28 +4644,28 @@ func expandComputeUrlMapPathMatcherHeaderAction(v interface{}, d TerraformResour original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedRequestHeadersToAdd, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(original["request_headers_to_add"], d, config) + transformedRequestHeadersToAdd, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(original["request_headers_to_add"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedRequestHeadersToAdd); val.IsValid() && !isEmptyValue(val) { transformed["requestHeadersToAdd"] = transformedRequestHeadersToAdd } - transformedRequestHeadersToRemove, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(original["request_headers_to_remove"], d, config) + transformedRequestHeadersToRemove, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(original["request_headers_to_remove"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedRequestHeadersToRemove); val.IsValid() && !isEmptyValue(val) { transformed["requestHeadersToRemove"] = transformedRequestHeadersToRemove } - transformedResponseHeadersToAdd, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(original["response_headers_to_add"], d, config) + transformedResponseHeadersToAdd, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(original["response_headers_to_add"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedResponseHeadersToAdd); val.IsValid() && !isEmptyValue(val) { transformed["responseHeadersToAdd"] = transformedResponseHeadersToAdd } - transformedResponseHeadersToRemove, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(original["response_headers_to_remove"], d, config) + transformedResponseHeadersToRemove, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(original["response_headers_to_remove"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedResponseHeadersToRemove); val.IsValid() && !isEmptyValue(val) { @@ -3037,7 +4675,7 @@ func expandComputeUrlMapPathMatcherHeaderAction(v interface{}, d TerraformResour return transformed, nil } -func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -3047,21 +4685,21 @@ func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{} original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedHeaderName, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) + transformedHeaderName, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { transformed["headerName"] = transformedHeaderName } - transformedHeaderValue, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) + transformedHeaderValue, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { transformed["headerValue"] = transformedHeaderValue } - transformedReplace, err := expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) + transformedReplace, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { @@ -3073,23 +4711,23 @@ func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(v interface{} return req, nil } -func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -3099,21 +4737,21 @@ func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{ original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedHeaderName, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(original["header_name"], d, config) + transformedHeaderName, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["header_name"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { transformed["headerName"] = transformedHeaderName } - transformedHeaderValue, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], d, config) + transformedHeaderValue, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { transformed["headerValue"] = transformedHeaderValue } - transformedReplace, err := expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(original["replace"], d, config) + transformedReplace, err := expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(original["replace"], d, config) if err != nil { return nil, err } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { @@ -3125,23 +4763,101 @@ func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{ return req, nil } -func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherPathRuleRouteActionWeightedBackendServicesWeight(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHostRedirect, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectHostRedirect(original["host_redirect"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHostRedirect); val.IsValid() && !isEmptyValue(val) { + transformed["hostRedirect"] = transformedHostRedirect + } + + transformedHttpsRedirect, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectHttpsRedirect(original["https_redirect"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHttpsRedirect); val.IsValid() && !isEmptyValue(val) { + transformed["httpsRedirect"] = transformedHttpsRedirect + } + + transformedPathRedirect, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectPathRedirect(original["path_redirect"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPathRedirect); val.IsValid() && !isEmptyValue(val) { + transformed["pathRedirect"] = transformedPathRedirect + } + + transformedPrefixRedirect, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectPrefixRedirect(original["prefix_redirect"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefixRedirect); val.IsValid() && !isEmptyValue(val) { + transformed["prefixRedirect"] = transformedPrefixRedirect + } + + transformedRedirectResponseCode, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectRedirectResponseCode(original["redirect_response_code"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRedirectResponseCode); val.IsValid() && !isEmptyValue(val) { + transformed["redirectResponseCode"] = transformedRedirectResponseCode + } + + transformedStripQuery, err := expandComputeUrlMapPathMatcherPathRuleUrlRedirectStripQuery(original["strip_query"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedStripQuery); val.IsValid() && !isEmptyValue(val) { + transformed["stripQuery"] = transformedStripQuery + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectHostRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectHttpsRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectPathRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectPrefixRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectRedirectResponseCode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRuleUrlRedirectStripQuery(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_url_map_generated_test.go b/google/resource_compute_url_map_generated_test.go index 76a936705f3..f3074865a4e 100644 --- a/google/resource_compute_url_map_generated_test.go +++ b/google/resource_compute_url_map_generated_test.go @@ -321,6 +321,239 @@ resource "google_compute_health_check" "default" { `, context) } +func TestAccComputeUrlMap_urlMapTrafficDirectorPathExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeUrlMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_urlMapTrafficDirectorPathExample(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeUrlMap_urlMapTrafficDirectorPathExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_url_map" "urlmap" { + name = "urlmap%{random_suffix}" + 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 = "home%{random_suffix}" + 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 = "health-check%{random_suffix}" + http_health_check { + port = 80 + } +} +`, context) +} + +func TestAccComputeUrlMap_urlMapTrafficDirectorPathPartialExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeUrlMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_urlMapTrafficDirectorPathPartialExample(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeUrlMap_urlMapTrafficDirectorPathPartialExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_url_map" "urlmap" { + name = "urlmap%{random_suffix}" + 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 = "home%{random_suffix}" + 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 = "health-check%{random_suffix}" + http_health_check { + port = 80 + } +} +`, context) +} + func testAccCheckComputeUrlMapDestroy(s *terraform.State) error { for name, rs := range s.RootModule().Resources { if rs.Type != "google_compute_url_map" { diff --git a/google/resource_compute_url_map_test.go b/google/resource_compute_url_map_test.go index 7fc85b803fd..2de743f5afe 100644 --- a/google/resource_compute_url_map_test.go +++ b/google/resource_compute_url_map_test.go @@ -155,6 +155,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() @@ -671,3 +704,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) +} diff --git a/website/docs/r/compute_url_map.html.markdown b/website/docs/r/compute_url_map.html.markdown index 5eda49241f1..04cf7ce1c29 100644 --- a/website/docs/r/compute_url_map.html.markdown +++ b/website/docs/r/compute_url_map.html.markdown @@ -264,6 +264,201 @@ resource "google_compute_backend_service" "home" { load_balancing_scheme = "INTERNAL_SELF_MANAGED" } +resource "google_compute_health_check" "default" { + name = "health-check" + http_health_check { + port = 80 + } +} +``` + +## Example Usage - Url Map Traffic Director Path + + +```hcl +resource "google_compute_url_map" "urlmap" { + name = "urlmap" + 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 = "home" + 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 = "health-check" + http_health_check { + port = 80 + } +} +``` + +## Example Usage - Url Map Traffic Director Path Partial + + +```hcl +resource "google_compute_url_map" "urlmap" { + name = "urlmap" + 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 = "home" + 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 = "health-check" http_health_check { @@ -406,10 +601,6 @@ The `path_matcher` block supports: An optional description of this resource. Provide this property when you create the resource. -* `path_rule` - - (Optional) - The list of path rules. Structure is documented below. - * `header_action` - (Optional) Specifies changes to request and response headers that need to take effect for @@ -420,6 +611,15 @@ The `path_matcher` block supports: (Required) The name to which this PathMatcher is referred by the HostRule. +* `path_rule` - + (Optional) + 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. Structure is documented below. + * `route_rules` - (Optional) The list of ordered HTTP route rules. Use this list instead of pathRules when @@ -430,19 +630,337 @@ The `path_matcher` block supports: External load balancers. Structure is documented below. +The `header_action` block supports: + +* `request_headers_to_add` - + (Optional) + Headers to add to a matching request prior to forwarding the request to the + backendService. Structure is documented below. + +* `request_headers_to_remove` - + (Optional) + A list of header names for headers that need to be removed from the request + prior to forwarding the request to the backendService. + +* `response_headers_to_add` - + (Optional) + Headers to add the response prior to sending the response back to the client. Structure is documented below. + +* `response_headers_to_remove` - + (Optional) + A list of header names for headers that need to be removed from the response + prior to sending the response back to the client. + + +The `request_headers_to_add` block supports: + +* `header_name` - + (Required) + The name of the header. + +* `header_value` - + (Required) + The value of the header to add. + +* `replace` - + (Required) + 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. + +The `response_headers_to_add` block supports: + +* `header_name` - + (Required) + The name of the header. + +* `header_value` - + (Required) + The value of the header to add. + +* `replace` - + (Required) + 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. + The `path_rule` block supports: +* `service` - + (Optional) + The backend service or backend bucket to use if any of the given paths match. + * `paths` - (Required) - 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 + 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. -* `service` - +* `route_action` - + (Optional) + 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. Structure is documented below. + +* `url_redirect` - + (Optional) + 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. Structure is documented below. + + +The `route_action` block supports: + +* `cors_policy` - + (Optional) + The specification for allowing client side cross-origin requests. Please see W3C + Recommendation for Cross Origin Resource Sharing Structure is documented below. + +* `fault_injection_policy` - + (Optional) + 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. Structure is documented below. + +* `request_mirror_policy` - + (Optional) + 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. Structure is documented below. + +* `retry_policy` - + (Optional) + Specifies the retry policy associated with this route. Structure is documented below. + +* `timeout` - + (Optional) + 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. Structure is documented below. + +* `url_rewrite` - + (Optional) + The spec to modify the URL of the request, prior to forwarding the request to + the matched service Structure is documented below. + +* `weighted_backend_services` - + (Optional) + 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. Structure is documented below. + + +The `cors_policy` block supports: + +* `allow_credentials` - + (Optional) + 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. + +* `allow_headers` - + (Optional) + Specifies the content for the Access-Control-Allow-Headers header. + +* `allow_methods` - + (Optional) + Specifies the content for the Access-Control-Allow-Methods header. + +* `allow_origin_regexes` - + (Optional) + 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. + +* `allow_origins` - + (Optional) + 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. + +* `disabled` - (Required) - The backend service or backend bucket to use if any of the given paths match. + If true, specifies the CORS policy is disabled. + +* `expose_headers` - + (Optional) + Specifies the content for the Access-Control-Expose-Headers header. + +* `max_age` - + (Optional) + Specifies how long the results of a preflight request can be cached. This + translates to the content for the Access-Control-Max-Age header. + +The `fault_injection_policy` block supports: + +* `abort` - + (Optional) + The specification for how client requests are aborted as part of fault + injection. Structure is documented below. + +* `delay` - + (Optional) + The specification for how client requests are delayed as part of fault + injection, before being sent to a backend service. Structure is documented below. + + +The `abort` block supports: + +* `http_status` - + (Required) + The HTTP status code used to abort the request. The value must be between 200 + and 599 inclusive. + +* `percentage` - + (Required) + 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. + +The `delay` block supports: + +* `fixed_delay` - + (Required) + Specifies the value of the fixed delay interval. Structure is documented below. + +* `percentage` - + (Required) + 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. + + +The `fixed_delay` block supports: + +* `nanos` - + (Optional) + 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. + +* `seconds` - + (Required) + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + +The `request_mirror_policy` block supports: + +* `backend_service` - + (Required) + The BackendService resource being mirrored to. + +The `retry_policy` block supports: + +* `num_retries` - + (Optional) + Specifies the allowed number retries. This number must be > 0. + +* `per_try_timeout` - + (Optional) + Specifies a non-zero timeout per retry attempt. Structure is documented below. + +* `retry_conditions` - + (Optional) + 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 + + +The `per_try_timeout` block supports: + +* `nanos` - + (Optional) + 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. + +* `seconds` - + (Required) + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + +The `timeout` block supports: + +* `nanos` - + (Optional) + 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. + +* `seconds` - + (Required) + Span of time at a resolution of a second. Must be from 0 to 315,576,000,000 + inclusive. + +The `url_rewrite` block supports: + +* `host_rewrite` - + (Optional) + 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. + +* `path_prefix_rewrite` - + (Optional) + 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. + +The `weighted_backend_services` block supports: + +* `backend_service` - + (Required) + The default BackendService resource. Before + forwarding the request to backendService, the loadbalancer applies any relevant + headerActions specified as part of this backendServiceWeight. + +* `header_action` - + (Optional) + 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. Structure is documented below. + +* `weight` - + (Optional) + 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 + The `header_action` block supports: @@ -498,6 +1016,48 @@ The `response_headers_to_add` block supports: header. If true, headerValue is set for the header, discarding any values that were set for that header. +The `url_redirect` block supports: + +* `host_redirect` - + (Optional) + 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. + +* `https_redirect` - + (Optional) + 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. + +* `path_redirect` - + (Optional) + 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. + +* `prefix_redirect` - + (Optional) + The prefix that replaces the prefixMatch specified in the HttpRouteRuleMatch, + retaining the remaining portion of the URL before redirecting the request. + +* `redirect_response_code` - + (Optional) + 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. + +* `strip_query` - + (Required) + 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. + The `route_rules` block supports: * `priority` -