| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // *** AUTO GENERATED CODE *** Type: MMv1 *** |
| // |
| // ---------------------------------------------------------------------------- |
| // |
| // This file is automatically generated by Magic Modules and manual |
| // changes will be clobbered when the file is regenerated. |
| // |
| // Please read more about how to change this file in |
| // .github/CONTRIBUTING.md. |
| // |
| // ---------------------------------------------------------------------------- |
| |
| package compute |
| |
| import ( |
| "bytes" |
| "fmt" |
| "log" |
| "net/http" |
| "reflect" |
| "regexp" |
| "time" |
| |
| "github.com/hashicorp/errwrap" |
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" |
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" |
| |
| "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" |
| transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" |
| "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" |
| |
| "google.golang.org/api/googleapi" |
| ) |
| |
| // suppress changes on sample_rate if log_config is set to disabled. |
| func suppressWhenDisabled(k, old, new string, d *schema.ResourceData) bool { |
| _, n := d.GetChange("log_config.0.enable") |
| if tpgresource.IsEmptyValue(reflect.ValueOf(n)) { |
| return true |
| } |
| return false |
| } |
| |
| // Whether the backend is a global or regional NEG |
| func isNegBackend(backend map[string]interface{}) bool { |
| backendGroup, ok := backend["group"] |
| if !ok { |
| return false |
| } |
| |
| match, err := regexp.MatchString("(?:global|regions/[^/]+)/networkEndpointGroups", backendGroup.(string)) |
| if err != nil { |
| // should not happen as long as the regexp pattern compiled correctly |
| return false |
| } |
| return match |
| } |
| |
| func resourceGoogleComputeBackendServiceBackendHash(v interface{}) int { |
| if v == nil { |
| return 0 |
| } |
| |
| var buf bytes.Buffer |
| m := v.(map[string]interface{}) |
| log.Printf("[DEBUG] hashing %v", m) |
| |
| if group, err := tpgresource.GetRelativePath(m["group"].(string)); err != nil { |
| log.Printf("[WARN] Error on retrieving relative path of instance group: %s", err) |
| buf.WriteString(fmt.Sprintf("%s-", m["group"].(string))) |
| } else { |
| buf.WriteString(fmt.Sprintf("%s-", group)) |
| } |
| |
| if v, ok := m["balancing_mode"]; ok { |
| if v == nil { |
| v = "" |
| } |
| |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["capacity_scaler"]; ok { |
| if v == nil { |
| v = 0.0 |
| } |
| |
| // floats can't be added to the hash with %v as the other values are because |
| // %v and %f are not equivalent strings so this must remain as a float so that |
| // the hash function doesn't return something else. |
| buf.WriteString(fmt.Sprintf("%f-", v.(float64))) |
| } |
| if v, ok := m["description"]; ok { |
| if v == nil { |
| v = "" |
| } |
| |
| log.Printf("[DEBUG] writing description %s", v) |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["max_rate"]; ok { |
| if v == nil { |
| v = 0 |
| } |
| |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["max_rate_per_instance"]; ok { |
| if v == nil { |
| v = 0.0 |
| } |
| |
| // floats can't be added to the hash with %v as the other values are because |
| // %v and %f are not equivalent strings so this must remain as a float so that |
| // the hash function doesn't return something else. |
| buf.WriteString(fmt.Sprintf("%f-", v.(float64))) |
| } |
| if v, ok := m["max_connections"]; ok { |
| if v == nil { |
| v = 0 |
| } |
| |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["max_connections_per_instance"]; ok { |
| if v == nil { |
| v = 0 |
| } |
| |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["max_rate_per_instance"]; ok { |
| if v == nil { |
| v = 0.0 |
| } |
| |
| // floats can't be added to the hash with %v as the other values are because |
| // %v and %f are not equivalent strings so this must remain as a float so that |
| // the hash function doesn't return something else. |
| buf.WriteString(fmt.Sprintf("%f-", v.(float64))) |
| } |
| if v, ok := m["max_connections_per_endpoint"]; ok { |
| if v == nil { |
| v = 0 |
| } |
| |
| buf.WriteString(fmt.Sprintf("%v-", v)) |
| } |
| if v, ok := m["max_rate_per_endpoint"]; ok { |
| if v == nil { |
| v = 0.0 |
| } |
| |
| // floats can't be added to the hash with %v as the other values are because |
| // %v and %f are not equivalent strings so this must remain as a float so that |
| // the hash function doesn't return something else. |
| buf.WriteString(fmt.Sprintf("%f-", v.(float64))) |
| } |
| if v, ok := m["max_utilization"]; ok && !isNegBackend(m) { |
| if v == nil { |
| v = 0.0 |
| } |
| |
| // floats can't be added to the hash with %v as the other values are because |
| // %v and %f are not equivalent strings so this must remain as a float so that |
| // the hash function doesn't return something else. |
| buf.WriteString(fmt.Sprintf("%f-", v.(float64))) |
| } |
| |
| // This is in region backend service, but not in backend service. Should be a no-op |
| // if it's not present. |
| if v, ok := m["failover"]; ok { |
| if v == nil { |
| v = false |
| } |
| buf.WriteString(fmt.Sprintf("%v-", v.(bool))) |
| } |
| |
| log.Printf("[DEBUG] computed hash value of %v from %v", tpgresource.Hashcode(buf.String()), buf.String()) |
| return tpgresource.Hashcode(buf.String()) |
| } |
| |
| func ResourceComputeBackendService() *schema.Resource { |
| return &schema.Resource{ |
| Create: resourceComputeBackendServiceCreate, |
| Read: resourceComputeBackendServiceRead, |
| Update: resourceComputeBackendServiceUpdate, |
| Delete: resourceComputeBackendServiceDelete, |
| |
| Importer: &schema.ResourceImporter{ |
| State: resourceComputeBackendServiceImport, |
| }, |
| |
| Timeouts: &schema.ResourceTimeout{ |
| Create: schema.DefaultTimeout(20 * time.Minute), |
| Update: schema.DefaultTimeout(20 * time.Minute), |
| Delete: schema.DefaultTimeout(20 * time.Minute), |
| }, |
| |
| SchemaVersion: 1, |
| CustomizeDiff: customdiff.All( |
| tpgresource.DefaultProviderProject, |
| ), |
| |
| Schema: map[string]*schema.Schema{ |
| "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.`, |
| }, |
| "affinity_cookie_ttl_sec": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Lifetime of cookies in seconds if session_affinity is |
| GENERATED_COOKIE. If set to 0, the cookie is non-persistent and lasts |
| only until the end of the browser session (or equivalent). The |
| maximum allowed value for TTL is one day. |
| |
| When the load balancing scheme is INTERNAL, this field is not used.`, |
| }, |
| "backend": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `The set of backends that serve this BackendService.`, |
| Elem: computeBackendServiceBackendSchema(), |
| Set: resourceGoogleComputeBackendServiceBackendHash, |
| }, |
| "cdn_policy": { |
| Type: schema.TypeList, |
| Computed: true, |
| Optional: true, |
| Description: `Cloud CDN configuration for this BackendService.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "bypass_cache_on_request_headers": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Bypass the cache when the specified request headers are matched - e.g. Pragma or Authorization headers. Up to 5 headers can be specified. |
| The cache is bypassed for all cdnPolicy.cacheMode settings.`, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "header_name": { |
| Type: schema.TypeString, |
| Required: true, |
| Description: `The header field name to match on when bypassing cache. Values are case-insensitive.`, |
| }, |
| }, |
| }, |
| }, |
| "cache_key_policy": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The CacheKeyPolicy for this CdnPolicy.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "include_host": { |
| Type: schema.TypeBool, |
| Optional: true, |
| Description: `If true requests to different hosts will be cached separately.`, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "include_http_headers": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Allows HTTP request headers (by name) to be used in the |
| cache key.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "include_named_cookies": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Names of cookies to include in cache keys.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "include_protocol": { |
| Type: schema.TypeBool, |
| Optional: true, |
| Description: `If true, http and https requests will be cached separately.`, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "include_query_string": { |
| Type: schema.TypeBool, |
| Optional: true, |
| Description: `If true, include query string parameters in the cache key |
| according to query_string_whitelist and |
| query_string_blacklist. If neither is set, the entire query |
| string will be included. |
| |
| If false, the query string will be excluded from the cache |
| key entirely.`, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "query_string_blacklist": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `Names of query string parameters to exclude in cache keys. |
| |
| All other parameters will be included. Either specify |
| query_string_whitelist or query_string_blacklist, not both. |
| '&' and '=' will be percent encoded and not treated as |
| delimiters.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| Set: schema.HashString, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| "query_string_whitelist": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `Names of query string parameters to include in cache keys. |
| |
| All other parameters will be excluded. Either specify |
| query_string_whitelist or query_string_blacklist, not both. |
| '&' and '=' will be percent encoded and not treated as |
| delimiters.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| Set: schema.HashString, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy.0.include_host", "cdn_policy.0.cache_key_policy.0.include_protocol", "cdn_policy.0.cache_key_policy.0.include_query_string", "cdn_policy.0.cache_key_policy.0.query_string_blacklist", "cdn_policy.0.cache_key_policy.0.query_string_whitelist", "cdn_policy.0.cache_key_policy.0.include_http_headers", "cdn_policy.0.cache_key_policy.0.include_named_cookies"}, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy", "cdn_policy.0.signed_url_cache_max_age_sec"}, |
| }, |
| "cache_mode": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"USE_ORIGIN_HEADERS", "FORCE_CACHE_ALL", "CACHE_ALL_STATIC", ""}), |
| Description: `Specifies the cache setting for all responses from this backend. |
| The possible values are: USE_ORIGIN_HEADERS, FORCE_CACHE_ALL and CACHE_ALL_STATIC Possible values: ["USE_ORIGIN_HEADERS", "FORCE_CACHE_ALL", "CACHE_ALL_STATIC"]`, |
| }, |
| "client_ttl": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `Specifies the maximum allowed TTL for cached content served by this origin.`, |
| }, |
| "default_ttl": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `Specifies the default TTL for cached content served by this origin for responses |
| that do not have an existing valid TTL (max-age or s-max-age).`, |
| }, |
| "max_ttl": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `Specifies the maximum allowed TTL for cached content served by this origin.`, |
| }, |
| "negative_caching": { |
| Type: schema.TypeBool, |
| Computed: true, |
| Optional: true, |
| Description: `Negative caching allows per-status code TTLs to be set, in order to apply fine-grained caching for common errors or redirects.`, |
| }, |
| "negative_caching_policy": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Sets a cache TTL for the specified HTTP status code. negativeCaching must be enabled to configure negativeCachingPolicy. |
| Omitting the policy and leaving negativeCaching enabled will use Cloud CDN's default cache TTLs.`, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "code": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The HTTP status code to define a TTL against. Only HTTP status codes 300, 301, 308, 404, 405, 410, 421, 451 and 501 |
| can be specified as values, and you cannot specify a status code more than once.`, |
| }, |
| "ttl": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The TTL (in seconds) for which to cache responses with the corresponding status code. The maximum allowed value is 1800s |
| (30 minutes), noting that infrequently accessed objects may be evicted from the cache before the defined TTL.`, |
| }, |
| }, |
| }, |
| }, |
| "serve_while_stale": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `Serve existing content from the cache (if available) when revalidating content with the origin, or when an error is encountered when refreshing the cache.`, |
| }, |
| "signed_url_cache_max_age_sec": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Maximum number of seconds the response to a signed URL request |
| will be considered fresh, defaults to 1hr (3600s). After this |
| time period, the response will be revalidated before |
| being served. |
| |
| When serving responses to signed URL requests, Cloud CDN will |
| internally behave as though all responses from this backend had a |
| "Cache-Control: public, max-age=[TTL]" header, regardless of any |
| existing Cache-Control header. The actual headers served in |
| responses will not be altered.`, |
| Default: 3600, |
| AtLeastOneOf: []string{"cdn_policy.0.cache_key_policy", "cdn_policy.0.signed_url_cache_max_age_sec"}, |
| }, |
| }, |
| }, |
| }, |
| "circuit_breakers": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Settings controlling the volume of connections to a backend service. This field |
| is applicable only when the load_balancing_scheme is set to INTERNAL_SELF_MANAGED.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "connect_timeout": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The timeout for new network connections to hosts.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "seconds": { |
| Type: schema.TypeInt, |
| 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.`, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| "max_connections": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The maximum number of connections to the backend cluster. |
| Defaults to 1024.`, |
| Default: 1024, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| "max_pending_requests": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The maximum number of pending requests to the backend cluster. |
| Defaults to 1024.`, |
| Default: 1024, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| "max_requests": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The maximum number of parallel requests to the backend cluster. |
| Defaults to 1024.`, |
| Default: 1024, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| "max_requests_per_connection": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Maximum requests for a single backend connection. This parameter |
| is respected by both the HTTP/1.1 and HTTP/2 implementations. If |
| not specified, there is no limit. Setting this parameter to 1 |
| will effectively disable keep alive.`, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| "max_retries": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The maximum number of parallel retries to the backend cluster. |
| Defaults to 3.`, |
| Default: 3, |
| AtLeastOneOf: []string{"circuit_breakers.0.connect_timeout", "circuit_breakers.0.max_requests_per_connection", "circuit_breakers.0.max_connections", "circuit_breakers.0.max_pending_requests", "circuit_breakers.0.max_requests", "circuit_breakers.0.max_retries"}, |
| }, |
| }, |
| }, |
| }, |
| "compression_mode": { |
| Type: schema.TypeString, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"AUTOMATIC", "DISABLED", ""}), |
| Description: `Compress text responses using Brotli or gzip compression, based on the client's Accept-Encoding header. Possible values: ["AUTOMATIC", "DISABLED"]`, |
| }, |
| "connection_draining_timeout_sec": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Time for which instance will be drained (not accept new |
| connections, but still work to finish started).`, |
| Default: 300, |
| }, |
| |
| "consistent_hash": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Consistent Hash-based load balancing can be used to provide soft session |
| affinity based on HTTP headers, cookies or other properties. This load balancing |
| policy is applicable only for HTTP connections. The affinity to a particular |
| destination host will be lost when one or more hosts are added/removed from the |
| destination service. This field specifies parameters that control consistent |
| hashing. This field only applies if the load_balancing_scheme is set to |
| INTERNAL_SELF_MANAGED. This field is only applicable when locality_lb_policy is |
| set to MAGLEV or RING_HASH.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "http_cookie": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Hash is based on HTTP Cookie. This field describes a HTTP cookie |
| that will be used as the hash key for the consistent hash load |
| balancer. If the cookie is not present, it will be generated. |
| This field is applicable if the sessionAffinity is set to HTTP_COOKIE.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "name": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `Name of the cookie.`, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie.0.ttl", "consistent_hash.0.http_cookie.0.name", "consistent_hash.0.http_cookie.0.path"}, |
| }, |
| "path": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `Path to set for the cookie.`, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie.0.ttl", "consistent_hash.0.http_cookie.0.name", "consistent_hash.0.http_cookie.0.path"}, |
| }, |
| "ttl": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Lifetime of the cookie.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "seconds": { |
| Type: schema.TypeInt, |
| 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.`, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie.0.ttl", "consistent_hash.0.http_cookie.0.name", "consistent_hash.0.http_cookie.0.path"}, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie", "consistent_hash.0.http_header_name", "consistent_hash.0.minimum_ring_size"}, |
| }, |
| "http_header_name": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `The hash based on the value of the specified header field. |
| This field is applicable if the sessionAffinity is set to HEADER_FIELD.`, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie", "consistent_hash.0.http_header_name", "consistent_hash.0.minimum_ring_size"}, |
| }, |
| "minimum_ring_size": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The minimum number of virtual nodes to use for the hash ring. |
| Larger ring sizes result in more granular load |
| distributions. If the number of hosts in the load balancing pool |
| is larger than the ring size, each host will be assigned a single |
| virtual node. |
| Defaults to 1024.`, |
| Default: 1024, |
| AtLeastOneOf: []string{"consistent_hash.0.http_cookie", "consistent_hash.0.http_header_name", "consistent_hash.0.minimum_ring_size"}, |
| }, |
| }, |
| }, |
| }, |
| "custom_request_headers": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `Headers that the HTTP/S load balancer should add to proxied |
| requests.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| Set: schema.HashString, |
| }, |
| "custom_response_headers": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `Headers that the HTTP/S load balancer should add to proxied |
| responses.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| Set: schema.HashString, |
| }, |
| "description": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `An optional description of this resource.`, |
| }, |
| "edge_security_policy": { |
| Type: schema.TypeString, |
| Optional: true, |
| DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, |
| Description: `The resource URL for the edge security policy associated with this backend service.`, |
| }, |
| "enable_cdn": { |
| Type: schema.TypeBool, |
| Optional: true, |
| Description: `If true, enable Cloud CDN for this BackendService.`, |
| }, |
| "health_checks": { |
| Type: schema.TypeSet, |
| Optional: true, |
| Description: `The set of URLs to the HttpHealthCheck or HttpsHealthCheck resource |
| for health checking this BackendService. Currently at most one health |
| check can be specified. |
| |
| A health check must be specified unless the backend service uses an internet |
| or serverless NEG as a backend. |
| |
| For internal load balancing, a URL to a HealthCheck resource must be specified instead.`, |
| MinItems: 1, |
| MaxItems: 1, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| Set: tpgresource.SelfLinkRelativePathHash, |
| }, |
| "iap": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Settings for enabling Cloud Identity Aware Proxy`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "enabled": { |
| Type: schema.TypeBool, |
| Required: true, |
| Description: `Whether the serving infrastructure will authenticate and authorize all incoming requests.`, |
| }, |
| "oauth2_client_id": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `OAuth2 Client ID for IAP`, |
| }, |
| "oauth2_client_secret": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `OAuth2 Client Secret for IAP`, |
| Sensitive: true, |
| }, |
| "oauth2_client_secret_sha256": { |
| Type: schema.TypeString, |
| Computed: true, |
| Description: `OAuth2 Client Secret SHA-256 for IAP`, |
| Sensitive: true, |
| }, |
| }, |
| }, |
| }, |
| "load_balancing_scheme": { |
| Type: schema.TypeString, |
| Optional: true, |
| ForceNew: true, |
| ValidateFunc: verify.ValidateEnum([]string{"EXTERNAL", "INTERNAL_SELF_MANAGED", "INTERNAL_MANAGED", "EXTERNAL_MANAGED", ""}), |
| Description: `Indicates whether the backend service will be used with internal or |
| external load balancing. A backend service created for one type of |
| load balancing cannot be used with the other. For more information, refer to |
| [Choosing a load balancer](https://cloud.google.com/load-balancing/docs/backend-service). Default value: "EXTERNAL" Possible values: ["EXTERNAL", "INTERNAL_SELF_MANAGED", "INTERNAL_MANAGED", "EXTERNAL_MANAGED"]`, |
| Default: "EXTERNAL", |
| }, |
| "locality_lb_policies": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `A list of locality load balancing policies to be used in order of |
| preference. Either the policy or the customPolicy field should be set. |
| Overrides any value set in the localityLbPolicy field. |
| |
| localityLbPolicies is only supported when the BackendService is referenced |
| by a URL Map that is referenced by a target gRPC proxy that has the |
| validateForProxyless field set to true.`, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "custom_policy": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The configuration for a custom policy implemented by the user and |
| deployed with the client.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "name": { |
| Type: schema.TypeString, |
| Required: true, |
| Description: `Identifies the custom policy. |
| |
| The value should match the type the custom implementation is registered |
| with on the gRPC clients. It should follow protocol buffer |
| message naming conventions and include the full path (e.g. |
| myorg.CustomLbPolicy). The maximum length is 256 characters. |
| |
| Note that specifying the same custom policy more than once for a |
| backend is not a valid configuration and will be rejected.`, |
| }, |
| "data": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `An optional, arbitrary JSON object with configuration data, understood |
| by a locally installed custom policy implementation.`, |
| }, |
| }, |
| }, |
| ExactlyOneOf: []string{}, |
| }, |
| "policy": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The configuration for a built-in load balancing policy.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "name": { |
| Type: schema.TypeString, |
| Required: true, |
| ValidateFunc: verify.ValidateEnum([]string{"ROUND_ROBIN", "LEAST_REQUEST", "RING_HASH", "RANDOM", "ORIGINAL_DESTINATION", "MAGLEV"}), |
| Description: `The name of a locality load balancer policy to be used. The value |
| should be one of the predefined ones as supported by localityLbPolicy, |
| although at the moment only ROUND_ROBIN is supported. |
| |
| This field should only be populated when the customPolicy field is not |
| used. |
| |
| Note that specifying the same policy more than once for a backend is |
| not a valid configuration and will be rejected. |
| |
| The possible values are: |
| |
| * 'ROUND_ROBIN': This is a simple policy in which each healthy backend |
| is selected in round robin order. |
| |
| * 'LEAST_REQUEST': An O(1) algorithm which selects two random healthy |
| hosts and picks the host which has fewer active requests. |
| |
| * 'RING_HASH': The ring/modulo hash load balancer implements consistent |
| hashing to backends. The algorithm has the property that the |
| addition/removal of a host from a set of N hosts only affects |
| 1/N of the requests. |
| |
| * 'RANDOM': The load balancer selects a random healthy host. |
| |
| * 'ORIGINAL_DESTINATION': Backend host is selected based on the client |
| connection metadata, i.e., connections are opened |
| to the same address as the destination address of |
| the incoming connection before the connection |
| was redirected to the load balancer. |
| |
| * 'MAGLEV': used as a drop in replacement for the ring hash load balancer. |
| Maglev is not as stable as ring hash but has faster table lookup |
| build times and host selection times. For more information about |
| Maglev, refer to https://ai.google/research/pubs/pub44824 Possible values: ["ROUND_ROBIN", "LEAST_REQUEST", "RING_HASH", "RANDOM", "ORIGINAL_DESTINATION", "MAGLEV"]`, |
| }, |
| }, |
| }, |
| ExactlyOneOf: []string{}, |
| }, |
| }, |
| }, |
| }, |
| "locality_lb_policy": { |
| Type: schema.TypeString, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"ROUND_ROBIN", "LEAST_REQUEST", "RING_HASH", "RANDOM", "ORIGINAL_DESTINATION", "MAGLEV", "WEIGHTED_MAGLEV", ""}), |
| Description: `The load balancing algorithm used within the scope of the locality. |
| The possible values are: |
| |
| * 'ROUND_ROBIN': This is a simple policy in which each healthy backend |
| is selected in round robin order. |
| |
| * 'LEAST_REQUEST': An O(1) algorithm which selects two random healthy |
| hosts and picks the host which has fewer active requests. |
| |
| * 'RING_HASH': The ring/modulo hash load balancer implements consistent |
| hashing to backends. The algorithm has the property that the |
| addition/removal of a host from a set of N hosts only affects |
| 1/N of the requests. |
| |
| * 'RANDOM': The load balancer selects a random healthy host. |
| |
| * 'ORIGINAL_DESTINATION': Backend host is selected based on the client |
| connection metadata, i.e., connections are opened |
| to the same address as the destination address of |
| the incoming connection before the connection |
| was redirected to the load balancer. |
| |
| * 'MAGLEV': used as a drop in replacement for the ring hash load balancer. |
| Maglev is not as stable as ring hash but has faster table lookup |
| build times and host selection times. For more information about |
| Maglev, refer to https://ai.google/research/pubs/pub44824 |
| |
| * 'WEIGHTED_MAGLEV': Per-instance weighted Load Balancing via health check |
| reported weights. If set, the Backend Service must |
| configure a non legacy HTTP-based Health Check, and |
| health check replies are expected to contain |
| non-standard HTTP response header field |
| X-Load-Balancing-Endpoint-Weight to specify the |
| per-instance weights. If set, Load Balancing is weight |
| based on the per-instance weights reported in the last |
| processed health check replies, as long as every |
| instance either reported a valid weight or had |
| UNAVAILABLE_WEIGHT. Otherwise, Load Balancing remains |
| equal-weight. |
| |
| This field is applicable to either: |
| |
| * A regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, |
| and loadBalancingScheme set to INTERNAL_MANAGED. |
| * A global backend service with the load_balancing_scheme set to INTERNAL_SELF_MANAGED. |
| * A regional backend service with loadBalancingScheme set to EXTERNAL (External Network |
| Load Balancing). Only MAGLEV and WEIGHTED_MAGLEV values are possible for External |
| Network Load Balancing. The default is MAGLEV. |
| |
| If session_affinity is not NONE, and this field is not set to MAGLEV, WEIGHTED_MAGLEV, |
| or RING_HASH, session affinity settings will not take effect. |
| |
| Only ROUND_ROBIN and RING_HASH are supported when the backend service is referenced |
| by a URL map that is bound to target gRPC proxy that has validate_for_proxyless |
| field set to true. Possible values: ["ROUND_ROBIN", "LEAST_REQUEST", "RING_HASH", "RANDOM", "ORIGINAL_DESTINATION", "MAGLEV", "WEIGHTED_MAGLEV"]`, |
| }, |
| "log_config": { |
| Type: schema.TypeList, |
| Computed: true, |
| Optional: true, |
| Description: `This field denotes the logging options for the load balancer traffic served by this backend service. |
| If logging is enabled, logs will be exported to Stackdriver.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "enable": { |
| Type: schema.TypeBool, |
| Optional: true, |
| Description: `Whether to enable logging for the load balancer traffic served by this backend service.`, |
| AtLeastOneOf: []string{"log_config.0.enable", "log_config.0.sample_rate"}, |
| }, |
| "sample_rate": { |
| Type: schema.TypeFloat, |
| Optional: true, |
| DiffSuppressFunc: suppressWhenDisabled, |
| Description: `This field can only be specified if logging is enabled for this backend service. The value of |
| the field must be in [0, 1]. This configures the sampling rate of requests to the load balancer |
| where 1.0 means all logged requests are reported and 0.0 means no logged requests are reported. |
| The default value is 1.0.`, |
| Default: 1.0, |
| AtLeastOneOf: []string{"log_config.0.enable", "log_config.0.sample_rate"}, |
| }, |
| }, |
| }, |
| }, |
| "outlier_detection": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Settings controlling eviction of unhealthy hosts from the load balancing pool. |
| Applicable backend service types can be a global backend service with the |
| loadBalancingScheme set to INTERNAL_SELF_MANAGED or EXTERNAL_MANAGED.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "base_ejection_time": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The base time that a host is ejected for. The real time is equal to the base |
| time multiplied by the number of times the host has been ejected. Defaults to |
| 30000ms or 30s.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "seconds": { |
| Type: schema.TypeInt, |
| 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.`, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "consecutive_errors": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Number of errors before a host is ejected from the connection pool. When the |
| backend host is accessed over HTTP, a 5xx return code qualifies as an error. |
| Defaults to 5.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "consecutive_gateway_failure": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The number of consecutive gateway failures (502, 503, 504 status or connection |
| errors that are mapped to one of those status codes) before a consecutive |
| gateway failure ejection occurs. Defaults to 5.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "enforcing_consecutive_errors": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The percentage chance that a host will be actually ejected when an outlier |
| status is detected through consecutive 5xx. This setting can be used to disable |
| ejection or to ramp it up slowly. Defaults to 100.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "enforcing_consecutive_gateway_failure": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The percentage chance that a host will be actually ejected when an outlier |
| status is detected through consecutive gateway failures. This setting can be |
| used to disable ejection or to ramp it up slowly. Defaults to 0.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "enforcing_success_rate": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The percentage chance that a host will be actually ejected when an outlier |
| status is detected through success rate statistics. This setting can be used to |
| disable ejection or to ramp it up slowly. Defaults to 100.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "interval": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `Time interval between ejection sweep analysis. This can result in both new |
| ejections as well as hosts being returned to service. Defaults to 10 seconds.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "seconds": { |
| Type: schema.TypeInt, |
| 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.`, |
| }, |
| }, |
| }, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "max_ejection_percent": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `Maximum percentage of hosts in the load balancing pool for the backend service |
| that can be ejected. Defaults to 10%.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "success_rate_minimum_hosts": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The number of hosts in a cluster that must have enough request volume to detect |
| success rate outliers. If the number of hosts is less than this setting, outlier |
| detection via success rate statistics is not performed for any host in the |
| cluster. Defaults to 5.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "success_rate_request_volume": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `The minimum number of total requests that must be collected in one interval (as |
| defined by the interval duration above) to include this host in success rate |
| based outlier detection. If the volume is lower than this setting, outlier |
| detection via success rate statistics is not performed for that host. Defaults |
| to 100.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| "success_rate_stdev_factor": { |
| Type: schema.TypeInt, |
| Optional: true, |
| Description: `This factor is used to determine the ejection threshold for success rate outlier |
| ejection. The ejection threshold is the difference between the mean success |
| rate, and the product of this factor and the standard deviation of the mean |
| success rate: mean - (stdev * success_rate_stdev_factor). This factor is divided |
| by a thousand to get a double. That is, if the desired factor is 1.9, the |
| runtime value should be 1900. Defaults to 1900.`, |
| AtLeastOneOf: []string{"outlier_detection.0.base_ejection_time", "outlier_detection.0.consecutive_errors", "outlier_detection.0.consecutive_gateway_failure", "outlier_detection.0.enforcing_consecutive_errors", "outlier_detection.0.enforcing_consecutive_gateway_failure", "outlier_detection.0.enforcing_success_rate", "outlier_detection.0.interval", "outlier_detection.0.max_ejection_percent", "outlier_detection.0.success_rate_minimum_hosts", "outlier_detection.0.success_rate_request_volume", "outlier_detection.0.success_rate_stdev_factor"}, |
| }, |
| }, |
| }, |
| }, |
| "port_name": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| Description: `Name of backend port. The same name should appear in the instance |
| groups referenced by this service. Required when the load balancing |
| scheme is EXTERNAL.`, |
| }, |
| "protocol": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"HTTP", "HTTPS", "HTTP2", "TCP", "SSL", "GRPC", "UNSPECIFIED", ""}), |
| Description: `The protocol this BackendService uses to communicate with backends. |
| The default is HTTP. **NOTE**: HTTP2 is only valid for beta HTTP/2 load balancer |
| types and may result in errors if used with the GA API. **NOTE**: With protocol “UNSPECIFIED”, |
| the backend service can be used by Layer 4 Internal Load Balancing or Network Load Balancing |
| with TCP/UDP/L3_DEFAULT Forwarding Rule protocol. Possible values: ["HTTP", "HTTPS", "HTTP2", "TCP", "SSL", "GRPC", "UNSPECIFIED"]`, |
| }, |
| "security_policy": { |
| Type: schema.TypeString, |
| Optional: true, |
| DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, |
| Description: `The security policy associated with this backend service.`, |
| }, |
| "security_settings": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The security settings that apply to this backend service. This field is applicable to either |
| a regional backend service with the service_protocol set to HTTP, HTTPS, or HTTP2, and |
| load_balancing_scheme set to INTERNAL_MANAGED; or a global backend service with the |
| load_balancing_scheme set to INTERNAL_SELF_MANAGED.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "aws_v4_authentication": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The configuration needed to generate a signature for access to private storage buckets that support AWS's Signature Version 4 for authentication. |
| Allowed only for INTERNET_IP_PORT and INTERNET_FQDN_PORT NEG backends.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "access_key": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `The access key used for s3 bucket authentication. |
| Required for updating or creating a backend that uses AWS v4 signature authentication, but will not be returned as part of the configuration when queried with a REST API GET request.`, |
| Sensitive: true, |
| }, |
| "access_key_id": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `The identifier of an access key used for s3 bucket authentication.`, |
| }, |
| "access_key_version": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `The optional version identifier for the access key. You can use this to keep track of different iterations of your access key.`, |
| }, |
| "origin_region": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `The name of the cloud region of your origin. This is a free-form field with the name of the region your cloud uses to host your origin. |
| For example, "us-east-1" for AWS or "us-ashburn-1" for OCI.`, |
| }, |
| }, |
| }, |
| }, |
| "client_tls_policy": { |
| Type: schema.TypeString, |
| Optional: true, |
| DiffSuppressFunc: tpgresource.ProjectNumberDiffSuppress, |
| Description: `ClientTlsPolicy is a resource that specifies how a client should authenticate |
| connections to backends of a service. This resource itself does not affect |
| configuration unless it is attached to a backend service resource.`, |
| }, |
| "subject_alt_names": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `A list of alternate names to verify the subject identity in the certificate. |
| If specified, the client will verify that the server certificate's subject |
| alt name matches one of the specified values.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| }, |
| }, |
| }, |
| }, |
| "service_lb_policy": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `URL to networkservices.ServiceLbPolicy resource. |
| Can only be set if load balancing scheme is EXTERNAL, EXTERNAL_MANAGED, INTERNAL_MANAGED or INTERNAL_SELF_MANAGED and the scope is global.`, |
| }, |
| "session_affinity": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"NONE", "CLIENT_IP", "CLIENT_IP_PORT_PROTO", "CLIENT_IP_PROTO", "GENERATED_COOKIE", "HEADER_FIELD", "HTTP_COOKIE", ""}), |
| Description: `Type of session affinity to use. The default is NONE. Session affinity is |
| not applicable if the protocol is UDP. Possible values: ["NONE", "CLIENT_IP", "CLIENT_IP_PORT_PROTO", "CLIENT_IP_PROTO", "GENERATED_COOKIE", "HEADER_FIELD", "HTTP_COOKIE"]`, |
| }, |
| "timeout_sec": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `The backend service timeout has a different meaning depending on the type of load balancer. |
| For more information see, [Backend service settings](https://cloud.google.com/compute/docs/reference/rest/v1/backendServices). |
| The default is 30 seconds. |
| The full range of timeout values allowed goes from 1 through 2,147,483,647 seconds.`, |
| }, |
| "creation_timestamp": { |
| Type: schema.TypeString, |
| Computed: true, |
| Description: `Creation timestamp in RFC3339 text format.`, |
| }, |
| "fingerprint": { |
| Type: schema.TypeString, |
| Computed: true, |
| Description: `Fingerprint of this resource. A hash of the contents stored in this |
| object. This field is used in optimistic locking.`, |
| }, |
| "generated_id": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Description: `The unique identifier for the resource. This identifier is defined by the server.`, |
| }, |
| "project": { |
| Type: schema.TypeString, |
| Optional: true, |
| Computed: true, |
| ForceNew: true, |
| }, |
| "self_link": { |
| Type: schema.TypeString, |
| Computed: true, |
| }, |
| }, |
| UseJSONNumber: true, |
| } |
| } |
| |
| func computeBackendServiceBackendSchema() *schema.Resource { |
| return &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "group": { |
| Type: schema.TypeString, |
| Required: true, |
| DiffSuppressFunc: tpgresource.CompareSelfLinkRelativePaths, |
| Description: `The fully-qualified URL of an Instance Group or Network Endpoint |
| Group resource. In case of instance group this defines the list |
| of instances that serve traffic. Member virtual machine |
| instances from each instance group must live in the same zone as |
| the instance group itself. No two backends in a backend service |
| are allowed to use same Instance Group resource. |
| |
| For Network Endpoint Groups this defines list of endpoints. All |
| endpoints of Network Endpoint Group must be hosted on instances |
| located in the same zone as the Network Endpoint Group. |
| |
| Backend services cannot mix Instance Group and |
| Network Endpoint Group backends. |
| |
| Note that you must specify an Instance Group or Network Endpoint |
| Group resource using the fully-qualified URL, rather than a |
| partial URL.`, |
| }, |
| "balancing_mode": { |
| Type: schema.TypeString, |
| Optional: true, |
| ValidateFunc: verify.ValidateEnum([]string{"UTILIZATION", "RATE", "CONNECTION", ""}), |
| Description: `Specifies the balancing mode for this backend. |
| |
| For global HTTP(S) or TCP/SSL load balancing, the default is |
| UTILIZATION. Valid values are UTILIZATION, RATE (for HTTP(S)) |
| and CONNECTION (for TCP/SSL). |
| |
| See the [Backend Services Overview](https://cloud.google.com/load-balancing/docs/backend-service#balancing-mode) |
| for an explanation of load balancing modes. Default value: "UTILIZATION" Possible values: ["UTILIZATION", "RATE", "CONNECTION"]`, |
| Default: "UTILIZATION", |
| }, |
| "capacity_scaler": { |
| Type: schema.TypeFloat, |
| Optional: true, |
| Description: `A multiplier applied to the group's maximum servicing capacity |
| (based on UTILIZATION, RATE or CONNECTION). |
| |
| Default value is 1, which means the group will serve up to 100% |
| of its configured capacity (depending on balancingMode). A |
| setting of 0 means the group is completely drained, offering |
| 0% of its available Capacity. Valid range is [0.0,1.0].`, |
| Default: 1.0, |
| }, |
| "description": { |
| Type: schema.TypeString, |
| Optional: true, |
| Description: `An optional description of this resource. |
| Provide this property when you create the resource.`, |
| }, |
| "max_connections": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `The max number of simultaneous connections for the group. Can |
| be used with either CONNECTION or UTILIZATION balancing modes. |
| |
| For CONNECTION mode, either maxConnections or one |
| of maxConnectionsPerInstance or maxConnectionsPerEndpoint, |
| as appropriate for group type, must be set.`, |
| }, |
| "max_connections_per_endpoint": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `The max number of simultaneous connections that a single backend |
| network endpoint can handle. This is used to calculate the |
| capacity of the group. Can be used in either CONNECTION or |
| UTILIZATION balancing modes. |
| |
| For CONNECTION mode, either |
| maxConnections or maxConnectionsPerEndpoint must be set.`, |
| }, |
| "max_connections_per_instance": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `The max number of simultaneous connections that a single |
| backend instance can handle. This is used to calculate the |
| capacity of the group. Can be used in either CONNECTION or |
| UTILIZATION balancing modes. |
| |
| For CONNECTION mode, either maxConnections or |
| maxConnectionsPerInstance must be set.`, |
| }, |
| "max_rate": { |
| Type: schema.TypeInt, |
| Computed: true, |
| Optional: true, |
| Description: `The max requests per second (RPS) of the group. |
| |
| Can be used with either RATE or UTILIZATION balancing modes, |
| but required if RATE mode. For RATE mode, either maxRate or one |
| of maxRatePerInstance or maxRatePerEndpoint, as appropriate for |
| group type, must be set.`, |
| }, |
| "max_rate_per_endpoint": { |
| Type: schema.TypeFloat, |
| Computed: true, |
| Optional: true, |
| Description: `The max requests per second (RPS) that a single backend network |
| endpoint can handle. This is used to calculate the capacity of |
| the group. Can be used in either balancing mode. For RATE mode, |
| either maxRate or maxRatePerEndpoint must be set.`, |
| }, |
| "max_rate_per_instance": { |
| Type: schema.TypeFloat, |
| Computed: true, |
| Optional: true, |
| Description: `The max requests per second (RPS) that a single backend |
| instance can handle. This is used to calculate the capacity of |
| the group. Can be used in either balancing mode. For RATE mode, |
| either maxRate or maxRatePerInstance must be set.`, |
| }, |
| "max_utilization": { |
| Type: schema.TypeFloat, |
| Computed: true, |
| Optional: true, |
| Description: `Used when balancingMode is UTILIZATION. This ratio defines the |
| CPU utilization target for the group. Valid range is [0.0, 1.0].`, |
| }, |
| }, |
| } |
| } |
| |
| func resourceComputeBackendServiceCreate(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| obj := make(map[string]interface{}) |
| affinityCookieTtlSecProp, err := expandComputeBackendServiceAffinityCookieTtlSec(d.Get("affinity_cookie_ttl_sec"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("affinity_cookie_ttl_sec"); !tpgresource.IsEmptyValue(reflect.ValueOf(affinityCookieTtlSecProp)) && (ok || !reflect.DeepEqual(v, affinityCookieTtlSecProp)) { |
| obj["affinityCookieTtlSec"] = affinityCookieTtlSecProp |
| } |
| backendsProp, err := expandComputeBackendServiceBackend(d.Get("backend"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("backend"); !tpgresource.IsEmptyValue(reflect.ValueOf(backendsProp)) && (ok || !reflect.DeepEqual(v, backendsProp)) { |
| obj["backends"] = backendsProp |
| } |
| circuitBreakersProp, err := expandComputeBackendServiceCircuitBreakers(d.Get("circuit_breakers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("circuit_breakers"); !tpgresource.IsEmptyValue(reflect.ValueOf(circuitBreakersProp)) && (ok || !reflect.DeepEqual(v, circuitBreakersProp)) { |
| obj["circuitBreakers"] = circuitBreakersProp |
| } |
| compressionModeProp, err := expandComputeBackendServiceCompressionMode(d.Get("compression_mode"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("compression_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(compressionModeProp)) && (ok || !reflect.DeepEqual(v, compressionModeProp)) { |
| obj["compressionMode"] = compressionModeProp |
| } |
| consistentHashProp, err := expandComputeBackendServiceConsistentHash(d.Get("consistent_hash"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("consistent_hash"); !tpgresource.IsEmptyValue(reflect.ValueOf(consistentHashProp)) && (ok || !reflect.DeepEqual(v, consistentHashProp)) { |
| obj["consistentHash"] = consistentHashProp |
| } |
| cdnPolicyProp, err := expandComputeBackendServiceCdnPolicy(d.Get("cdn_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("cdn_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(cdnPolicyProp)) && (ok || !reflect.DeepEqual(v, cdnPolicyProp)) { |
| obj["cdnPolicy"] = cdnPolicyProp |
| } |
| connectionDrainingProp, err := expandComputeBackendServiceConnectionDraining(nil, d, config) |
| if err != nil { |
| return err |
| } else if !tpgresource.IsEmptyValue(reflect.ValueOf(connectionDrainingProp)) { |
| obj["connectionDraining"] = connectionDrainingProp |
| } |
| customRequestHeadersProp, err := expandComputeBackendServiceCustomRequestHeaders(d.Get("custom_request_headers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("custom_request_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(customRequestHeadersProp)) && (ok || !reflect.DeepEqual(v, customRequestHeadersProp)) { |
| obj["customRequestHeaders"] = customRequestHeadersProp |
| } |
| customResponseHeadersProp, err := expandComputeBackendServiceCustomResponseHeaders(d.Get("custom_response_headers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("custom_response_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(customResponseHeadersProp)) && (ok || !reflect.DeepEqual(v, customResponseHeadersProp)) { |
| obj["customResponseHeaders"] = customResponseHeadersProp |
| } |
| fingerprintProp, err := expandComputeBackendServiceFingerprint(d.Get("fingerprint"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { |
| obj["fingerprint"] = fingerprintProp |
| } |
| descriptionProp, err := expandComputeBackendServiceDescription(d.Get("description"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { |
| obj["description"] = descriptionProp |
| } |
| enableCDNProp, err := expandComputeBackendServiceEnableCDN(d.Get("enable_cdn"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("enable_cdn"); !tpgresource.IsEmptyValue(reflect.ValueOf(enableCDNProp)) && (ok || !reflect.DeepEqual(v, enableCDNProp)) { |
| obj["enableCDN"] = enableCDNProp |
| } |
| healthChecksProp, err := expandComputeBackendServiceHealthChecks(d.Get("health_checks"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("health_checks"); !tpgresource.IsEmptyValue(reflect.ValueOf(healthChecksProp)) && (ok || !reflect.DeepEqual(v, healthChecksProp)) { |
| obj["healthChecks"] = healthChecksProp |
| } |
| iapProp, err := expandComputeBackendServiceIap(d.Get("iap"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("iap"); ok || !reflect.DeepEqual(v, iapProp) { |
| obj["iap"] = iapProp |
| } |
| loadBalancingSchemeProp, err := expandComputeBackendServiceLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("load_balancing_scheme"); !tpgresource.IsEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { |
| obj["loadBalancingScheme"] = loadBalancingSchemeProp |
| } |
| localityLbPolicyProp, err := expandComputeBackendServiceLocalityLbPolicy(d.Get("locality_lb_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("locality_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(localityLbPolicyProp)) && (ok || !reflect.DeepEqual(v, localityLbPolicyProp)) { |
| obj["localityLbPolicy"] = localityLbPolicyProp |
| } |
| localityLbPoliciesProp, err := expandComputeBackendServiceLocalityLbPolicies(d.Get("locality_lb_policies"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("locality_lb_policies"); !tpgresource.IsEmptyValue(reflect.ValueOf(localityLbPoliciesProp)) && (ok || !reflect.DeepEqual(v, localityLbPoliciesProp)) { |
| obj["localityLbPolicies"] = localityLbPoliciesProp |
| } |
| nameProp, err := expandComputeBackendServiceName(d.Get("name"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { |
| obj["name"] = nameProp |
| } |
| outlierDetectionProp, err := expandComputeBackendServiceOutlierDetection(d.Get("outlier_detection"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("outlier_detection"); !tpgresource.IsEmptyValue(reflect.ValueOf(outlierDetectionProp)) && (ok || !reflect.DeepEqual(v, outlierDetectionProp)) { |
| obj["outlierDetection"] = outlierDetectionProp |
| } |
| portNameProp, err := expandComputeBackendServicePortName(d.Get("port_name"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("port_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(portNameProp)) && (ok || !reflect.DeepEqual(v, portNameProp)) { |
| obj["portName"] = portNameProp |
| } |
| protocolProp, err := expandComputeBackendServiceProtocol(d.Get("protocol"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("protocol"); !tpgresource.IsEmptyValue(reflect.ValueOf(protocolProp)) && (ok || !reflect.DeepEqual(v, protocolProp)) { |
| obj["protocol"] = protocolProp |
| } |
| securityPolicyProp, err := expandComputeBackendServiceSecurityPolicy(d.Get("security_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(securityPolicyProp)) && (ok || !reflect.DeepEqual(v, securityPolicyProp)) { |
| obj["securityPolicy"] = securityPolicyProp |
| } |
| edgeSecurityPolicyProp, err := expandComputeBackendServiceEdgeSecurityPolicy(d.Get("edge_security_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("edge_security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(edgeSecurityPolicyProp)) && (ok || !reflect.DeepEqual(v, edgeSecurityPolicyProp)) { |
| obj["edgeSecurityPolicy"] = edgeSecurityPolicyProp |
| } |
| securitySettingsProp, err := expandComputeBackendServiceSecuritySettings(d.Get("security_settings"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("security_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(securitySettingsProp)) && (ok || !reflect.DeepEqual(v, securitySettingsProp)) { |
| obj["securitySettings"] = securitySettingsProp |
| } |
| sessionAffinityProp, err := expandComputeBackendServiceSessionAffinity(d.Get("session_affinity"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("session_affinity"); !tpgresource.IsEmptyValue(reflect.ValueOf(sessionAffinityProp)) && (ok || !reflect.DeepEqual(v, sessionAffinityProp)) { |
| obj["sessionAffinity"] = sessionAffinityProp |
| } |
| timeoutSecProp, err := expandComputeBackendServiceTimeoutSec(d.Get("timeout_sec"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("timeout_sec"); !tpgresource.IsEmptyValue(reflect.ValueOf(timeoutSecProp)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { |
| obj["timeoutSec"] = timeoutSecProp |
| } |
| logConfigProp, err := expandComputeBackendServiceLogConfig(d.Get("log_config"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("log_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(logConfigProp)) && (ok || !reflect.DeepEqual(v, logConfigProp)) { |
| obj["logConfig"] = logConfigProp |
| } |
| serviceLbPolicyProp, err := expandComputeBackendServiceServiceLbPolicy(d.Get("service_lb_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("service_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(serviceLbPolicyProp)) && (ok || !reflect.DeepEqual(v, serviceLbPolicyProp)) { |
| obj["serviceLbPolicy"] = serviceLbPolicyProp |
| } |
| |
| obj, err = resourceComputeBackendServiceEncoder(d, meta, obj) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/backendServices") |
| if err != nil { |
| return err |
| } |
| |
| log.Printf("[DEBUG] Creating new BackendService: %#v", obj) |
| billingProject := "" |
| |
| project, err := tpgresource.GetProject(d, config) |
| if err != nil { |
| return fmt.Errorf("Error fetching project for BackendService: %s", err) |
| } |
| billingProject = project |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| headers := make(http.Header) |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "POST", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Body: obj, |
| Timeout: d.Timeout(schema.TimeoutCreate), |
| Headers: headers, |
| }) |
| if err != nil { |
| return fmt.Errorf("Error creating BackendService: %s", err) |
| } |
| |
| // Store the ID now |
| id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/global/backendServices/{{name}}") |
| if err != nil { |
| return fmt.Errorf("Error constructing id: %s", err) |
| } |
| d.SetId(id) |
| |
| err = ComputeOperationWaitTime( |
| config, res, project, "Creating BackendService", userAgent, |
| d.Timeout(schema.TimeoutCreate)) |
| |
| if err != nil { |
| // The resource didn't actually create |
| d.SetId("") |
| return fmt.Errorf("Error waiting to create BackendService: %s", err) |
| } |
| |
| // security_policy isn't set by Create / Update |
| if o, n := d.GetChange("security_policy"); o.(string) != n.(string) { |
| pol, err := tpgresource.ParseSecurityPolicyFieldValue(n.(string), d, config) |
| if err != nil { |
| return errwrap.Wrapf("Error parsing Backend Service security policy: {{err}}", err) |
| } |
| |
| spr := emptySecurityPolicyReference() |
| spr.SecurityPolicy = pol.RelativeLink() |
| op, err := config.NewComputeClient(userAgent).BackendServices.SetSecurityPolicy(project, obj["name"].(string), spr).Do() |
| if err != nil { |
| return errwrap.Wrapf("Error setting Backend Service security policy: {{err}}", err) |
| } |
| // This uses the create timeout for simplicity, though technically this code appears in both create and update |
| waitErr := ComputeOperationWaitTime(config, op, project, "Setting Backend Service Security Policy", userAgent, d.Timeout(schema.TimeoutCreate)) |
| if waitErr != nil { |
| return waitErr |
| } |
| } |
| // edge security_policy isn't set by Create / Update |
| if o, n := d.GetChange("edge_security_policy"); o.(string) != n.(string) { |
| pol, err := tpgresource.ParseSecurityPolicyFieldValue(n.(string), d, config) |
| if err != nil { |
| return errwrap.Wrapf("Error parsing Backend Service edge security policy: {{err}}", err) |
| } |
| |
| spr := emptySecurityPolicyReference() |
| spr.SecurityPolicy = pol.RelativeLink() |
| op, err := config.NewComputeClient(userAgent).BackendServices.SetEdgeSecurityPolicy(project, obj["name"].(string), spr).Do() |
| if err != nil { |
| return errwrap.Wrapf("Error setting Backend Service edge security policy: {{err}}", err) |
| } |
| // This uses the create timeout for simplicity, though technically this code appears in both create and update |
| waitErr := ComputeOperationWaitTime(config, op, project, "Setting Backend Service Edge Security Policy", userAgent, d.Timeout(schema.TimeoutCreate)) |
| if waitErr != nil { |
| return waitErr |
| } |
| } |
| |
| log.Printf("[DEBUG] Finished creating BackendService %q: %#v", d.Id(), res) |
| |
| return resourceComputeBackendServiceRead(d, meta) |
| } |
| |
| func resourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/backendServices/{{name}}") |
| if err != nil { |
| return err |
| } |
| |
| billingProject := "" |
| |
| project, err := tpgresource.GetProject(d, config) |
| if err != nil { |
| return fmt.Errorf("Error fetching project for BackendService: %s", err) |
| } |
| billingProject = project |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| headers := make(http.Header) |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "GET", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Headers: headers, |
| }) |
| if err != nil { |
| return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeBackendService %q", d.Id())) |
| } |
| |
| res, err = resourceComputeBackendServiceDecoder(d, meta, res) |
| if err != nil { |
| return err |
| } |
| |
| if res == nil { |
| // Decoding the object has resulted in it being gone. It may be marked deleted |
| log.Printf("[DEBUG] Removing ComputeBackendService because it no longer exists.") |
| d.SetId("") |
| return nil |
| } |
| |
| if err := d.Set("project", project); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| |
| if err := d.Set("affinity_cookie_ttl_sec", flattenComputeBackendServiceAffinityCookieTtlSec(res["affinityCookieTtlSec"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("backend", flattenComputeBackendServiceBackend(res["backends"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("circuit_breakers", flattenComputeBackendServiceCircuitBreakers(res["circuitBreakers"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("compression_mode", flattenComputeBackendServiceCompressionMode(res["compressionMode"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("consistent_hash", flattenComputeBackendServiceConsistentHash(res["consistentHash"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("cdn_policy", flattenComputeBackendServiceCdnPolicy(res["cdnPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| // Terraform must set the top level schema field, but since this object contains collapsed properties |
| // it's difficult to know what the top level should be. Instead we just loop over the map returned from flatten. |
| if flattenedProp := flattenComputeBackendServiceConnectionDraining(res["connectionDraining"], d, config); flattenedProp != nil { |
| if gerr, ok := flattenedProp.(*googleapi.Error); ok { |
| return fmt.Errorf("Error reading BackendService: %s", gerr) |
| } |
| casted := flattenedProp.([]interface{})[0] |
| if casted != nil { |
| for k, v := range casted.(map[string]interface{}) { |
| if err := d.Set(k, v); err != nil { |
| return fmt.Errorf("Error setting %s: %s", k, err) |
| } |
| } |
| } |
| } |
| if err := d.Set("creation_timestamp", flattenComputeBackendServiceCreationTimestamp(res["creationTimestamp"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("custom_request_headers", flattenComputeBackendServiceCustomRequestHeaders(res["customRequestHeaders"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("custom_response_headers", flattenComputeBackendServiceCustomResponseHeaders(res["customResponseHeaders"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("fingerprint", flattenComputeBackendServiceFingerprint(res["fingerprint"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("description", flattenComputeBackendServiceDescription(res["description"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("enable_cdn", flattenComputeBackendServiceEnableCDN(res["enableCDN"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("health_checks", flattenComputeBackendServiceHealthChecks(res["healthChecks"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("generated_id", flattenComputeBackendServiceGeneratedId(res["id"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("iap", flattenComputeBackendServiceIap(res["iap"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("load_balancing_scheme", flattenComputeBackendServiceLoadBalancingScheme(res["loadBalancingScheme"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("locality_lb_policy", flattenComputeBackendServiceLocalityLbPolicy(res["localityLbPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("locality_lb_policies", flattenComputeBackendServiceLocalityLbPolicies(res["localityLbPolicies"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("name", flattenComputeBackendServiceName(res["name"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("outlier_detection", flattenComputeBackendServiceOutlierDetection(res["outlierDetection"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("port_name", flattenComputeBackendServicePortName(res["portName"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("protocol", flattenComputeBackendServiceProtocol(res["protocol"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("security_policy", flattenComputeBackendServiceSecurityPolicy(res["securityPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("edge_security_policy", flattenComputeBackendServiceEdgeSecurityPolicy(res["edgeSecurityPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("security_settings", flattenComputeBackendServiceSecuritySettings(res["securitySettings"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("session_affinity", flattenComputeBackendServiceSessionAffinity(res["sessionAffinity"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("timeout_sec", flattenComputeBackendServiceTimeoutSec(res["timeoutSec"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("log_config", flattenComputeBackendServiceLogConfig(res["logConfig"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("service_lb_policy", flattenComputeBackendServiceServiceLbPolicy(res["serviceLbPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| if err := d.Set("self_link", tpgresource.ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { |
| return fmt.Errorf("Error reading BackendService: %s", err) |
| } |
| |
| return nil |
| } |
| |
| func resourceComputeBackendServiceUpdate(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| billingProject := "" |
| |
| project, err := tpgresource.GetProject(d, config) |
| if err != nil { |
| return fmt.Errorf("Error fetching project for BackendService: %s", err) |
| } |
| billingProject = project |
| |
| obj := make(map[string]interface{}) |
| affinityCookieTtlSecProp, err := expandComputeBackendServiceAffinityCookieTtlSec(d.Get("affinity_cookie_ttl_sec"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("affinity_cookie_ttl_sec"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, affinityCookieTtlSecProp)) { |
| obj["affinityCookieTtlSec"] = affinityCookieTtlSecProp |
| } |
| backendsProp, err := expandComputeBackendServiceBackend(d.Get("backend"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("backend"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, backendsProp)) { |
| obj["backends"] = backendsProp |
| } |
| circuitBreakersProp, err := expandComputeBackendServiceCircuitBreakers(d.Get("circuit_breakers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("circuit_breakers"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, circuitBreakersProp)) { |
| obj["circuitBreakers"] = circuitBreakersProp |
| } |
| compressionModeProp, err := expandComputeBackendServiceCompressionMode(d.Get("compression_mode"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("compression_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, compressionModeProp)) { |
| obj["compressionMode"] = compressionModeProp |
| } |
| consistentHashProp, err := expandComputeBackendServiceConsistentHash(d.Get("consistent_hash"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("consistent_hash"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, consistentHashProp)) { |
| obj["consistentHash"] = consistentHashProp |
| } |
| cdnPolicyProp, err := expandComputeBackendServiceCdnPolicy(d.Get("cdn_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("cdn_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, cdnPolicyProp)) { |
| obj["cdnPolicy"] = cdnPolicyProp |
| } |
| connectionDrainingProp, err := expandComputeBackendServiceConnectionDraining(nil, d, config) |
| if err != nil { |
| return err |
| } else if !tpgresource.IsEmptyValue(reflect.ValueOf(connectionDrainingProp)) { |
| obj["connectionDraining"] = connectionDrainingProp |
| } |
| customRequestHeadersProp, err := expandComputeBackendServiceCustomRequestHeaders(d.Get("custom_request_headers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("custom_request_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, customRequestHeadersProp)) { |
| obj["customRequestHeaders"] = customRequestHeadersProp |
| } |
| customResponseHeadersProp, err := expandComputeBackendServiceCustomResponseHeaders(d.Get("custom_response_headers"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("custom_response_headers"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, customResponseHeadersProp)) { |
| obj["customResponseHeaders"] = customResponseHeadersProp |
| } |
| fingerprintProp, err := expandComputeBackendServiceFingerprint(d.Get("fingerprint"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { |
| obj["fingerprint"] = fingerprintProp |
| } |
| descriptionProp, err := expandComputeBackendServiceDescription(d.Get("description"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { |
| obj["description"] = descriptionProp |
| } |
| enableCDNProp, err := expandComputeBackendServiceEnableCDN(d.Get("enable_cdn"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("enable_cdn"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, enableCDNProp)) { |
| obj["enableCDN"] = enableCDNProp |
| } |
| healthChecksProp, err := expandComputeBackendServiceHealthChecks(d.Get("health_checks"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("health_checks"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, healthChecksProp)) { |
| obj["healthChecks"] = healthChecksProp |
| } |
| iapProp, err := expandComputeBackendServiceIap(d.Get("iap"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("iap"); ok || !reflect.DeepEqual(v, iapProp) { |
| obj["iap"] = iapProp |
| } |
| loadBalancingSchemeProp, err := expandComputeBackendServiceLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("load_balancing_scheme"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { |
| obj["loadBalancingScheme"] = loadBalancingSchemeProp |
| } |
| localityLbPolicyProp, err := expandComputeBackendServiceLocalityLbPolicy(d.Get("locality_lb_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("locality_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, localityLbPolicyProp)) { |
| obj["localityLbPolicy"] = localityLbPolicyProp |
| } |
| localityLbPoliciesProp, err := expandComputeBackendServiceLocalityLbPolicies(d.Get("locality_lb_policies"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("locality_lb_policies"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, localityLbPoliciesProp)) { |
| obj["localityLbPolicies"] = localityLbPoliciesProp |
| } |
| nameProp, err := expandComputeBackendServiceName(d.Get("name"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { |
| obj["name"] = nameProp |
| } |
| outlierDetectionProp, err := expandComputeBackendServiceOutlierDetection(d.Get("outlier_detection"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("outlier_detection"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, outlierDetectionProp)) { |
| obj["outlierDetection"] = outlierDetectionProp |
| } |
| portNameProp, err := expandComputeBackendServicePortName(d.Get("port_name"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("port_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, portNameProp)) { |
| obj["portName"] = portNameProp |
| } |
| protocolProp, err := expandComputeBackendServiceProtocol(d.Get("protocol"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("protocol"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, protocolProp)) { |
| obj["protocol"] = protocolProp |
| } |
| securityPolicyProp, err := expandComputeBackendServiceSecurityPolicy(d.Get("security_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, securityPolicyProp)) { |
| obj["securityPolicy"] = securityPolicyProp |
| } |
| edgeSecurityPolicyProp, err := expandComputeBackendServiceEdgeSecurityPolicy(d.Get("edge_security_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("edge_security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, edgeSecurityPolicyProp)) { |
| obj["edgeSecurityPolicy"] = edgeSecurityPolicyProp |
| } |
| securitySettingsProp, err := expandComputeBackendServiceSecuritySettings(d.Get("security_settings"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("security_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, securitySettingsProp)) { |
| obj["securitySettings"] = securitySettingsProp |
| } |
| sessionAffinityProp, err := expandComputeBackendServiceSessionAffinity(d.Get("session_affinity"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("session_affinity"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sessionAffinityProp)) { |
| obj["sessionAffinity"] = sessionAffinityProp |
| } |
| timeoutSecProp, err := expandComputeBackendServiceTimeoutSec(d.Get("timeout_sec"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("timeout_sec"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { |
| obj["timeoutSec"] = timeoutSecProp |
| } |
| logConfigProp, err := expandComputeBackendServiceLogConfig(d.Get("log_config"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("log_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, logConfigProp)) { |
| obj["logConfig"] = logConfigProp |
| } |
| serviceLbPolicyProp, err := expandComputeBackendServiceServiceLbPolicy(d.Get("service_lb_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("service_lb_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serviceLbPolicyProp)) { |
| obj["serviceLbPolicy"] = serviceLbPolicyProp |
| } |
| |
| obj, err = resourceComputeBackendServiceEncoder(d, meta, obj) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/backendServices/{{name}}") |
| if err != nil { |
| return err |
| } |
| |
| log.Printf("[DEBUG] Updating BackendService %q: %#v", d.Id(), obj) |
| headers := make(http.Header) |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "PUT", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Body: obj, |
| Timeout: d.Timeout(schema.TimeoutUpdate), |
| Headers: headers, |
| }) |
| |
| if err != nil { |
| return fmt.Errorf("Error updating BackendService %q: %s", d.Id(), err) |
| } else { |
| log.Printf("[DEBUG] Finished updating BackendService %q: %#v", d.Id(), res) |
| } |
| |
| err = ComputeOperationWaitTime( |
| config, res, project, "Updating BackendService", userAgent, |
| d.Timeout(schema.TimeoutUpdate)) |
| |
| if err != nil { |
| return err |
| } |
| |
| // security_policy isn't set by Create / Update |
| if o, n := d.GetChange("security_policy"); o.(string) != n.(string) { |
| pol, err := tpgresource.ParseSecurityPolicyFieldValue(n.(string), d, config) |
| if err != nil { |
| return errwrap.Wrapf("Error parsing Backend Service security policy: {{err}}", err) |
| } |
| |
| spr := emptySecurityPolicyReference() |
| spr.SecurityPolicy = pol.RelativeLink() |
| op, err := config.NewComputeClient(userAgent).BackendServices.SetSecurityPolicy(project, obj["name"].(string), spr).Do() |
| if err != nil { |
| return errwrap.Wrapf("Error setting Backend Service security policy: {{err}}", err) |
| } |
| // This uses the create timeout for simplicity, though technically this code appears in both create and update |
| waitErr := ComputeOperationWaitTime(config, op, project, "Setting Backend Service Security Policy", userAgent, d.Timeout(schema.TimeoutCreate)) |
| if waitErr != nil { |
| return waitErr |
| } |
| } |
| // edge security_policy isn't set by Create / Update |
| if o, n := d.GetChange("edge_security_policy"); o.(string) != n.(string) { |
| pol, err := tpgresource.ParseSecurityPolicyFieldValue(n.(string), d, config) |
| if err != nil { |
| return errwrap.Wrapf("Error parsing Backend Service edge security policy: {{err}}", err) |
| } |
| |
| spr := emptySecurityPolicyReference() |
| spr.SecurityPolicy = pol.RelativeLink() |
| op, err := config.NewComputeClient(userAgent).BackendServices.SetEdgeSecurityPolicy(project, obj["name"].(string), spr).Do() |
| if err != nil { |
| return errwrap.Wrapf("Error setting Backend Service edge security policy: {{err}}", err) |
| } |
| // This uses the create timeout for simplicity, though technically this code appears in both create and update |
| waitErr := ComputeOperationWaitTime(config, op, project, "Setting Backend Service Edge Security Policy", userAgent, d.Timeout(schema.TimeoutCreate)) |
| if waitErr != nil { |
| return waitErr |
| } |
| } |
| return resourceComputeBackendServiceRead(d, meta) |
| } |
| |
| func resourceComputeBackendServiceDelete(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| billingProject := "" |
| |
| project, err := tpgresource.GetProject(d, config) |
| if err != nil { |
| return fmt.Errorf("Error fetching project for BackendService: %s", err) |
| } |
| billingProject = project |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/backendServices/{{name}}") |
| if err != nil { |
| return err |
| } |
| |
| var obj map[string]interface{} |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| headers := make(http.Header) |
| |
| log.Printf("[DEBUG] Deleting BackendService %q", d.Id()) |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "DELETE", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Body: obj, |
| Timeout: d.Timeout(schema.TimeoutDelete), |
| Headers: headers, |
| }) |
| if err != nil { |
| return transport_tpg.HandleNotFoundError(err, d, "BackendService") |
| } |
| |
| err = ComputeOperationWaitTime( |
| config, res, project, "Deleting BackendService", userAgent, |
| d.Timeout(schema.TimeoutDelete)) |
| |
| if err != nil { |
| return err |
| } |
| |
| log.Printf("[DEBUG] Finished deleting BackendService %q: %#v", d.Id(), res) |
| return nil |
| } |
| |
| func resourceComputeBackendServiceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { |
| config := meta.(*transport_tpg.Config) |
| if err := tpgresource.ParseImportId([]string{ |
| "^projects/(?P<project>[^/]+)/global/backendServices/(?P<name>[^/]+)$", |
| "^(?P<project>[^/]+)/(?P<name>[^/]+)$", |
| "^(?P<name>[^/]+)$", |
| }, d, config); err != nil { |
| return nil, err |
| } |
| |
| // Replace import id for the resource id |
| id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/global/backendServices/{{name}}") |
| if err != nil { |
| return nil, fmt.Errorf("Error constructing id: %s", err) |
| } |
| d.SetId(id) |
| |
| return []*schema.ResourceData{d}, nil |
| } |
| |
| func flattenComputeBackendServiceAffinityCookieTtlSec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceBackend(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| l := v.([]interface{}) |
| transformed := schema.NewSet(resourceGoogleComputeBackendServiceBackendHash, []interface{}{}) |
| for _, raw := range l { |
| original := raw.(map[string]interface{}) |
| if len(original) < 1 { |
| // Do not include empty json objects coming back from the api |
| continue |
| } |
| transformed.Add(map[string]interface{}{ |
| "balancing_mode": flattenComputeBackendServiceBackendBalancingMode(original["balancingMode"], d, config), |
| "capacity_scaler": flattenComputeBackendServiceBackendCapacityScaler(original["capacityScaler"], d, config), |
| "description": flattenComputeBackendServiceBackendDescription(original["description"], d, config), |
| "group": flattenComputeBackendServiceBackendGroup(original["group"], d, config), |
| "max_connections": flattenComputeBackendServiceBackendMaxConnections(original["maxConnections"], d, config), |
| "max_connections_per_instance": flattenComputeBackendServiceBackendMaxConnectionsPerInstance(original["maxConnectionsPerInstance"], d, config), |
| "max_connections_per_endpoint": flattenComputeBackendServiceBackendMaxConnectionsPerEndpoint(original["maxConnectionsPerEndpoint"], d, config), |
| "max_rate": flattenComputeBackendServiceBackendMaxRate(original["maxRate"], d, config), |
| "max_rate_per_instance": flattenComputeBackendServiceBackendMaxRatePerInstance(original["maxRatePerInstance"], d, config), |
| "max_rate_per_endpoint": flattenComputeBackendServiceBackendMaxRatePerEndpoint(original["maxRatePerEndpoint"], d, config), |
| "max_utilization": flattenComputeBackendServiceBackendMaxUtilization(original["maxUtilization"], d, config), |
| }) |
| } |
| return transformed |
| } |
| func flattenComputeBackendServiceBackendBalancingMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceBackendCapacityScaler(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceBackendDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceBackendGroup(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return tpgresource.ConvertSelfLinkToV1(v.(string)) |
| } |
| |
| func flattenComputeBackendServiceBackendMaxConnections(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceBackendMaxConnectionsPerInstance(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceBackendMaxConnectionsPerEndpoint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceBackendMaxRate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceBackendMaxRatePerInstance(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceBackendMaxRatePerEndpoint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceBackendMaxUtilization(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["connect_timeout"] = |
| flattenComputeBackendServiceCircuitBreakersConnectTimeout(original["connectTimeout"], d, config) |
| transformed["max_requests_per_connection"] = |
| flattenComputeBackendServiceCircuitBreakersMaxRequestsPerConnection(original["maxRequestsPerConnection"], d, config) |
| transformed["max_connections"] = |
| flattenComputeBackendServiceCircuitBreakersMaxConnections(original["maxConnections"], d, config) |
| transformed["max_pending_requests"] = |
| flattenComputeBackendServiceCircuitBreakersMaxPendingRequests(original["maxPendingRequests"], d, config) |
| transformed["max_requests"] = |
| flattenComputeBackendServiceCircuitBreakersMaxRequests(original["maxRequests"], d, config) |
| transformed["max_retries"] = |
| flattenComputeBackendServiceCircuitBreakersMaxRetries(original["maxRetries"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceCircuitBreakersConnectTimeout(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["seconds"] = |
| flattenComputeBackendServiceCircuitBreakersConnectTimeoutSeconds(original["seconds"], d, config) |
| transformed["nanos"] = |
| flattenComputeBackendServiceCircuitBreakersConnectTimeoutNanos(original["nanos"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceCircuitBreakersConnectTimeoutSeconds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersConnectTimeoutNanos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersMaxRequestsPerConnection(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersMaxConnections(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersMaxPendingRequests(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersMaxRequests(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCircuitBreakersMaxRetries(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCompressionMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceConsistentHash(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["http_cookie"] = |
| flattenComputeBackendServiceConsistentHashHttpCookie(original["httpCookie"], d, config) |
| transformed["http_header_name"] = |
| flattenComputeBackendServiceConsistentHashHttpHeaderName(original["httpHeaderName"], d, config) |
| transformed["minimum_ring_size"] = |
| flattenComputeBackendServiceConsistentHashMinimumRingSize(original["minimumRingSize"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceConsistentHashHttpCookie(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["ttl"] = |
| flattenComputeBackendServiceConsistentHashHttpCookieTtl(original["ttl"], d, config) |
| transformed["name"] = |
| flattenComputeBackendServiceConsistentHashHttpCookieName(original["name"], d, config) |
| transformed["path"] = |
| flattenComputeBackendServiceConsistentHashHttpCookiePath(original["path"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceConsistentHashHttpCookieTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["seconds"] = |
| flattenComputeBackendServiceConsistentHashHttpCookieTtlSeconds(original["seconds"], d, config) |
| transformed["nanos"] = |
| flattenComputeBackendServiceConsistentHashHttpCookieTtlNanos(original["nanos"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceConsistentHashHttpCookieTtlSeconds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceConsistentHashHttpCookieTtlNanos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceConsistentHashHttpCookieName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceConsistentHashHttpCookiePath(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceConsistentHashHttpHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceConsistentHashMinimumRingSize(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["cache_key_policy"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicy(original["cacheKeyPolicy"], d, config) |
| transformed["signed_url_cache_max_age_sec"] = |
| flattenComputeBackendServiceCdnPolicySignedUrlCacheMaxAgeSec(original["signedUrlCacheMaxAgeSec"], d, config) |
| transformed["default_ttl"] = |
| flattenComputeBackendServiceCdnPolicyDefaultTtl(original["defaultTtl"], d, config) |
| transformed["max_ttl"] = |
| flattenComputeBackendServiceCdnPolicyMaxTtl(original["maxTtl"], d, config) |
| transformed["client_ttl"] = |
| flattenComputeBackendServiceCdnPolicyClientTtl(original["clientTtl"], d, config) |
| transformed["negative_caching"] = |
| flattenComputeBackendServiceCdnPolicyNegativeCaching(original["negativeCaching"], d, config) |
| transformed["negative_caching_policy"] = |
| flattenComputeBackendServiceCdnPolicyNegativeCachingPolicy(original["negativeCachingPolicy"], d, config) |
| transformed["cache_mode"] = |
| flattenComputeBackendServiceCdnPolicyCacheMode(original["cacheMode"], d, config) |
| transformed["serve_while_stale"] = |
| flattenComputeBackendServiceCdnPolicyServeWhileStale(original["serveWhileStale"], d, config) |
| transformed["bypass_cache_on_request_headers"] = |
| flattenComputeBackendServiceCdnPolicyBypassCacheOnRequestHeaders(original["bypassCacheOnRequestHeaders"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["include_host"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHost(original["includeHost"], d, config) |
| transformed["include_protocol"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeProtocol(original["includeProtocol"], d, config) |
| transformed["include_query_string"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeQueryString(original["includeQueryString"], d, config) |
| transformed["query_string_blacklist"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringBlacklist(original["queryStringBlacklist"], d, config) |
| transformed["query_string_whitelist"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringWhitelist(original["queryStringWhitelist"], d, config) |
| transformed["include_http_headers"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHttpHeaders(original["includeHttpHeaders"], d, config) |
| transformed["include_named_cookies"] = |
| flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeNamedCookies(original["includeNamedCookies"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHost(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeProtocol(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeQueryString(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringBlacklist(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return schema.NewSet(schema.HashString, v.([]interface{})) |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringWhitelist(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return schema.NewSet(schema.HashString, v.([]interface{})) |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHttpHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeNamedCookies(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicySignedUrlCacheMaxAgeSec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyDefaultTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyMaxTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyClientTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyNegativeCaching(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyNegativeCachingPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| l := v.([]interface{}) |
| transformed := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| original := raw.(map[string]interface{}) |
| if len(original) < 1 { |
| // Do not include empty json objects coming back from the api |
| continue |
| } |
| transformed = append(transformed, map[string]interface{}{ |
| "code": flattenComputeBackendServiceCdnPolicyNegativeCachingPolicyCode(original["code"], d, config), |
| "ttl": flattenComputeBackendServiceCdnPolicyNegativeCachingPolicyTtl(original["ttl"], d, config), |
| }) |
| } |
| return transformed |
| } |
| func flattenComputeBackendServiceCdnPolicyNegativeCachingPolicyCode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyNegativeCachingPolicyTtl(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyCacheMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyServeWhileStale(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCdnPolicyBypassCacheOnRequestHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| l := v.([]interface{}) |
| transformed := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| original := raw.(map[string]interface{}) |
| if len(original) < 1 { |
| // Do not include empty json objects coming back from the api |
| continue |
| } |
| transformed = append(transformed, map[string]interface{}{ |
| "header_name": flattenComputeBackendServiceCdnPolicyBypassCacheOnRequestHeadersHeaderName(original["headerName"], d, config), |
| }) |
| } |
| return transformed |
| } |
| func flattenComputeBackendServiceCdnPolicyBypassCacheOnRequestHeadersHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceConnectionDraining(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["connection_draining_timeout_sec"] = |
| flattenComputeBackendServiceConnectionDrainingConnectionDrainingTimeoutSec(original["drainingTimeoutSec"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceConnectionDrainingConnectionDrainingTimeoutSec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceCreationTimestamp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceCustomRequestHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return schema.NewSet(schema.HashString, v.([]interface{})) |
| } |
| |
| func flattenComputeBackendServiceCustomResponseHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return schema.NewSet(schema.HashString, v.([]interface{})) |
| } |
| |
| func flattenComputeBackendServiceFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceEnableCDN(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceHealthChecks(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1) |
| } |
| |
| func flattenComputeBackendServiceGeneratedId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceIap(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["enabled"] = |
| flattenComputeBackendServiceIapEnabled(original["enabled"], d, config) |
| transformed["oauth2_client_id"] = |
| flattenComputeBackendServiceIapOauth2ClientId(original["oauth2ClientId"], d, config) |
| transformed["oauth2_client_secret"] = |
| flattenComputeBackendServiceIapOauth2ClientSecret(original["oauth2ClientSecret"], d, config) |
| transformed["oauth2_client_secret_sha256"] = |
| flattenComputeBackendServiceIapOauth2ClientSecretSha256(original["oauth2ClientSecretSha256"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceIapEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceIapOauth2ClientId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceIapOauth2ClientSecret(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return d.Get("iap.0.oauth2_client_secret") |
| } |
| |
| func flattenComputeBackendServiceIapOauth2ClientSecretSha256(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLoadBalancingScheme(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLocalityLbPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLocalityLbPolicies(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| l := v.([]interface{}) |
| transformed := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| original := raw.(map[string]interface{}) |
| if len(original) < 1 { |
| // Do not include empty json objects coming back from the api |
| continue |
| } |
| transformed = append(transformed, map[string]interface{}{ |
| "policy": flattenComputeBackendServiceLocalityLbPoliciesPolicy(original["policy"], d, config), |
| "custom_policy": flattenComputeBackendServiceLocalityLbPoliciesCustomPolicy(original["customPolicy"], d, config), |
| }) |
| } |
| return transformed |
| } |
| func flattenComputeBackendServiceLocalityLbPoliciesPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["name"] = |
| flattenComputeBackendServiceLocalityLbPoliciesPolicyName(original["name"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceLocalityLbPoliciesPolicyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLocalityLbPoliciesCustomPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["name"] = |
| flattenComputeBackendServiceLocalityLbPoliciesCustomPolicyName(original["name"], d, config) |
| transformed["data"] = |
| flattenComputeBackendServiceLocalityLbPoliciesCustomPolicyData(original["data"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceLocalityLbPoliciesCustomPolicyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLocalityLbPoliciesCustomPolicyData(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceOutlierDetection(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["base_ejection_time"] = |
| flattenComputeBackendServiceOutlierDetectionBaseEjectionTime(original["baseEjectionTime"], d, config) |
| transformed["consecutive_errors"] = |
| flattenComputeBackendServiceOutlierDetectionConsecutiveErrors(original["consecutiveErrors"], d, config) |
| transformed["consecutive_gateway_failure"] = |
| flattenComputeBackendServiceOutlierDetectionConsecutiveGatewayFailure(original["consecutiveGatewayFailure"], d, config) |
| transformed["enforcing_consecutive_errors"] = |
| flattenComputeBackendServiceOutlierDetectionEnforcingConsecutiveErrors(original["enforcingConsecutiveErrors"], d, config) |
| transformed["enforcing_consecutive_gateway_failure"] = |
| flattenComputeBackendServiceOutlierDetectionEnforcingConsecutiveGatewayFailure(original["enforcingConsecutiveGatewayFailure"], d, config) |
| transformed["enforcing_success_rate"] = |
| flattenComputeBackendServiceOutlierDetectionEnforcingSuccessRate(original["enforcingSuccessRate"], d, config) |
| transformed["interval"] = |
| flattenComputeBackendServiceOutlierDetectionInterval(original["interval"], d, config) |
| transformed["max_ejection_percent"] = |
| flattenComputeBackendServiceOutlierDetectionMaxEjectionPercent(original["maxEjectionPercent"], d, config) |
| transformed["success_rate_minimum_hosts"] = |
| flattenComputeBackendServiceOutlierDetectionSuccessRateMinimumHosts(original["successRateMinimumHosts"], d, config) |
| transformed["success_rate_request_volume"] = |
| flattenComputeBackendServiceOutlierDetectionSuccessRateRequestVolume(original["successRateRequestVolume"], d, config) |
| transformed["success_rate_stdev_factor"] = |
| flattenComputeBackendServiceOutlierDetectionSuccessRateStdevFactor(original["successRateStdevFactor"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceOutlierDetectionBaseEjectionTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["seconds"] = |
| flattenComputeBackendServiceOutlierDetectionBaseEjectionTimeSeconds(original["seconds"], d, config) |
| transformed["nanos"] = |
| flattenComputeBackendServiceOutlierDetectionBaseEjectionTimeNanos(original["nanos"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceOutlierDetectionBaseEjectionTimeSeconds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionBaseEjectionTimeNanos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionConsecutiveErrors(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionConsecutiveGatewayFailure(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionEnforcingConsecutiveErrors(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionEnforcingConsecutiveGatewayFailure(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionEnforcingSuccessRate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionInterval(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["seconds"] = |
| flattenComputeBackendServiceOutlierDetectionIntervalSeconds(original["seconds"], d, config) |
| transformed["nanos"] = |
| flattenComputeBackendServiceOutlierDetectionIntervalNanos(original["nanos"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceOutlierDetectionIntervalSeconds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionIntervalNanos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionMaxEjectionPercent(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionSuccessRateMinimumHosts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionSuccessRateRequestVolume(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceOutlierDetectionSuccessRateStdevFactor(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServicePortName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceProtocol(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSecurityPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceEdgeSecurityPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSecuritySettings(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["client_tls_policy"] = |
| flattenComputeBackendServiceSecuritySettingsClientTlsPolicy(original["clientTlsPolicy"], d, config) |
| transformed["subject_alt_names"] = |
| flattenComputeBackendServiceSecuritySettingsSubjectAltNames(original["subjectAltNames"], d, config) |
| transformed["aws_v4_authentication"] = |
| flattenComputeBackendServiceSecuritySettingsAwsV4Authentication(original["awsV4Authentication"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceSecuritySettingsClientTlsPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| return tpgresource.ConvertSelfLinkToV1(v.(string)) |
| } |
| |
| func flattenComputeBackendServiceSecuritySettingsSubjectAltNames(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSecuritySettingsAwsV4Authentication(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["access_key_id"] = |
| flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyId(original["accessKeyId"], d, config) |
| transformed["access_key"] = |
| flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKey(original["accessKey"], d, config) |
| transformed["access_key_version"] = |
| flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyVersion(original["accessKeyVersion"], d, config) |
| transformed["origin_region"] = |
| flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationOriginRegion(original["originRegion"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return d.Get("security_settings.0.aws_v4_authentication.0.access_key") |
| } |
| |
| func flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyVersion(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSecuritySettingsAwsV4AuthenticationOriginRegion(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceSessionAffinity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceTimeoutSec(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| // Handles the string fixed64 format |
| if strVal, ok := v.(string); ok { |
| if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { |
| return intVal |
| } |
| } |
| |
| // number values are represented as float64 |
| if floatVal, ok := v.(float64); ok { |
| intVal := int(floatVal) |
| return intVal |
| } |
| |
| return v // let terraform core handle it otherwise |
| } |
| |
| func flattenComputeBackendServiceLogConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["enable"] = |
| flattenComputeBackendServiceLogConfigEnable(original["enable"], d, config) |
| transformed["sample_rate"] = |
| flattenComputeBackendServiceLogConfigSampleRate(original["sampleRate"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenComputeBackendServiceLogConfigEnable(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceLogConfigSampleRate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenComputeBackendServiceServiceLbPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func expandComputeBackendServiceAffinityCookieTtlSec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackend(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| l := v.([]interface{}) |
| req := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| if raw == nil { |
| continue |
| } |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedBalancingMode, err := expandComputeBackendServiceBackendBalancingMode(original["balancing_mode"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedBalancingMode); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["balancingMode"] = transformedBalancingMode |
| } |
| |
| transformedCapacityScaler, err := expandComputeBackendServiceBackendCapacityScaler(original["capacity_scaler"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["capacityScaler"] = transformedCapacityScaler |
| } |
| |
| transformedDescription, err := expandComputeBackendServiceBackendDescription(original["description"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["description"] = transformedDescription |
| } |
| |
| transformedGroup, err := expandComputeBackendServiceBackendGroup(original["group"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedGroup); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["group"] = transformedGroup |
| } |
| |
| transformedMaxConnections, err := expandComputeBackendServiceBackendMaxConnections(original["max_connections"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxConnections); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxConnections"] = transformedMaxConnections |
| } |
| |
| transformedMaxConnectionsPerInstance, err := expandComputeBackendServiceBackendMaxConnectionsPerInstance(original["max_connections_per_instance"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxConnectionsPerInstance); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxConnectionsPerInstance"] = transformedMaxConnectionsPerInstance |
| } |
| |
| transformedMaxConnectionsPerEndpoint, err := expandComputeBackendServiceBackendMaxConnectionsPerEndpoint(original["max_connections_per_endpoint"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxConnectionsPerEndpoint); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxConnectionsPerEndpoint"] = transformedMaxConnectionsPerEndpoint |
| } |
| |
| transformedMaxRate, err := expandComputeBackendServiceBackendMaxRate(original["max_rate"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRate); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRate"] = transformedMaxRate |
| } |
| |
| transformedMaxRatePerInstance, err := expandComputeBackendServiceBackendMaxRatePerInstance(original["max_rate_per_instance"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRatePerInstance); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRatePerInstance"] = transformedMaxRatePerInstance |
| } |
| |
| transformedMaxRatePerEndpoint, err := expandComputeBackendServiceBackendMaxRatePerEndpoint(original["max_rate_per_endpoint"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRatePerEndpoint); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRatePerEndpoint"] = transformedMaxRatePerEndpoint |
| } |
| |
| transformedMaxUtilization, err := expandComputeBackendServiceBackendMaxUtilization(original["max_utilization"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxUtilization); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxUtilization"] = transformedMaxUtilization |
| } |
| |
| req = append(req, transformed) |
| } |
| return req, nil |
| } |
| |
| func expandComputeBackendServiceBackendBalancingMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendCapacityScaler(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendGroup(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxConnections(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxConnectionsPerInstance(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxConnectionsPerEndpoint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxRate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxRatePerInstance(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxRatePerEndpoint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceBackendMaxUtilization(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakers(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedConnectTimeout, err := expandComputeBackendServiceCircuitBreakersConnectTimeout(original["connect_timeout"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedConnectTimeout); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["connectTimeout"] = transformedConnectTimeout |
| } |
| |
| transformedMaxRequestsPerConnection, err := expandComputeBackendServiceCircuitBreakersMaxRequestsPerConnection(original["max_requests_per_connection"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRequestsPerConnection); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRequestsPerConnection"] = transformedMaxRequestsPerConnection |
| } |
| |
| transformedMaxConnections, err := expandComputeBackendServiceCircuitBreakersMaxConnections(original["max_connections"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxConnections); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxConnections"] = transformedMaxConnections |
| } |
| |
| transformedMaxPendingRequests, err := expandComputeBackendServiceCircuitBreakersMaxPendingRequests(original["max_pending_requests"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxPendingRequests); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxPendingRequests"] = transformedMaxPendingRequests |
| } |
| |
| transformedMaxRequests, err := expandComputeBackendServiceCircuitBreakersMaxRequests(original["max_requests"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRequests); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRequests"] = transformedMaxRequests |
| } |
| |
| transformedMaxRetries, err := expandComputeBackendServiceCircuitBreakersMaxRetries(original["max_retries"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxRetries); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxRetries"] = transformedMaxRetries |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersConnectTimeout(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedSeconds, err := expandComputeBackendServiceCircuitBreakersConnectTimeoutSeconds(original["seconds"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["seconds"] = transformedSeconds |
| } |
| |
| transformedNanos, err := expandComputeBackendServiceCircuitBreakersConnectTimeoutNanos(original["nanos"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["nanos"] = transformedNanos |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersConnectTimeoutSeconds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersConnectTimeoutNanos(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersMaxRequestsPerConnection(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersMaxConnections(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersMaxPendingRequests(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersMaxRequests(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCircuitBreakersMaxRetries(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCompressionMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHash(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedHttpCookie, err := expandComputeBackendServiceConsistentHashHttpCookie(original["http_cookie"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedHttpCookie); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["httpCookie"] = transformedHttpCookie |
| } |
| |
| transformedHttpHeaderName, err := expandComputeBackendServiceConsistentHashHttpHeaderName(original["http_header_name"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedHttpHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["httpHeaderName"] = transformedHttpHeaderName |
| } |
| |
| transformedMinimumRingSize, err := expandComputeBackendServiceConsistentHashMinimumRingSize(original["minimum_ring_size"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMinimumRingSize); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["minimumRingSize"] = transformedMinimumRingSize |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookie(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedTtl, err := expandComputeBackendServiceConsistentHashHttpCookieTtl(original["ttl"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedTtl); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["ttl"] = transformedTtl |
| } |
| |
| transformedName, err := expandComputeBackendServiceConsistentHashHttpCookieName(original["name"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["name"] = transformedName |
| } |
| |
| transformedPath, err := expandComputeBackendServiceConsistentHashHttpCookiePath(original["path"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedPath); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["path"] = transformedPath |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookieTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedSeconds, err := expandComputeBackendServiceConsistentHashHttpCookieTtlSeconds(original["seconds"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["seconds"] = transformedSeconds |
| } |
| |
| transformedNanos, err := expandComputeBackendServiceConsistentHashHttpCookieTtlNanos(original["nanos"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["nanos"] = transformedNanos |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookieTtlSeconds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookieTtlNanos(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookieName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpCookiePath(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashHttpHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConsistentHashMinimumRingSize(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedCacheKeyPolicy, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicy(original["cache_key_policy"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedCacheKeyPolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["cacheKeyPolicy"] = transformedCacheKeyPolicy |
| } |
| |
| transformedSignedUrlCacheMaxAgeSec, err := expandComputeBackendServiceCdnPolicySignedUrlCacheMaxAgeSec(original["signed_url_cache_max_age_sec"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSignedUrlCacheMaxAgeSec); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["signedUrlCacheMaxAgeSec"] = transformedSignedUrlCacheMaxAgeSec |
| } |
| |
| transformedDefaultTtl, err := expandComputeBackendServiceCdnPolicyDefaultTtl(original["default_ttl"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedDefaultTtl); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["defaultTtl"] = transformedDefaultTtl |
| } |
| |
| transformedMaxTtl, err := expandComputeBackendServiceCdnPolicyMaxTtl(original["max_ttl"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxTtl); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxTtl"] = transformedMaxTtl |
| } |
| |
| transformedClientTtl, err := expandComputeBackendServiceCdnPolicyClientTtl(original["client_ttl"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedClientTtl); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["clientTtl"] = transformedClientTtl |
| } |
| |
| transformedNegativeCaching, err := expandComputeBackendServiceCdnPolicyNegativeCaching(original["negative_caching"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["negativeCaching"] = transformedNegativeCaching |
| } |
| |
| transformedNegativeCachingPolicy, err := expandComputeBackendServiceCdnPolicyNegativeCachingPolicy(original["negative_caching_policy"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedNegativeCachingPolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["negativeCachingPolicy"] = transformedNegativeCachingPolicy |
| } |
| |
| transformedCacheMode, err := expandComputeBackendServiceCdnPolicyCacheMode(original["cache_mode"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedCacheMode); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["cacheMode"] = transformedCacheMode |
| } |
| |
| transformedServeWhileStale, err := expandComputeBackendServiceCdnPolicyServeWhileStale(original["serve_while_stale"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["serveWhileStale"] = transformedServeWhileStale |
| } |
| |
| transformedBypassCacheOnRequestHeaders, err := expandComputeBackendServiceCdnPolicyBypassCacheOnRequestHeaders(original["bypass_cache_on_request_headers"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedBypassCacheOnRequestHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["bypassCacheOnRequestHeaders"] = transformedBypassCacheOnRequestHeaders |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedIncludeHost, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHost(original["include_host"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["includeHost"] = transformedIncludeHost |
| } |
| |
| transformedIncludeProtocol, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeProtocol(original["include_protocol"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["includeProtocol"] = transformedIncludeProtocol |
| } |
| |
| transformedIncludeQueryString, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeQueryString(original["include_query_string"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["includeQueryString"] = transformedIncludeQueryString |
| } |
| |
| transformedQueryStringBlacklist, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringBlacklist(original["query_string_blacklist"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["queryStringBlacklist"] = transformedQueryStringBlacklist |
| } |
| |
| transformedQueryStringWhitelist, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringWhitelist(original["query_string_whitelist"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["queryStringWhitelist"] = transformedQueryStringWhitelist |
| } |
| |
| transformedIncludeHttpHeaders, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHttpHeaders(original["include_http_headers"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["includeHttpHeaders"] = transformedIncludeHttpHeaders |
| } |
| |
| transformedIncludeNamedCookies, err := expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeNamedCookies(original["include_named_cookies"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["includeNamedCookies"] = transformedIncludeNamedCookies |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHost(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeProtocol(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeQueryString(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringBlacklist(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyQueryStringWhitelist(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeHttpHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheKeyPolicyIncludeNamedCookies(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicySignedUrlCacheMaxAgeSec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyDefaultTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyMaxTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyClientTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyNegativeCaching(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyNegativeCachingPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| req := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| if raw == nil { |
| continue |
| } |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedCode, err := expandComputeBackendServiceCdnPolicyNegativeCachingPolicyCode(original["code"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedCode); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["code"] = transformedCode |
| } |
| |
| transformedTtl, err := expandComputeBackendServiceCdnPolicyNegativeCachingPolicyTtl(original["ttl"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["ttl"] = transformedTtl |
| } |
| |
| req = append(req, transformed) |
| } |
| return req, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyNegativeCachingPolicyCode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyNegativeCachingPolicyTtl(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyCacheMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyServeWhileStale(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyBypassCacheOnRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| req := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| if raw == nil { |
| continue |
| } |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedHeaderName, err := expandComputeBackendServiceCdnPolicyBypassCacheOnRequestHeadersHeaderName(original["header_name"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["headerName"] = transformedHeaderName |
| } |
| |
| req = append(req, transformed) |
| } |
| return req, nil |
| } |
| |
| func expandComputeBackendServiceCdnPolicyBypassCacheOnRequestHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceConnectionDraining(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| transformed := make(map[string]interface{}) |
| transformedConnectionDrainingTimeoutSec, err := expandComputeBackendServiceConnectionDrainingConnectionDrainingTimeoutSec(d.Get("connection_draining_timeout_sec"), d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedConnectionDrainingTimeoutSec); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["drainingTimeoutSec"] = transformedConnectionDrainingTimeoutSec |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceConnectionDrainingConnectionDrainingTimeoutSec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCustomRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceCustomResponseHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceEnableCDN(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceHealthChecks(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| v = v.(*schema.Set).List() |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceIap(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedEnabled, err := expandComputeBackendServiceIapEnabled(original["enabled"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["enabled"] = transformedEnabled |
| } |
| |
| transformedOauth2ClientId, err := expandComputeBackendServiceIapOauth2ClientId(original["oauth2_client_id"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedOauth2ClientId); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["oauth2ClientId"] = transformedOauth2ClientId |
| } |
| |
| transformedOauth2ClientSecret, err := expandComputeBackendServiceIapOauth2ClientSecret(original["oauth2_client_secret"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["oauth2ClientSecret"] = transformedOauth2ClientSecret |
| } |
| |
| transformedOauth2ClientSecretSha256, err := expandComputeBackendServiceIapOauth2ClientSecretSha256(original["oauth2_client_secret_sha256"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedOauth2ClientSecretSha256); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["oauth2ClientSecretSha256"] = transformedOauth2ClientSecretSha256 |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceIapEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceIapOauth2ClientId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceIapOauth2ClientSecret(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceIapOauth2ClientSecretSha256(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLoadBalancingScheme(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPolicies(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| req := make([]interface{}, 0, len(l)) |
| for _, raw := range l { |
| if raw == nil { |
| continue |
| } |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedPolicy, err := expandComputeBackendServiceLocalityLbPoliciesPolicy(original["policy"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedPolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["policy"] = transformedPolicy |
| } |
| |
| transformedCustomPolicy, err := expandComputeBackendServiceLocalityLbPoliciesCustomPolicy(original["custom_policy"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedCustomPolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["customPolicy"] = transformedCustomPolicy |
| } |
| |
| req = append(req, transformed) |
| } |
| return req, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPoliciesPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedName, err := expandComputeBackendServiceLocalityLbPoliciesPolicyName(original["name"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["name"] = transformedName |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPoliciesPolicyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPoliciesCustomPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedName, err := expandComputeBackendServiceLocalityLbPoliciesCustomPolicyName(original["name"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["name"] = transformedName |
| } |
| |
| transformedData, err := expandComputeBackendServiceLocalityLbPoliciesCustomPolicyData(original["data"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedData); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["data"] = transformedData |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPoliciesCustomPolicyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLocalityLbPoliciesCustomPolicyData(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetection(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedBaseEjectionTime, err := expandComputeBackendServiceOutlierDetectionBaseEjectionTime(original["base_ejection_time"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedBaseEjectionTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["baseEjectionTime"] = transformedBaseEjectionTime |
| } |
| |
| transformedConsecutiveErrors, err := expandComputeBackendServiceOutlierDetectionConsecutiveErrors(original["consecutive_errors"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedConsecutiveErrors); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["consecutiveErrors"] = transformedConsecutiveErrors |
| } |
| |
| transformedConsecutiveGatewayFailure, err := expandComputeBackendServiceOutlierDetectionConsecutiveGatewayFailure(original["consecutive_gateway_failure"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedConsecutiveGatewayFailure); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["consecutiveGatewayFailure"] = transformedConsecutiveGatewayFailure |
| } |
| |
| transformedEnforcingConsecutiveErrors, err := expandComputeBackendServiceOutlierDetectionEnforcingConsecutiveErrors(original["enforcing_consecutive_errors"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedEnforcingConsecutiveErrors); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["enforcingConsecutiveErrors"] = transformedEnforcingConsecutiveErrors |
| } |
| |
| transformedEnforcingConsecutiveGatewayFailure, err := expandComputeBackendServiceOutlierDetectionEnforcingConsecutiveGatewayFailure(original["enforcing_consecutive_gateway_failure"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedEnforcingConsecutiveGatewayFailure); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["enforcingConsecutiveGatewayFailure"] = transformedEnforcingConsecutiveGatewayFailure |
| } |
| |
| transformedEnforcingSuccessRate, err := expandComputeBackendServiceOutlierDetectionEnforcingSuccessRate(original["enforcing_success_rate"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedEnforcingSuccessRate); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["enforcingSuccessRate"] = transformedEnforcingSuccessRate |
| } |
| |
| transformedInterval, err := expandComputeBackendServiceOutlierDetectionInterval(original["interval"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedInterval); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["interval"] = transformedInterval |
| } |
| |
| transformedMaxEjectionPercent, err := expandComputeBackendServiceOutlierDetectionMaxEjectionPercent(original["max_ejection_percent"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedMaxEjectionPercent); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["maxEjectionPercent"] = transformedMaxEjectionPercent |
| } |
| |
| transformedSuccessRateMinimumHosts, err := expandComputeBackendServiceOutlierDetectionSuccessRateMinimumHosts(original["success_rate_minimum_hosts"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSuccessRateMinimumHosts); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["successRateMinimumHosts"] = transformedSuccessRateMinimumHosts |
| } |
| |
| transformedSuccessRateRequestVolume, err := expandComputeBackendServiceOutlierDetectionSuccessRateRequestVolume(original["success_rate_request_volume"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSuccessRateRequestVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["successRateRequestVolume"] = transformedSuccessRateRequestVolume |
| } |
| |
| transformedSuccessRateStdevFactor, err := expandComputeBackendServiceOutlierDetectionSuccessRateStdevFactor(original["success_rate_stdev_factor"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSuccessRateStdevFactor); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["successRateStdevFactor"] = transformedSuccessRateStdevFactor |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionBaseEjectionTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedSeconds, err := expandComputeBackendServiceOutlierDetectionBaseEjectionTimeSeconds(original["seconds"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["seconds"] = transformedSeconds |
| } |
| |
| transformedNanos, err := expandComputeBackendServiceOutlierDetectionBaseEjectionTimeNanos(original["nanos"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["nanos"] = transformedNanos |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionBaseEjectionTimeSeconds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionBaseEjectionTimeNanos(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionConsecutiveErrors(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionConsecutiveGatewayFailure(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionEnforcingConsecutiveErrors(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionEnforcingConsecutiveGatewayFailure(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionEnforcingSuccessRate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionInterval(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedSeconds, err := expandComputeBackendServiceOutlierDetectionIntervalSeconds(original["seconds"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["seconds"] = transformedSeconds |
| } |
| |
| transformedNanos, err := expandComputeBackendServiceOutlierDetectionIntervalNanos(original["nanos"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["nanos"] = transformedNanos |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionIntervalSeconds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionIntervalNanos(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionMaxEjectionPercent(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionSuccessRateMinimumHosts(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionSuccessRateRequestVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceOutlierDetectionSuccessRateStdevFactor(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServicePortName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceProtocol(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecurityPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceEdgeSecurityPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedClientTlsPolicy, err := expandComputeBackendServiceSecuritySettingsClientTlsPolicy(original["client_tls_policy"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedClientTlsPolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["clientTlsPolicy"] = transformedClientTlsPolicy |
| } |
| |
| transformedSubjectAltNames, err := expandComputeBackendServiceSecuritySettingsSubjectAltNames(original["subject_alt_names"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSubjectAltNames); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["subjectAltNames"] = transformedSubjectAltNames |
| } |
| |
| transformedAwsV4Authentication, err := expandComputeBackendServiceSecuritySettingsAwsV4Authentication(original["aws_v4_authentication"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedAwsV4Authentication); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["awsV4Authentication"] = transformedAwsV4Authentication |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsClientTlsPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsSubjectAltNames(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsAwsV4Authentication(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedAccessKeyId, err := expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyId(original["access_key_id"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedAccessKeyId); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["accessKeyId"] = transformedAccessKeyId |
| } |
| |
| transformedAccessKey, err := expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKey(original["access_key"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["accessKey"] = transformedAccessKey |
| } |
| |
| transformedAccessKeyVersion, err := expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyVersion(original["access_key_version"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedAccessKeyVersion); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["accessKeyVersion"] = transformedAccessKeyVersion |
| } |
| |
| transformedOriginRegion, err := expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationOriginRegion(original["origin_region"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedOriginRegion); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["originRegion"] = transformedOriginRegion |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationAccessKeyVersion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSecuritySettingsAwsV4AuthenticationOriginRegion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceSessionAffinity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceTimeoutSec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLogConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedEnable, err := expandComputeBackendServiceLogConfigEnable(original["enable"], d, config) |
| if err != nil { |
| return nil, err |
| } else { |
| transformed["enable"] = transformedEnable |
| } |
| |
| transformedSampleRate, err := expandComputeBackendServiceLogConfigSampleRate(original["sample_rate"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedSampleRate); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["sampleRate"] = transformedSampleRate |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandComputeBackendServiceLogConfigEnable(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceLogConfigSampleRate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandComputeBackendServiceServiceLbPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func resourceComputeBackendServiceEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { |
| backendsRaw, ok := obj["backends"] |
| if !ok { |
| return obj, nil |
| } |
| backends := backendsRaw.([]interface{}) |
| for _, backendRaw := range backends { |
| backend := backendRaw.(map[string]interface{}) |
| |
| if isNegBackend(backend) { |
| // Remove `max_utilization` from any backend that belongs to an NEG. This field |
| // has a default value and causes API validation errors |
| backend["maxUtilization"] = nil |
| } |
| } |
| |
| // This custom encoding helps prevent sending 0 for clientTtl, defaultTtl and |
| // maxTtl in API calls to update these values when unset in the provider |
| // (doing so results in an API level error) |
| c, cdnPolicyOk := d.GetOk("cdn_policy") |
| |
| // Only apply during updates |
| if !cdnPolicyOk || obj["cdnPolicy"] == nil { |
| return obj, nil |
| } |
| |
| currentCdnPolicies := c.([]interface{}) |
| |
| // state does not contain cdnPolicy, so we can return early here as well |
| if len(currentCdnPolicies) == 0 { |
| return obj, nil |
| } |
| |
| futureCdnPolicy := obj["cdnPolicy"].(map[string]interface{}) |
| currentCdnPolicy := currentCdnPolicies[0].(map[string]interface{}) |
| |
| cacheMode, ok := futureCdnPolicy["cache_mode"].(string) |
| // Fallback to state if doesn't exist in object |
| if !ok { |
| cacheMode = currentCdnPolicy["cache_mode"].(string) |
| } |
| |
| switch cacheMode { |
| case "USE_ORIGIN_HEADERS": |
| if _, ok := futureCdnPolicy["clientTtl"]; ok { |
| delete(futureCdnPolicy, "clientTtl") |
| } |
| if _, ok := futureCdnPolicy["defaultTtl"]; ok { |
| delete(futureCdnPolicy, "defaultTtl") |
| } |
| if _, ok := futureCdnPolicy["maxTtl"]; ok { |
| delete(futureCdnPolicy, "maxTtl") |
| } |
| } |
| |
| return obj, nil |
| } |
| |
| func resourceComputeBackendServiceDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { |
| // Requests with consistentHash will error for specific values of |
| // localityLbPolicy. However, the API will not remove it if the backend |
| // service is updated to from supporting to non-supporting localityLbPolicy |
| // (e.g. RING_HASH to RANDOM), which causes an error on subsequent update. |
| // In order to prevent errors, we ignore any consistentHash returned |
| // from the API when the localityLbPolicy doesn't support it. |
| if v, ok := res["localityLbPolicy"]; ok { |
| lbPolicy := v.(string) |
| if lbPolicy != "MAGLEV" && lbPolicy != "RING_HASH" { |
| delete(res, "consistentHash") |
| } |
| } |
| |
| return res, nil |
| } |