diff --git a/google/resource_compute_url_map.go b/google/resource_compute_url_map.go index c6264ad75fa..ee62879e772 100644 --- a/google/resource_compute_url_map.go +++ b/google/resource_compute_url_map.go @@ -22,6 +22,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) func resourceComputeUrlMap() *schema.Resource { @@ -42,29 +43,115 @@ func resourceComputeUrlMap() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "default_service": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The backend service or backend bucket to use when none of the given rules match.`, - }, "name": { Type: schema.TypeString, Required: true, ForceNew: true, - Description: `Name of the resource. Provided by the client when the resource is -created. The name must be 1-63 characters long, and comply with -RFC1035. Specifically, the name must be 1-63 characters long and match -the regular expression '[a-z]([-a-z0-9]*[a-z0-9])?' which means the -first character must be a lowercase letter, and all following -characters must be a dash, lowercase letter, or digit, except the last -character, which cannot be a dash.`, + Description: `Name of the resource. Provided by the client when the resource is created. The +name must be 1-63 characters long, and comply with RFC1035. Specifically, the +name must be 1-63 characters long and match the regular expression +'[a-z]([-a-z0-9]*[a-z0-9])?' which means the first character must be a lowercase +letter, and all following characters must be a dash, lowercase letter, or digit, +except the last character, which cannot be a dash.`, + }, + "default_service": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The backend service or backend bucket to use when none of the given rules match.`, }, "description": { Type: schema.TypeString, Optional: true, - Description: `An optional description of this resource. Provide this property when -you create the resource.`, + Description: `An optional description of this resource. Provide this property when you create +the resource.`, + }, + "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 take effect after +headerAction specified under pathMatcher.`, + 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.`, + }, + }, + }, + AtLeastOneOf: []string{"header_action.0.request_headers_to_add", "header_action.0.request_headers_to_remove", "header_action.0.response_headers_to_add", "header_action.0.response_headers_to_remove"}, + }, + "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, + }, + AtLeastOneOf: []string{"header_action.0.request_headers_to_add", "header_action.0.request_headers_to_remove", "header_action.0.response_headers_to_add", "header_action.0.response_headers_to_remove"}, + }, + "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.`, + }, + }, + }, + AtLeastOneOf: []string{"header_action.0.request_headers_to_add", "header_action.0.request_headers_to_remove", "header_action.0.response_headers_to_add", "header_action.0.response_headers_to_remove"}, + }, + "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, + }, + AtLeastOneOf: []string{"header_action.0.request_headers_to_add", "header_action.0.request_headers_to_remove", "header_action.0.response_headers_to_add", "header_action.0.response_headers_to_remove"}, + }, + }, + }, }, "host_rule": { Type: schema.TypeSet, @@ -79,21 +166,105 @@ you create the resource.`, Description: `The list of named PathMatchers to use against the URL.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "default_service": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The backend service or backend bucket to use when none of the given paths match.`, - }, "name": { Type: schema.TypeString, Required: true, Description: `The name to which this PathMatcher is referred by the HostRule.`, }, + "default_service": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The backend service or backend bucket to use when none of the given paths match.`, + }, "description": { - Type: schema.TypeString, - Optional: true, - Description: `An optional description of this resource.`, + Type: schema.TypeString, + Optional: true, + Description: `An optional description of this resource. Provide this property when you create +the resource.`, + }, + "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 are applied after the +matching HttpRouteRule HeaderAction and before the HeaderAction in the 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, + }, + }, + }, + }, }, "path_rule": { Type: schema.TypeList, @@ -123,14 +294,840 @@ allowed here.`, }, }, }, + "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 mappings. Requests to update this UrlMap will -succeed only if all of the test cases pass.`, + 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": { @@ -165,8 +1162,8 @@ succeed only if all of the test cases pass.`, "fingerprint": { Type: schema.TypeString, Computed: true, - Description: `Fingerprint of this resource. This field is used internally during -updates of this resource.`, + Description: `Fingerprint of this resource. A hash of the contents stored in this object. This +field is used in optimistic locking.`, }, "map_id": { Type: schema.TypeInt, @@ -193,10 +1190,9 @@ func computeUrlMapHostRuleSchema() *schema.Resource { "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 ..`, + 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, }, @@ -205,14 +1201,14 @@ the pattern by either - or ..`, "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: `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 HostRule. Provide this property -when you create the resource.`, + Description: `An optional description of this resource. Provide this property when you create +the resource.`, }, }, } @@ -234,18 +1230,24 @@ func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { obj["description"] = descriptionProp } - 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 - } 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 @@ -332,15 +1334,18 @@ func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("description", flattenComputeUrlMapDescription(res["description"], 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("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) } @@ -378,18 +1383,24 @@ func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { obj["description"] = descriptionProp } - 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 - } 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 @@ -500,6 +1511,111 @@ func flattenComputeUrlMapDescription(v interface{}, d *schema.ResourceData) inte 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 @@ -535,20 +1651,6 @@ func flattenComputeUrlMapHostRulePathMatcher(v interface{}, d *schema.ResourceDa 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 flattenComputeUrlMapName(v interface{}, d *schema.ResourceData) interface{} { return v } @@ -568,8 +1670,10 @@ func flattenComputeUrlMapPathMatcher(v interface{}, d *schema.ResourceData) inte transformed = append(transformed, map[string]interface{}{ "default_service": flattenComputeUrlMapPathMatcherDefaultService(original["defaultService"], d), "description": flattenComputeUrlMapPathMatcherDescription(original["description"], d), - "name": flattenComputeUrlMapPathMatcherName(original["name"], d), "path_rule": flattenComputeUrlMapPathMatcherPathRule(original["pathRules"], d), + "header_action": flattenComputeUrlMapPathMatcherHeaderAction(original["headerAction"], d), + "name": flattenComputeUrlMapPathMatcherName(original["name"], d), + "route_rules": flattenComputeUrlMapPathMatcherRouteRules(original["routeRules"], d), }) } return transformed @@ -585,10 +1689,6 @@ func flattenComputeUrlMapPathMatcherDescription(v interface{}, d *schema.Resourc 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 @@ -622,7 +1722,26 @@ func flattenComputeUrlMapPathMatcherPathRuleService(v interface{}, d *schema.Res return ConvertSelfLinkToV1(v.(string)) } -func flattenComputeUrlMapTest(v interface{}, d *schema.ResourceData) interface{} { +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 } @@ -635,39 +1754,1090 @@ func flattenComputeUrlMapTest(v interface{}, d *schema.ResourceData) interface{} 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), + "header_name": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(original["replace"], d), }) } return transformed } -func flattenComputeUrlMapTestDescription(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapTestHost(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapTestPath(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { return v } -func flattenComputeUrlMapTestService(v interface{}, d *schema.ResourceData) interface{} { +func flattenComputeUrlMapPathMatcherHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(v interface{}, d *schema.ResourceData) interface{} { if v == nil { return v } - return ConvertSelfLinkToV1(v.(string)) + 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 expandComputeUrlMapDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil +func flattenComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v } -func expandComputeUrlMapDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil +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 flattenComputeUrlMapPathMatcherRouteRules(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{}{ + "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), + }) + } + 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. + } + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderAction(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"] = + 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 + } + 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{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRules(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{}{ + "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 +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(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": 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 flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(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["range_end"] = + flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(original["rangeEnd"], d) + transformed["range_start"] = + flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(original["rangeStart"], 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. + } + 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. + } + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(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 flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(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{}{ + "name": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(original["name"], d), + "value": flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(original["value"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(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 +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteAction(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"] = + 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 + } + 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 flattenComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 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 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 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 v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 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 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 flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(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 flattenComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +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 +} + +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. + } + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(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"] = + 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. + } + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(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["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 +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(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{}{ + "backend_service": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(original["backendService"], d), + "header_action": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(original["headerAction"], d), + "weight": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(original["weight"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +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 flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(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": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 + } + 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": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["headerName"], d), + "header_value": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["headerValue"], d), + "replace": flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(original["replace"], d), + }) + } + return transformed +} +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 flattenComputeUrlMapPathMatcherRouteRulesUrlRedirect(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["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 +} + +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +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 flattenComputeUrlMapTestHost(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapTestPath(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeUrlMapTestService(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func expandComputeUrlMapDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, 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{}) + + 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 + } + + 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 + } + + 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 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 expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHeaderActionRequestHeadersToAddReplace(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 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 expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil } func expandComputeUrlMapHostRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { @@ -681,25 +2851,1324 @@ func expandComputeUrlMapHostRule(v interface{}, d TerraformResourceData, config original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedDescription, err := expandComputeUrlMapHostRuleDescription(original["description"], d, config) + 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 req, nil +} + +func expandComputeUrlMapHostRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapHostRuleHosts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + return v, nil +} + +func expandComputeUrlMapHostRulePathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +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 + } + + 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 + } + + 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 + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherPathRule(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{}) + + 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 + } + + 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 + } + + req = append(req, transformed) + } + 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 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{}) + + 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 + } + + 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 + } + + 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 + } + + 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 + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAdd(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 := 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 req, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +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 expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAdd(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 := 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 req, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRules(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{}) + + transformedPriority, err := expandComputeUrlMapPathMatcherRouteRulesPriority(original["priority"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPriority); val.IsValid() && !isEmptyValue(val) { + transformed["priority"] = transformedPriority + } + + transformedHeaderAction, err := expandComputeUrlMapPathMatcherRouteRulesHeaderAction(original["header_action"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderAction); val.IsValid() && !isEmptyValue(val) { + transformed["headerAction"] = transformedHeaderAction + } + + transformedMatchRules, err := expandComputeUrlMapPathMatcherRouteRulesMatchRules(original["match_rules"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMatchRules); val.IsValid() && !isEmptyValue(val) { + transformed["matchRules"] = transformedMatchRules + } + + transformedRouteAction, err := expandComputeUrlMapPathMatcherRouteRulesRouteAction(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirect(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 req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesPriority(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderAction(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{}) + + transformedRequestHeadersToAdd, err := expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(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 expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAdd(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(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 expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAdd(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(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 := expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(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 expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRules(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{}) + + transformedFullPathMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(original["full_path_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFullPathMatch); val.IsValid() && !isEmptyValue(val) { + transformed["fullPathMatch"] = transformedFullPathMatch + } + + transformedHeaderMatches, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(original["header_matches"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderMatches); val.IsValid() && !isEmptyValue(val) { + transformed["headerMatches"] = transformedHeaderMatches + } + + transformedIgnoreCase, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(original["ignore_case"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIgnoreCase); val.IsValid() && !isEmptyValue(val) { + transformed["ignoreCase"] = transformedIgnoreCase + } + + transformedMetadataFilters, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(original["metadata_filters"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMetadataFilters); val.IsValid() && !isEmptyValue(val) { + transformed["metadataFilters"] = transformedMetadataFilters + } + + transformedPrefixMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(original["prefix_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefixMatch); val.IsValid() && !isEmptyValue(val) { + transformed["prefixMatch"] = transformedPrefixMatch + } + + transformedQueryParameterMatches, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(original["query_parameter_matches"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedQueryParameterMatches); val.IsValid() && !isEmptyValue(val) { + transformed["queryParameterMatches"] = transformedQueryParameterMatches + } + + transformedRegexMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(original["regex_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRegexMatch); val.IsValid() && !isEmptyValue(val) { + transformed["regexMatch"] = transformedRegexMatch + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesFullPathMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatches(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{}) + + transformedExactMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(original["exact_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExactMatch); val.IsValid() && !isEmptyValue(val) { + transformed["exactMatch"] = transformedExactMatch + } + + transformedHeaderName, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + transformedInvertMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(original["invert_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedInvertMatch); val.IsValid() && !isEmptyValue(val) { + transformed["invertMatch"] = transformedInvertMatch + } + + transformedPrefixMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(original["prefix_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPrefixMatch); val.IsValid() && !isEmptyValue(val) { + transformed["prefixMatch"] = transformedPrefixMatch + } + + transformedPresentMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(original["present_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPresentMatch); val.IsValid() && !isEmptyValue(val) { + transformed["presentMatch"] = transformedPresentMatch + } + + transformedRangeMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(original["range_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRangeMatch); val.IsValid() && !isEmptyValue(val) { + transformed["rangeMatch"] = transformedRangeMatch + } + + transformedRegexMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(original["regex_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRegexMatch); val.IsValid() && !isEmptyValue(val) { + transformed["regexMatch"] = transformedRegexMatch + } + + transformedSuffixMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(original["suffix_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSuffixMatch); val.IsValid() && !isEmptyValue(val) { + transformed["suffixMatch"] = transformedSuffixMatch + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesExactMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesInvertMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPrefixMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesPresentMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatch(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{}) + + transformedRangeEnd, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(original["range_end"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRangeEnd); val.IsValid() && !isEmptyValue(val) { + transformed["rangeEnd"] = transformedRangeEnd + } + + transformedRangeStart, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(original["range_start"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRangeStart); val.IsValid() && !isEmptyValue(val) { + transformed["rangeStart"] = transformedRangeStart + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeEnd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRangeMatchRangeStart(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesRegexMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesHeaderMatchesSuffixMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesIgnoreCase(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFilters(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{}) + + transformedFilterLabels, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(original["filter_labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFilterLabels); val.IsValid() && !isEmptyValue(val) { + transformed["filterLabels"] = transformedFilterLabels + } + + transformedFilterMatchCriteria, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(original["filter_match_criteria"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFilterMatchCriteria); val.IsValid() && !isEmptyValue(val) { + transformed["filterMatchCriteria"] = transformedFilterMatchCriteria + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabels(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{}) + + transformedName, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { + transformed["name"] = transformedName + } + + transformedValue, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(original["value"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedValue); val.IsValid() && !isEmptyValue(val) { + transformed["value"] = transformedValue + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterLabelsValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesMetadataFiltersFilterMatchCriteria(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesPrefixMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatches(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{}) + + transformedExactMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(original["exact_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExactMatch); val.IsValid() && !isEmptyValue(val) { + transformed["exactMatch"] = transformedExactMatch + } + + transformedName, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { + transformed["name"] = transformedName + } + + transformedPresentMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(original["present_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPresentMatch); val.IsValid() && !isEmptyValue(val) { + transformed["presentMatch"] = transformedPresentMatch + } + + transformedRegexMatch, err := expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(original["regex_match"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRegexMatch); val.IsValid() && !isEmptyValue(val) { + transformed["regexMatch"] = transformedRegexMatch + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesExactMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesPresentMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesQueryParameterMatchesRegexMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesMatchRulesRegexMatch(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteAction(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{}) + + transformedCorsPolicy, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(original["cors_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCorsPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["corsPolicy"] = transformedCorsPolicy + } + + transformedFaultInjectionPolicy, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(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 + } + + transformedRequestMirrorPolicy, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(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 + } + + transformedRetryPolicy, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(original["retry_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetryPolicy); val.IsValid() && !isEmptyValue(val) { + transformed["retryPolicy"] = transformedRetryPolicy + } + + transformedTimeout, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicy(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(original["max_age"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMaxAge); val.IsValid() && !isEmptyValue(val) { + transformed["maxAge"] = transformedMaxAge + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowCredentials(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowHeaders(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowMethods(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOriginRegexes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyAllowOrigins(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyExposeHeaders(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionCorsPolicyMaxAge(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicy(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{}) + + transformedAbort, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(original["abort"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAbort); val.IsValid() && !isEmptyValue(val) { + transformed["abort"] = transformedAbort + } + + transformedDelay, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(original["delay"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDelay); val.IsValid() && !isEmptyValue(val) { + transformed["delay"] = transformedDelay + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbort(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(original["http_status"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHttpStatus); val.IsValid() && !isEmptyValue(val) { + transformed["httpStatus"] = transformedHttpStatus + } + + transformedPercentage, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(original["percentage"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPercentage); val.IsValid() && !isEmptyValue(val) { + transformed["percentage"] = transformedPercentage + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortHttpStatus(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyAbortPercentage(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelay(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{}) + + transformedFixedDelay, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(original["fixed_delay"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFixedDelay); val.IsValid() && !isEmptyValue(val) { + transformed["fixedDelay"] = transformedFixedDelay + } + + transformedPercentage, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(original["percentage"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPercentage); val.IsValid() && !isEmptyValue(val) { + transformed["percentage"] = transformedPercentage + } + + return transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelay(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelayNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayFixedDelaySeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionFaultInjectionPolicyDelayPercentage(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicy(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionRequestMirrorPolicyBackendService(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicy(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{}) + + transformedNumRetries, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(original["num_retries"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNumRetries); val.IsValid() && !isEmptyValue(val) { + transformed["numRetries"] = transformedNumRetries + } + + transformedPerTryTimeout, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(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 + } + + transformedRetryConditions, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyNumRetries(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeout(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyPerTryTimeoutSeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionRetryPolicyRetryConditions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeout(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(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 expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutNanos(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionTimeoutSeconds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewrite(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{}) + + transformedHostRewrite, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(original["host_rewrite"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHostRewrite); val.IsValid() && !isEmptyValue(val) { + transformed["hostRewrite"] = transformedHostRewrite + } + + transformedPathPrefixRewrite, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(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 transformed, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewriteHostRewrite(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionUrlRewritePathPrefixRewrite(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServices(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{}) + + transformedBackendService, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(original["backend_service"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { - transformed["description"] = transformedDescription + } else if val := reflect.ValueOf(transformedBackendService); val.IsValid() && !isEmptyValue(val) { + transformed["backendService"] = transformedBackendService } - transformedHosts, err := expandComputeUrlMapHostRuleHosts(original["hosts"], d, config) + transformedHeaderAction, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(original["header_action"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedHosts); val.IsValid() && !isEmptyValue(val) { - transformed["hosts"] = transformedHosts + } else if val := reflect.ValueOf(transformedHeaderAction); val.IsValid() && !isEmptyValue(val) { + transformed["headerAction"] = transformedHeaderAction } - transformedPathMatcher, err := expandComputeUrlMapHostRulePathMatcher(original["path_matcher"], d, config) + transformedWeight, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(original["weight"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedPathMatcher); val.IsValid() && !isEmptyValue(val) { - transformed["pathMatcher"] = transformedPathMatcher + } else if val := reflect.ValueOf(transformedWeight); val.IsValid() && !isEmptyValue(val) { + transformed["weight"] = transformedWeight } req = append(req, transformed) @@ -707,28 +4176,55 @@ func expandComputeUrlMapHostRule(v interface{}, d TerraformResourceData, config return req, nil } -func expandComputeUrlMapHostRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesBackendService(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 expandComputeUrlMapHostRuleHosts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - v = v.(*schema.Set).List() - return v, nil -} +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderAction(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 expandComputeUrlMapHostRulePathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + transformedRequestHeadersToAdd, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(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 + } -func expandComputeUrlMapFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + transformedRequestHeadersToRemove, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(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 expandComputeUrlMapName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil + transformedResponseHeadersToAdd, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(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 := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(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 expandComputeUrlMapPathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -738,32 +4234,25 @@ func expandComputeUrlMapPathMatcher(v interface{}, d TerraformResourceData, conf 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) + transformedHeaderName, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(original["header_name"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { - transformed["description"] = transformedDescription + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName } - transformedName, err := expandComputeUrlMapPathMatcherName(original["name"], d, config) + transformedHeaderValue, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(original["header_value"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { - transformed["name"] = transformedName + } else if val := reflect.ValueOf(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue } - transformedPathRule, err := expandComputeUrlMapPathMatcherPathRule(original["path_rule"], d, config) + transformedReplace, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(original["replace"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedPathRule); val.IsValid() && !isEmptyValue(val) { - transformed["pathRules"] = transformedPathRule + } else if val := reflect.ValueOf(transformedReplace); val.IsValid() && !isEmptyValue(val) { + transformed["replace"] = transformedReplace } req = append(req, transformed) @@ -771,19 +4260,23 @@ func expandComputeUrlMapPathMatcher(v interface{}, d TerraformResourceData, conf return req, nil } -func expandComputeUrlMapPathMatcherDefaultService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionRequestHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAdd(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) for _, raw := range l { @@ -793,18 +4286,25 @@ func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceDa original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) - transformedPaths, err := expandComputeUrlMapPathMatcherPathRulePaths(original["paths"], d, config) + transformedHeaderName, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(original["header_name"], 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(transformedHeaderName); val.IsValid() && !isEmptyValue(val) { + transformed["headerName"] = transformedHeaderName } - transformedService, err := expandComputeUrlMapPathMatcherPathRuleService(original["service"], d, config) + transformedHeaderValue, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(original["header_value"], 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(transformedHeaderValue); val.IsValid() && !isEmptyValue(val) { + transformed["headerValue"] = transformedHeaderValue + } + + transformedReplace, err := expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(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) @@ -812,12 +4312,101 @@ func expandComputeUrlMapPathMatcherPathRule(v interface{}, d TerraformResourceDa return req, nil } -func expandComputeUrlMapPathMatcherPathRulePaths(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - v = v.(*schema.Set).List() +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } -func expandComputeUrlMapPathMatcherPathRuleService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddHeaderValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToAddReplace(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesHeaderActionResponseHeadersToRemove(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesRouteActionWeightedBackendServicesWeight(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirect(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(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 := expandComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(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 expandComputeUrlMapPathMatcherRouteRulesUrlRedirectHostRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirectHttpsRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirectPathRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirectPrefixRedirect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirectRedirectResponseCode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPathMatcherRouteRulesUrlRedirectStripQuery(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 6e841894015..76a936705f3 100644 --- a/google/resource_compute_url_map_generated_test.go +++ b/google/resource_compute_url_map_generated_test.go @@ -126,6 +126,201 @@ resource "google_storage_bucket" "static" { `, context) } +func TestAccComputeUrlMap_urlMapTrafficDirectorRouteExample(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_urlMapTrafficDirectorRouteExample(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeUrlMap_urlMapTrafficDirectorRouteExample(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}" + + route_rules { + priority = 1 + header_action { + request_headers_to_remove = ["RemoveMe2"] + request_headers_to_add { + header_name = "AddSomethingElse" + header_value = "MyOtherValue" + replace = true + } + response_headers_to_remove = ["RemoveMe3"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + match_rules { + full_path_match = "a full path" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + ignore_case = true + metadata_filters { + filter_match_criteria = "MATCH_ANY" + filter_labels { + name = "PLANET" + value = "MARS" + } + } + query_parameter_matches { + name = "a query parameter" + present_match = true + } + } + url_redirect { + host_redirect = "A host" + https_redirect = false + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = true + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "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_urlMapTrafficDirectorRoutePartialExample(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_urlMapTrafficDirectorRoutePartialExample(context), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeUrlMap_urlMapTrafficDirectorRoutePartialExample(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}" + + route_rules { + priority = 1 + match_rules { + prefix_match = "/someprefix" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + } + url_redirect { + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + } + } + } + + 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 5b61c498d56..7fc85b803fd 100644 --- a/google/resource_compute_url_map_test.go +++ b/google/resource_compute_url_map_test.go @@ -122,6 +122,72 @@ func testAccCheckComputeUrlMapExists(n string) resource.TestCheckFunc { } } +func TestAccComputeUrlMap_trafficDirectorUpdate(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_trafficDirector(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_trafficDirectorUpdate(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeUrlMap_trafficDirectorRemoveRouteRule(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_trafficDirector(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeUrlMap_trafficDirectorRemoveRouteRule(bsName, hcName, umName), + }, + { + ResourceName: "google_compute_url_map.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccComputeUrlMap_basic1(bsName, hcName, umName string) string { return fmt.Sprintf(` resource "google_compute_backend_service" "foobar" { @@ -364,3 +430,244 @@ resource "google_compute_url_map" "foobar" { } `, bsName, hcName, umName) } + +func testAccComputeUrlMap_trafficDirector(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths" + } + + path_matcher { + name = "allpaths" + default_service = "${google_compute_backend_service.home.self_link}" + + route_rules { + priority = 1 + header_action { + request_headers_to_remove = ["RemoveMe2"] + request_headers_to_add { + header_name = "AddSomethingElse" + header_value = "MyOtherValue" + replace = true + } + response_headers_to_remove = ["RemoveMe3"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + match_rules { + full_path_match = "a full path" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + ignore_case = true + metadata_filters { + filter_match_criteria = "MATCH_ANY" + filter_labels { + name = "PLANET" + value = "MARS" + } + } + query_parameter_matches { + name = "a query parameter" + present_match = true + } + } + url_redirect { + host_redirect = "A host" + https_redirect = false + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = true + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} + +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorUpdate(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home2.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + default_service = "${google_compute_backend_service.home2.self_link}" + + route_rules { + priority = 2 + header_action { + request_headers_to_remove = ["RemoveMe2", "AndMe"] + request_headers_to_add { + header_name = "AddSomethingElseUpdated" + header_value = "MyOtherValueUpdated" + replace = false + } + response_headers_to_remove = ["RemoveMe3", "AndMe4"] + } + match_rules { + full_path_match = "a full path to match" + header_matches { + header_name = "someheaderfoo" + exact_match = "match this exactly again" + invert_match = false + } + ignore_case = false + metadata_filters { + filter_match_criteria = "MATCH_ALL" + filter_labels { + name = "PLANET" + value = "EARTH" + } + } + } + url_redirect { + host_redirect = "A host again" + https_redirect = true + path_redirect = "some/path/twice" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = false + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} + +func testAccComputeUrlMap_trafficDirectorRemoveRouteRule(bsName, hcName, umName string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "foobar" { + name = "%s" + description = "a description" + default_service = "${google_compute_backend_service.home2.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths2" + } + + path_matcher { + name = "allpaths2" + default_service = "${google_compute_backend_service.home2.self_link}" + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_backend_service" "home2" { + name = "%s-2" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_health_check.default.self_link}"] + load_balancing_scheme = "INTERNAL_SELF_MANAGED" +} + +resource "google_compute_health_check" "default" { + name = "%s" + http_health_check { + port = 80 + } +} +`, umName, bsName, bsName, hcName) +} diff --git a/google/resource_sql_database_instance_test.go b/google/resource_sql_database_instance_test.go index 402fe1699bc..4c96a3d03b9 100644 --- a/google/resource_sql_database_instance_test.go +++ b/google/resource_sql_database_instance_test.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" - sqladmin "google.golang.org/api/sqladmin/v1beta4" ) diff --git a/website/docs/r/compute_url_map.html.markdown b/website/docs/r/compute_url_map.html.markdown index 0c19607dbd6..5eda49241f1 100644 --- a/website/docs/r/compute_url_map.html.markdown +++ b/website/docs/r/compute_url_map.html.markdown @@ -27,6 +27,9 @@ UrlMaps are used to route requests to a backend service based on rules that you define for the host and path of an incoming URL. +To get more information about UrlMap, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/urlMaps)
@@ -111,34 +114,196 @@ resource "google_storage_bucket" "static" { location = "US" } ``` +
+ + Open in Cloud Shell + +
+## Example Usage - Url Map Traffic Director Route + + +```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}" + + route_rules { + priority = 1 + header_action { + request_headers_to_remove = ["RemoveMe2"] + request_headers_to_add { + header_name = "AddSomethingElse" + header_value = "MyOtherValue" + replace = true + } + response_headers_to_remove = ["RemoveMe3"] + response_headers_to_add { + header_name = "AddMe" + header_value = "MyValue" + replace = false + } + } + match_rules { + full_path_match = "a full path" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + ignore_case = true + metadata_filters { + filter_match_criteria = "MATCH_ANY" + filter_labels { + name = "PLANET" + value = "MARS" + } + } + query_parameter_matches { + name = "a query parameter" + present_match = true + } + } + url_redirect { + host_redirect = "A host" + https_redirect = false + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + strip_query = true + } + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "home" { + name = "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 + } +} +``` +
+ + Open in Cloud Shell + +
+## Example Usage - Url Map Traffic Director Route 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}" + + route_rules { + priority = 1 + match_rules { + prefix_match = "/someprefix" + header_matches { + header_name = "someheader" + exact_match = "match this exactly" + invert_match = true + } + } + url_redirect { + path_redirect = "some/path" + redirect_response_code = "TEMPORARY_REDIRECT" + } + } + } + + 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 + } +} +``` ## Argument Reference The following arguments are supported: -* `default_service` - - (Required) - The backend service or backend bucket to use when none of the given rules match. - * `name` - (Required) - Name of the resource. Provided by the client when the resource is - created. The name must be 1-63 characters long, and comply with - RFC1035. Specifically, the name must be 1-63 characters long and match - the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the - first character must be a lowercase letter, and all following - characters must be a dash, lowercase letter, or digit, except the last - character, which cannot be a dash. + Name of the resource. Provided by the client when the resource is created. The + name must be 1-63 characters long, and comply with RFC1035. Specifically, the + name must be 1-63 characters long and match the regular expression + `[a-z]([-a-z0-9]*[a-z0-9])?` which means the first character must be a lowercase + letter, and all following characters must be a dash, lowercase letter, or digit, + except the last character, which cannot be a dash. - - - +* `default_service` - + (Optional) + The backend service or backend bucket to use when none of the given rules match. + * `description` - (Optional) - An optional description of this resource. Provide this property when - you create the resource. + An optional description of this resource. Provide this property when you create + the resource. + +* `header_action` - + (Optional) + Specifies changes to request and response headers that need to take effect for + the selected backendService. The headerAction specified here take effect after + headerAction specified under pathMatcher. Structure is documented below. * `host_rule` - (Optional) @@ -150,49 +315,119 @@ The following arguments are supported: * `test` - (Optional) - The list of expected URL mappings. Requests to update this UrlMap will - succeed only if all of the test cases pass. Structure is documented below. + 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. Structure is documented below. * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. +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 `host_rule` block supports: * `description` - (Optional) - An optional description of this HostRule. Provide this property - when you create the resource. + An optional description of this resource. Provide this property when you create + the resource. * `hosts` - (Required) - 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 .. + 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 .. * `path_matcher` - (Required) - The name of the PathMatcher to use to match the path portion of - the URL if the hostRule matches the URL's host portion. + The name of the PathMatcher to use to match the path portion of the URL if the + hostRule matches the URL's host portion. The `path_matcher` block supports: * `default_service` - - (Required) + (Optional) The backend service or backend bucket to use when none of the given paths match. * `description` - (Optional) - An optional description of this resource. + 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 + the selected backendService. HeaderAction specified here are applied after the + matching HttpRouteRule HeaderAction and before the HeaderAction in the UrlMap Structure is documented below. * `name` - (Required) The name to which this PathMatcher is referred by the HostRule. -* `path_rule` - +* `route_rules` - (Optional) - The list of path rules. Structure is documented below. + 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. Structure is documented below. The `path_rule` block supports: @@ -209,6 +444,683 @@ The `path_rule` block supports: (Required) The backend service or backend bucket to use if any of the given paths match. +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 `route_rules` block supports: + +* `priority` - + (Required) + 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` - + (Optional) + 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 Structure is documented below. + +* `match_rules` - + (Optional) + The rules for determining a match. Structure is documented below. + +* `route_action` - + (Optional) + 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. Structure is documented below. + +* `url_redirect` - + (Optional) + 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. 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 `match_rules` block supports: + +* `full_path_match` - + (Optional) + 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` - + (Optional) + Specifies a list of header match criteria, all of which must match corresponding + headers in the request. Structure is documented below. + +* `ignore_case` - + (Optional) + Specifies that prefixMatch and fullPathMatch matches are case sensitive. + Defaults to false. + +* `metadata_filters` - + (Optional) + 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. Structure is documented below. + +* `prefix_match` - + (Optional) + 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` - + (Optional) + Specifies a list of query parameter match criteria, all of which must match + corresponding query parameters in the request. Structure is documented below. + +* `regex_match` - + (Optional) + 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. + + +The `header_matches` block supports: + +* `exact_match` - + (Optional) + The value should exactly match contents of exactMatch. Only one of exactMatch, + prefixMatch, suffixMatch, regexMatch, presentMatch or rangeMatch must be set. + +* `header_name` - + (Required) + 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". + +* `invert_match` - + (Optional) + 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. + +* `prefix_match` - + (Optional) + 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` - + (Optional) + 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` - + (Optional) + 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. Structure is documented below. + +* `regex_match` - + (Optional) + 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` - + (Optional) + 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. + + +The `range_match` block supports: + +* `range_end` - + (Required) + The end of the range (exclusive). + +* `range_start` - + (Required) + The start of the range (inclusive). + +The `metadata_filters` block supports: + +* `filter_labels` - + (Required) + 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. Structure is documented below. + +* `filter_match_criteria` - + (Required) + 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. + + +The `filter_labels` block supports: + +* `name` - + (Required) + Name of metadata label. The name can have a maximum length of 1024 characters + and must be at least 1 character long. + +* `value` - + (Required) + The value of the label must match the specified value. value can have a maximum + length of 1024 characters. + +The `query_parameter_matches` block supports: + +* `exact_match` - + (Optional) + 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. + +* `name` - + (Required) + 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. + +* `present_match` - + (Optional) + 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` - + (Optional) + 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. + +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` - + (Optional) + If true, specifies the CORS policy is disabled. + which indicates that the CORS policy is in effect. Defaults to false. + +* `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` - + (Optional) + The HTTP status code used to abort the request. The value must be between 200 + and 599 inclusive. + +* `percentage` - + (Optional) + 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` - + (Optional) + Specifies the value of the fixed delay interval. Structure is documented below. + +* `percentage` - + (Optional) + 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` - + (Required) + Specifies the allowed number retries. This number must be > 0. + +* `per_try_timeout` - + (Optional) + 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. 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: + +* `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 `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` - + (Optional) + 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. + The `test` block supports: * `description` - @@ -239,8 +1151,8 @@ In addition to the arguments listed above, the following computed attributes are The unique identifier for the resource. * `fingerprint` - - Fingerprint of this resource. This field is used internally during - updates of this resource. + Fingerprint of this resource. A hash of the contents stored in this object. This + field is used in optimistic locking. * `self_link` - The URI of the created resource.