From f860da35ac47b724a4b343b99432ae94b32f3297 Mon Sep 17 00:00:00 2001 From: The Magician Date: Wed, 8 Sep 2021 01:36:31 -0500 Subject: [PATCH] Global forwarding rule and forwarding rule DCL conversion. (#5138) (#10030) * Add forwarding rule to tpgtools. Signed-off-by: Modular Magician --- .changelog/5138.txt | 2 + go.mod | 2 +- go.sum | 6 + ...rce_google_compute_forwarding_rule_test.go | 2 +- ...gle_global_compute_forwarding_rule_test.go | 2 +- google/resource_compute_forwarding_rule.go | 1002 +++++------------ ..._compute_forwarding_rule_generated_test.go | 4 +- ...ce_compute_forwarding_rule_sweeper_test.go | 104 +- ...resource_compute_global_forwarding_rule.go | 834 ++++++-------- ...e_global_forwarding_rule_generated_test.go | 7 +- ...ute_global_forwarding_rule_sweeper_test.go | 104 +- ...rce_compute_global_forwarding_rule_test.go | 21 +- 12 files changed, 727 insertions(+), 1363 deletions(-) create mode 100644 .changelog/5138.txt diff --git a/.changelog/5138.txt b/.changelog/5138.txt new file mode 100644 index 00000000000..e4e22fc1e47 --- /dev/null +++ b/.changelog/5138.txt @@ -0,0 +1,2 @@ +```release-note:none +``` diff --git a/go.mod b/go.mod index bfde44eff8d..83d409cc238 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/hashicorp/terraform-provider-google require ( cloud.google.com/go/bigtable v1.10.1 - github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210824221031-bbef03d2748a + github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210901222754-f6c1204eeae9 github.com/apparentlymart/go-cidr v1.1.0 github.com/client9/misspell v0.3.4 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 7fc3f73e5e8..1f336365d28 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,12 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOC github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210901222754-f6c1204eeae9 h1:b4+4SWkgDcBSTpKYvl+SaUDZ/PwEMfnuI1z41qPy+z8= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210901222754-f6c1204eeae9/go.mod h1:oEeBHikdF/NrnUy0ornVaY1OT+jGvTqm+LQS0+ZDKzU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210830202814-90d607e5aba1 h1:Cq6wsP8cz8yoyIqVe9qXiuLv6myB3jY5aCobrvTN5WQ= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210830202814-90d607e5aba1/go.mod h1:oEeBHikdF/NrnUy0ornVaY1OT+jGvTqm+LQS0+ZDKzU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210828005957-5e300a425b22 h1:r1uW7IkHP90/jxMW8Br+DzEK2wuZQs0JFYC6T5foazk= +github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210828005957-5e300a425b22/go.mod h1:oEeBHikdF/NrnUy0ornVaY1OT+jGvTqm+LQS0+ZDKzU= github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210824221031-bbef03d2748a h1:k71tcjN3d1+YrSB1cN2d9T787JjbwbfNFM6HarBrn2o= github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210824221031-bbef03d2748a/go.mod h1:oEeBHikdF/NrnUy0ornVaY1OT+jGvTqm+LQS0+ZDKzU= github.com/GoogleCloudPlatform/declarative-resource-client-library v0.0.0-20210623224421-7f5af5003bbb h1:9HBI5n77Z2ReBlOFk1h2JFLpY/HobH9Xaq90E7IjCpw= diff --git a/google/data_source_google_compute_forwarding_rule_test.go b/google/data_source_google_compute_forwarding_rule_test.go index 2538ac1c727..03966829c6b 100644 --- a/google/data_source_google_compute_forwarding_rule_test.go +++ b/google/data_source_google_compute_forwarding_rule_test.go @@ -19,7 +19,7 @@ func TestAccDataSourceGoogleForwardingRule(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleForwardingRuleConfig(poolName, ruleName), - Check: checkDataSourceStateMatchesResourceState("data.google_compute_forwarding_rule.my_forwarding_rule", "google_compute_forwarding_rule.foobar-fr"), + Check: checkDataSourceStateMatchesResourceStateWithIgnores("data.google_compute_forwarding_rule.my_forwarding_rule", "google_compute_forwarding_rule.foobar-fr", map[string]struct{}{"port_range": {}, "target": {}}), }, }, }) diff --git a/google/data_source_google_global_compute_forwarding_rule_test.go b/google/data_source_google_global_compute_forwarding_rule_test.go index ec276b52c53..79768efa5d5 100644 --- a/google/data_source_google_global_compute_forwarding_rule_test.go +++ b/google/data_source_google_global_compute_forwarding_rule_test.go @@ -19,7 +19,7 @@ func TestAccDataSourceGoogleGlobalForwardingRule(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleGlobalForwardingRuleConfig(poolName, ruleName), - Check: checkDataSourceStateMatchesResourceState("data.google_compute_global_forwarding_rule.my_forwarding_rule", "google_compute_global_forwarding_rule.foobar-fr"), + Check: checkDataSourceStateMatchesResourceStateWithIgnores("data.google_compute_global_forwarding_rule.my_forwarding_rule", "google_compute_global_forwarding_rule.foobar-fr", map[string]struct{}{"port_range": {}, "target": {}}), }, }, }) diff --git a/google/resource_compute_forwarding_rule.go b/google/resource_compute_forwarding_rule.go index 0b19c34b5d6..5f77fb10b70 100644 --- a/google/resource_compute_forwarding_rule.go +++ b/google/resource_compute_forwarding_rule.go @@ -1,28 +1,31 @@ // ---------------------------------------------------------------------------- // -// *** AUTO GENERATED CODE *** Type: MMv1 *** +// *** AUTO GENERATED CODE *** Type: DCL *** // // ---------------------------------------------------------------------------- // -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. // -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose // // ---------------------------------------------------------------------------- package google import ( + "context" "fmt" "log" - "reflect" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" ) func resourceComputeForwardingRule() *schema.Resource { @@ -37,409 +40,251 @@ func resourceComputeForwardingRule() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(4 * time.Minute), - Update: schema.DefaultTimeout(4 * time.Minute), - Delete: schema.DefaultTimeout(4 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), }, 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.`, + 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](https://www.ietf.org/rfc/rfc1035.txt). 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.", + }, + + "all_ports": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: "This field is used along with the `backend_service` field for internal load balancing or with the `target` field for internal TargetInstance. This field cannot be used with `port` or `portRange` fields. When the load balancing scheme is `INTERNAL` and protocol is TCP/UDP, specify this field to allow packets addressed to any ports will be forwarded to the backends configured with this forwarding rule.", + }, + + "allow_global_access": { + Type: schema.TypeBool, + Optional: true, + Description: "This field is used along with the `backend_service` field for internal load balancing or with the `target` field for internal TargetInstance. If the field is set to `TRUE`, clients can access ILB from all regions. Otherwise only allows access from clients in the same region as the internal load balancer.", + }, + + "backend_service": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "This field is only used for `INTERNAL` load balancing. For internal load balancing, this field identifies the BackendService resource to receive the matched traffic.", + }, + + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "An optional description of this resource. Provide this property when you create the resource.", }, + "ip_address": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, DiffSuppressFunc: internalIpDiffSuppress, - Description: `The IP address that this forwarding rule serves. When a client sends -traffic to this IP address, the forwarding rule directs the traffic to -the target that you specify in the forwarding rule. The -loadBalancingScheme and the forwarding rule's target determine the -type of IP address that you can use. For detailed information, refer -to [IP address specifications](https://cloud.google.com/load-balancing/docs/forwarding-rule-concepts#ip_address_specifications). - -An address can be specified either by a literal IP address or a -reference to an existing Address resource. If you don't specify a -reserved IP address, an ephemeral IP address is assigned. - -The value must be set to 0.0.0.0 when the target is a targetGrpcProxy -that has validateForProxyless field set to true. - -For Private Service Connect forwarding rules that forward traffic to -Google APIs, IP address must be provided.`, + Description: "IP address that this forwarding rule serves. When a client sends traffic to this IP address, the forwarding rule directs the traffic to the target that you specify in the forwarding rule. If you don't specify a reserved IP address, an ephemeral IP address is assigned. Methods for specifying an IP address: * IPv4 dotted decimal, as in `100.1.2.3` * Full URL, as in `https://www.googleapis.com/compute/v1/projects/project_id/regions/region/addresses/address-name` * Partial URL or by name, as in: * `projects/project_id/regions/region/addresses/address-name` * `regions/region/addresses/address-name` * `global/addresses/address-name` * `address-name` The loadBalancingScheme and the forwarding rule's target determine the type of IP address that you can use. For detailed information, refer to [IP address specifications](/load-balancing/docs/forwarding-rule-concepts#ip_address_specifications).", }, + "ip_protocol": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"TCP", "UDP", "ESP", "AH", "SCTP", "ICMP", "L3_DEFAULT", ""}, false), DiffSuppressFunc: caseDiffSuppress, - Description: `The IP protocol to which this rule applies. - -When the load balancing scheme is INTERNAL, only TCP and UDP are -valid. Possible values: ["TCP", "UDP", "ESP", "AH", "SCTP", "ICMP", "L3_DEFAULT"]`, - }, - "all_ports": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - Description: `This field can be used with internal load balancer or network load balancer -when the forwarding rule references a backend service, or with the target -field when it references a TargetInstance. Set this to true to -allow packets addressed to any ports to be forwarded to the backends configured -with this forwarding rule. This can be used when the protocol is TCP/UDP, and it -must be set to true when the protocol is set to L3_DEFAULT. -Cannot be set if port or portRange are set.`, - }, - "allow_global_access": { - Type: schema.TypeBool, - Optional: true, - Description: `If true, clients can access ILB from all regions. -Otherwise only allows from the local region the ILB is located at.`, - }, - "backend_service": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `A BackendService to receive the matched traffic. This is used only -for INTERNAL load balancing.`, - }, - "description": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: `An optional description of this resource. Provide this property when -you create the resource.`, + Description: "The IP protocol to which this rule applies. For protocol forwarding, valid options are `TCP`, `UDP`, `ESP`, `AH`, `SCTP` or `ICMP`. For Internal TCP/UDP Load Balancing, the load balancing scheme is `INTERNAL`, and one of `TCP` or `UDP` are valid. For Traffic Director, the load balancing scheme is `INTERNAL_SELF_MANAGED`, and only `TCP`is valid. For Internal HTTP(S) Load Balancing, the load balancing scheme is `INTERNAL_MANAGED`, and only `TCP` is valid. For HTTP(S), SSL Proxy, and TCP Proxy Load Balancing, the load balancing scheme is `EXTERNAL` and only `TCP` is valid. For Network TCP/UDP Load Balancing, the load balancing scheme is `EXTERNAL`, and one of `TCP` or `UDP` is valid.", + ValidateFunc: validation.StringInSlice([]string{"TCP", "UDP", "ESP", "AH", "SCTP", "ICMP", "L3_DEFAULT", ""}, false), }, + "is_mirroring_collector": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - Description: `Indicates whether or not this load balancer can be used -as a collector for packet mirroring. To prevent mirroring loops, -instances behind this load balancer will not have their traffic -mirrored even if a PacketMirroring rule applies to them. This -can only be set to true for load balancers that have their -loadBalancingScheme set to INTERNAL.`, + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: "Indicates whether or not this load balancer can be used as a collector for packet mirroring. To prevent mirroring loops, instances behind this load balancer will not have their traffic mirrored even if a `PacketMirroring` rule applies to them. This can only be set to true for load balancers that have their `loadBalancingScheme` set to `INTERNAL`.", + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: "Labels to apply to this rule.", + Elem: &schema.Schema{Type: schema.TypeString}, }, + "load_balancing_scheme": { Type: schema.TypeString, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"EXTERNAL", "INTERNAL", "INTERNAL_MANAGED", ""}, false), - Description: `This signifies what the ForwardingRule will be used for and can be -EXTERNAL, INTERNAL, or INTERNAL_MANAGED. EXTERNAL is used for Classic -Cloud VPN gateways, protocol forwarding to VMs from an external IP address, -and HTTP(S), SSL Proxy, TCP Proxy, and Network TCP/UDP load balancers. -INTERNAL is used for protocol forwarding to VMs from an internal IP address, -and internal TCP/UDP load balancers. -INTERNAL_MANAGED is used for internal HTTP(S) load balancers. Default value: "EXTERNAL" Possible values: ["EXTERNAL", "INTERNAL", "INTERNAL_MANAGED"]`, - Default: "EXTERNAL", + Description: "Specifies the forwarding rule type.\n\n* `EXTERNAL` is used for:\n * Classic Cloud VPN gateways\n * Protocol forwarding to VMs from an external IP address\n * The following load balancers: HTTP(S), SSL Proxy, TCP Proxy, and Network TCP/UDP\n* `INTERNAL` is used for:\n * Protocol forwarding to VMs from an internal IP address\n * Internal TCP/UDP load balancers\n* `INTERNAL_MANAGED` is used for:\n * Internal HTTP(S) load balancers\n* `INTERNAL_SELF_MANAGED` is used for:\n * Traffic Director\n\nFor more information about forwarding rules, refer to [Forwarding rule concepts](/load-balancing/docs/forwarding-rule-concepts). Possible values: INVALID, INTERNAL, INTERNAL_MANAGED, INTERNAL_SELF_MANAGED, EXTERNAL", + Default: "EXTERNAL", + ValidateFunc: validation.StringInSlice([]string{"INVALID", "INTERNAL", "INTERNAL_MANAGED", "INTERNAL_SELF_MANAGED", "EXTERNAL", ""}, false), }, + "network": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `For internal load balancing, this field identifies the network that -the load balanced IP should belong to for this Forwarding Rule. If -this field is not specified, the default network will be used. -This field is only used for INTERNAL load balancing.`, + Description: "This field is not used for external load balancing. For `INTERNAL` and `INTERNAL_SELF_MANAGED` load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", }, + "network_tier": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, + Description: "This signifies the networking tier used for configuring this load balancer and can only take the following values: `PREMIUM`, `STANDARD`. For regional ForwardingRule, the valid values are `PREMIUM` and `STANDARD`. For GlobalForwardingRule, the valid value is `PREMIUM`. If this field is not specified, it is assumed to be `PREMIUM`. If `IPAddress` is specified, this value must be equal to the networkTier of the Address.", ValidateFunc: validation.StringInSlice([]string{"PREMIUM", "STANDARD", ""}, false), - Description: `The networking tier used for configuring this address. If this field is not -specified, it is assumed to be PREMIUM. Possible values: ["PREMIUM", "STANDARD"]`, }, + "port_range": { Type: schema.TypeString, Optional: true, ForceNew: true, DiffSuppressFunc: portRangeDiffSuppress, - Description: `This field is used along with the target field for TargetHttpProxy, -TargetHttpsProxy, TargetSslProxy, TargetTcpProxy, TargetVpnGateway, -TargetPool, TargetInstance. - -Applicable only when IPProtocol is TCP, UDP, or SCTP, only packets -addressed to ports in the specified range will be forwarded to target. -Forwarding rules with the same [IPAddress, IPProtocol] pair must have -disjoint port ranges. - -Some types of forwarding target have constraints on the acceptable -ports: - -* TargetHttpProxy: 80, 8080 -* TargetHttpsProxy: 443 -* TargetTcpProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, - 1883, 5222 -* TargetSslProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, - 1883, 5222 -* TargetVpnGateway: 500, 4500`, + Description: "When the load balancing scheme is `EXTERNAL`, `INTERNAL_SELF_MANAGED` and `INTERNAL_MANAGED`, you can specify a `port_range`. Use with a forwarding rule that points to a target proxy or a target pool. Do not use with a forwarding rule that points to a backend service. This field is used along with the `target` field for TargetHttpProxy, TargetHttpsProxy, TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance. Applicable only when `IPProtocol` is `TCP`, `UDP`, or `SCTP`, only packets addressed to ports in the specified range will be forwarded to `target`. Forwarding rules with the same `[IPAddress, IPProtocol]` pair must have disjoint port ranges. Some types of forwarding target have constraints on the acceptable ports:\n\n* TargetHttpProxy: 80, 8080\n* TargetHttpsProxy: 443\n* TargetTcpProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, 1688, 1883, 5222\n* TargetSslProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, 1688, 1883, 5222\n* TargetVpnGateway: 500, 4500\n\n@pattern: d+(?:-d+)?", }, + "ports": { - Type: schema.TypeSet, - Optional: true, - ForceNew: true, - Description: `This field is used along with internal load balancing and network -load balancer when the forwarding rule references a backend service -and when protocol is not L3_DEFAULT. - -A single port or a comma separated list of ports can be configured. -Only packets addressed to these ports will be forwarded to the backends -configured with this forwarding rule. - -You can only use one of ports and portRange, or allPorts. -The three are mutually exclusive. - -You may specify a maximum of up to 5 ports, which can be non-contiguous.`, - MaxItems: 5, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Set: schema.HashString, + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Description: "This field is used along with the `backend_service` field for internal load balancing. When the load balancing scheme is `INTERNAL`, a list of ports can be configured, for example, ['80'], ['8000','9000']. Only packets addressed to these ports are forwarded to the backends configured with the forwarding rule. If the forwarding rule's loadBalancingScheme is INTERNAL, you can specify ports in one of the following ways: * A list of up to five ports, which can be non-contiguous * Keyword `ALL`, which causes the forwarding rule to forward traffic on any port of the forwarding rule's protocol. @pattern: d+(?:-d+)? For more information, refer to [Port specifications](/load-balancing/docs/forwarding-rule-concepts#port_specifications).", + MaxItems: 5, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The project this resource belongs in.", }, + "region": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `A reference to the region where the regional forwarding rule resides. -This field is not applicable to global forwarding rules.`, + Description: "The location of this resource.", }, + "service_label": { Type: schema.TypeString, Optional: true, ForceNew: true, + Description: "An optional prefix to the service name for this Forwarding Rule. If specified, the prefix is the first label of the fully qualified service name. The label must be 1-63 characters long, and comply with [RFC1035](https://www.ietf.org/rfc/rfc1035.txt). Specifically, the label 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. This field is only used for internal load balancing.", ValidateFunc: validateGCPName, - Description: `An optional prefix to the service name for this Forwarding Rule. -If specified, will be the first label of the fully qualified service -name. - -The label must be 1-63 characters long, and comply with RFC1035. -Specifically, the label 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. - -This field is only used for INTERNAL load balancing.`, }, + "subnetwork": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, DiffSuppressFunc: compareSelfLinkOrResourceName, - Description: `The subnetwork that the load balanced IP should belong to for this -Forwarding Rule. This field is only used for INTERNAL load balancing. - -If the network specified is in auto subnet mode, this field is -optional. However, if the network is in custom subnet mode, a -subnetwork must be specified.`, + Description: "This field is only used for `INTERNAL` load balancing. For internal load balancing, this field identifies the subnetwork that the load balanced IP should belong to for this Forwarding Rule. If the network specified is in auto subnet mode, this field is optional. However, if the network is in custom subnet mode, a subnetwork must be specified.", }, + "target": { Type: schema.TypeString, Optional: true, DiffSuppressFunc: compareSelfLinkRelativePaths, - Description: `The URL of the target resource to receive the matched traffic. -The target must live in the same region as the forwarding rule. -The forwarded traffic must be of a type appropriate to the target -object.`, + Description: "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object. For `INTERNAL_SELF_MANAGED` load balancing, only `targetHttpProxy` is valid, not `targetHttpsProxy`.", }, + "creation_timestamp": { Type: schema.TypeString, Computed: true, - Description: `Creation timestamp in RFC3339 text format.`, + Description: "[Output Only] Creation timestamp in [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) text format.", }, - "service_name": { - Type: schema.TypeString, - Computed: true, - Description: `The internal fully qualified service name for this Forwarding Rule. -This field is only used for INTERNAL load balancing.`, - }, - "project": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, + + "label_fingerprint": { + Type: schema.TypeString, + Computed: true, + Description: "Used internally during label updates.", }, + "self_link": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] Server-defined URL for the resource.", + }, + + "service_name": { + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] The internal fully qualified service name for this Forwarding Rule. This field is only used for internal load balancing.", }, }, - UseJSONNumber: true, } } func resourceComputeForwardingRuleCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) - if err != nil { - return err - } - - obj := make(map[string]interface{}) - isMirroringCollectorProp, err := expandComputeForwardingRuleIsMirroringCollector(d.Get("is_mirroring_collector"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("is_mirroring_collector"); !isEmptyValue(reflect.ValueOf(isMirroringCollectorProp)) && (ok || !reflect.DeepEqual(v, isMirroringCollectorProp)) { - obj["isMirroringCollector"] = isMirroringCollectorProp - } - descriptionProp, err := expandComputeForwardingRuleDescription(d.Get("description"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { - obj["description"] = descriptionProp - } - IPAddressProp, err := expandComputeForwardingRuleIPAddress(d.Get("ip_address"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ip_address"); !isEmptyValue(reflect.ValueOf(IPAddressProp)) && (ok || !reflect.DeepEqual(v, IPAddressProp)) { - obj["IPAddress"] = IPAddressProp - } - IPProtocolProp, err := expandComputeForwardingRuleIPProtocol(d.Get("ip_protocol"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ip_protocol"); !isEmptyValue(reflect.ValueOf(IPProtocolProp)) && (ok || !reflect.DeepEqual(v, IPProtocolProp)) { - obj["IPProtocol"] = IPProtocolProp - } - backendServiceProp, err := expandComputeForwardingRuleBackendService(d.Get("backend_service"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("backend_service"); !isEmptyValue(reflect.ValueOf(backendServiceProp)) && (ok || !reflect.DeepEqual(v, backendServiceProp)) { - obj["backendService"] = backendServiceProp - } - loadBalancingSchemeProp, err := expandComputeForwardingRuleLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("load_balancing_scheme"); !isEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { - obj["loadBalancingScheme"] = loadBalancingSchemeProp - } - nameProp, err := expandComputeForwardingRuleName(d.Get("name"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { - obj["name"] = nameProp - } - networkProp, err := expandComputeForwardingRuleNetwork(d.Get("network"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { - obj["network"] = networkProp - } - portRangeProp, err := expandComputeForwardingRulePortRange(d.Get("port_range"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("port_range"); !isEmptyValue(reflect.ValueOf(portRangeProp)) && (ok || !reflect.DeepEqual(v, portRangeProp)) { - obj["portRange"] = portRangeProp - } - portsProp, err := expandComputeForwardingRulePorts(d.Get("ports"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ports"); !isEmptyValue(reflect.ValueOf(portsProp)) && (ok || !reflect.DeepEqual(v, portsProp)) { - obj["ports"] = portsProp - } - subnetworkProp, err := expandComputeForwardingRuleSubnetwork(d.Get("subnetwork"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("subnetwork"); !isEmptyValue(reflect.ValueOf(subnetworkProp)) && (ok || !reflect.DeepEqual(v, subnetworkProp)) { - obj["subnetwork"] = subnetworkProp - } - targetProp, err := expandComputeForwardingRuleTarget(d.Get("target"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) { - obj["target"] = targetProp - } - allowGlobalAccessProp, err := expandComputeForwardingRuleAllowGlobalAccess(d.Get("allow_global_access"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("allow_global_access"); ok || !reflect.DeepEqual(v, allowGlobalAccessProp) { - obj["allowGlobalAccess"] = allowGlobalAccessProp - } - allPortsProp, err := expandComputeForwardingRuleAllPorts(d.Get("all_ports"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("all_ports"); !isEmptyValue(reflect.ValueOf(allPortsProp)) && (ok || !reflect.DeepEqual(v, allPortsProp)) { - obj["allPorts"] = allPortsProp - } - networkTierProp, err := expandComputeForwardingRuleNetworkTier(d.Get("network_tier"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("network_tier"); !isEmptyValue(reflect.ValueOf(networkTierProp)) && (ok || !reflect.DeepEqual(v, networkTierProp)) { - obj["networkTier"] = networkTierProp - } - serviceLabelProp, err := expandComputeForwardingRuleServiceLabel(d.Get("service_label"), d, config) + project, err := getProject(d, config) if err != nil { return err - } else if v, ok := d.GetOkExists("service_label"); !isEmptyValue(reflect.ValueOf(serviceLabelProp)) && (ok || !reflect.DeepEqual(v, serviceLabelProp)) { - obj["serviceLabel"] = serviceLabelProp } - regionProp, err := expandComputeForwardingRuleRegion(d.Get("region"), d, config) + region, err := getRegion(d, config) if err != nil { return err - } else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) { - obj["region"] = regionProp } - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/forwardingRules") + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + AllPorts: dcl.Bool(d.Get("all_ports").(bool)), + AllowGlobalAccess: dcl.Bool(d.Get("allow_global_access").(bool)), + BackendService: dcl.String(d.Get("backend_service").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IsMirroringCollector: dcl.Bool(d.Get("is_mirroring_collector").(bool)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + Network: dcl.StringOrNil(d.Get("network").(string)), + NetworkTier: compute.ForwardingRuleNetworkTierEnumRef(d.Get("network_tier").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Ports: expandStringArray(d.Get("ports")), + Project: dcl.String(project), + Location: dcl.String(region), + ServiceLabel: dcl.String(d.Get("service_label").(string)), + Subnetwork: dcl.StringOrNil(d.Get("subnetwork").(string)), + Target: dcl.String(d.Get("target").(string)), + } + + id, err := replaceVarsForId(d, config, "projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") if err != nil { - return err + return fmt.Errorf("Error constructing id: %s", err) } - - log.Printf("[DEBUG] Creating new ForwardingRule: %#v", obj) - billingProject := "" - - project, err := getProject(d, config) + d.SetId(id) + createDirective := CreateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { - return fmt.Errorf("Error fetching project for ForwardingRule: %s", err) + return err } - billingProject = project - + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.ApplyForwardingRule(context.Background(), obj, createDirective...) - res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) - if err != nil { - return fmt.Errorf("Error creating ForwardingRule: %s", err) - } - - // Store the ID now - id, err := replaceVars(d, config, "projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - - err = computeOperationWaitTime( - config, res, project, "Creating ForwardingRule", userAgent, - d.Timeout(schema.TimeoutCreate)) - - if err != nil { + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { // The resource didn't actually create d.SetId("") - return fmt.Errorf("Error waiting to create ForwardingRule: %s", err) + return fmt.Errorf("Error creating ForwardingRule: %s", err) } log.Printf("[DEBUG] Finished creating ForwardingRule %q: %#v", d.Id(), res) @@ -449,235 +294,233 @@ func resourceComputeForwardingRuleCreate(d *schema.ResourceData, meta interface{ func resourceComputeForwardingRuleRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) + project, err := getProject(d, config) if err != nil { return err } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") + region, err := getRegion(d, config) if err != nil { return err } - billingProject := "" + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + AllPorts: dcl.Bool(d.Get("all_ports").(bool)), + AllowGlobalAccess: dcl.Bool(d.Get("allow_global_access").(bool)), + BackendService: dcl.String(d.Get("backend_service").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IsMirroringCollector: dcl.Bool(d.Get("is_mirroring_collector").(bool)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + Network: dcl.StringOrNil(d.Get("network").(string)), + NetworkTier: compute.ForwardingRuleNetworkTierEnumRef(d.Get("network_tier").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Ports: expandStringArray(d.Get("ports")), + Project: dcl.String(project), + Location: dcl.String(region), + ServiceLabel: dcl.String(d.Get("service_label").(string)), + Subnetwork: dcl.StringOrNil(d.Get("subnetwork").(string)), + Target: dcl.String(d.Get("target").(string)), + } - project, err := getProject(d, config) + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { - return fmt.Errorf("Error fetching project for ForwardingRule: %s", err) + return err } - billingProject = project - + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } - - res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil) + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.GetForwardingRule(context.Background(), obj) if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("ComputeForwardingRule %q", d.Id())) + resourceName := fmt.Sprintf("ComputeForwardingRule %q", d.Id()) + return handleNotFoundDCLError(err, d, resourceName) } - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("name", res.Name); err != nil { + return fmt.Errorf("error setting name in state: %s", err) } - - if err := d.Set("creation_timestamp", flattenComputeForwardingRuleCreationTimestamp(res["creationTimestamp"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("all_ports", res.AllPorts); err != nil { + return fmt.Errorf("error setting all_ports in state: %s", err) + } + if err = d.Set("allow_global_access", res.AllowGlobalAccess); err != nil { + return fmt.Errorf("error setting allow_global_access in state: %s", err) + } + if err = d.Set("backend_service", res.BackendService); err != nil { + return fmt.Errorf("error setting backend_service in state: %s", err) } - if err := d.Set("is_mirroring_collector", flattenComputeForwardingRuleIsMirroringCollector(res["isMirroringCollector"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("description", res.Description); err != nil { + return fmt.Errorf("error setting description in state: %s", err) } - if err := d.Set("description", flattenComputeForwardingRuleDescription(res["description"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("ip_address", res.IPAddress); err != nil { + return fmt.Errorf("error setting ip_address in state: %s", err) } - if err := d.Set("ip_address", flattenComputeForwardingRuleIPAddress(res["IPAddress"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("ip_protocol", res.IPProtocol); err != nil { + return fmt.Errorf("error setting ip_protocol in state: %s", err) } - if err := d.Set("ip_protocol", flattenComputeForwardingRuleIPProtocol(res["IPProtocol"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("is_mirroring_collector", res.IsMirroringCollector); err != nil { + return fmt.Errorf("error setting is_mirroring_collector in state: %s", err) } - if err := d.Set("backend_service", flattenComputeForwardingRuleBackendService(res["backendService"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("labels", res.Labels); err != nil { + return fmt.Errorf("error setting labels in state: %s", err) } - if err := d.Set("load_balancing_scheme", flattenComputeForwardingRuleLoadBalancingScheme(res["loadBalancingScheme"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("load_balancing_scheme", res.LoadBalancingScheme); err != nil { + return fmt.Errorf("error setting load_balancing_scheme in state: %s", err) } - if err := d.Set("name", flattenComputeForwardingRuleName(res["name"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("network", res.Network); err != nil { + return fmt.Errorf("error setting network in state: %s", err) } - if err := d.Set("network", flattenComputeForwardingRuleNetwork(res["network"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("network_tier", res.NetworkTier); err != nil { + return fmt.Errorf("error setting network_tier in state: %s", err) } - if err := d.Set("port_range", flattenComputeForwardingRulePortRange(res["portRange"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("port_range", res.PortRange); err != nil { + return fmt.Errorf("error setting port_range in state: %s", err) } - if err := d.Set("ports", flattenComputeForwardingRulePorts(res["ports"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("ports", res.Ports); err != nil { + return fmt.Errorf("error setting ports in state: %s", err) } - if err := d.Set("subnetwork", flattenComputeForwardingRuleSubnetwork(res["subnetwork"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("project", res.Project); err != nil { + return fmt.Errorf("error setting project in state: %s", err) } - if err := d.Set("target", flattenComputeForwardingRuleTarget(res["target"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("region", res.Location); err != nil { + return fmt.Errorf("error setting region in state: %s", err) } - if err := d.Set("allow_global_access", flattenComputeForwardingRuleAllowGlobalAccess(res["allowGlobalAccess"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("service_label", res.ServiceLabel); err != nil { + return fmt.Errorf("error setting service_label in state: %s", err) } - if err := d.Set("all_ports", flattenComputeForwardingRuleAllPorts(res["allPorts"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("subnetwork", res.Subnetwork); err != nil { + return fmt.Errorf("error setting subnetwork in state: %s", err) } - if err := d.Set("network_tier", flattenComputeForwardingRuleNetworkTier(res["networkTier"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("target", res.Target); err != nil { + return fmt.Errorf("error setting target in state: %s", err) } - if err := d.Set("service_label", flattenComputeForwardingRuleServiceLabel(res["serviceLabel"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("creation_timestamp", res.CreationTimestamp); err != nil { + return fmt.Errorf("error setting creation_timestamp in state: %s", err) } - if err := d.Set("service_name", flattenComputeForwardingRuleServiceName(res["serviceName"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("label_fingerprint", res.LabelFingerprint); err != nil { + return fmt.Errorf("error setting label_fingerprint in state: %s", err) } - if err := d.Set("region", flattenComputeForwardingRuleRegion(res["region"], d, config)); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("self_link", res.SelfLink); err != nil { + return fmt.Errorf("error setting self_link in state: %s", err) } - if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { - return fmt.Errorf("Error reading ForwardingRule: %s", err) + if err = d.Set("service_name", res.ServiceName); err != nil { + return fmt.Errorf("error setting service_name in state: %s", err) } return nil } - func resourceComputeForwardingRuleUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + region, err := getRegion(d, config) + if err != nil { + return err + } + + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + AllPorts: dcl.Bool(d.Get("all_ports").(bool)), + AllowGlobalAccess: dcl.Bool(d.Get("allow_global_access").(bool)), + BackendService: dcl.String(d.Get("backend_service").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IsMirroringCollector: dcl.Bool(d.Get("is_mirroring_collector").(bool)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + Network: dcl.StringOrNil(d.Get("network").(string)), + NetworkTier: compute.ForwardingRuleNetworkTierEnumRef(d.Get("network_tier").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Ports: expandStringArray(d.Get("ports")), + Project: dcl.String(project), + Location: dcl.String(region), + ServiceLabel: dcl.String(d.Get("service_label").(string)), + Subnetwork: dcl.StringOrNil(d.Get("subnetwork").(string)), + Target: dcl.String(d.Get("target").(string)), + } + directive := UpdateDirective userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { return err } billingProject := "" + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.ApplyForwardingRule(context.Background(), obj, directive...) - project, err := getProject(d, config) - if err != nil { - return fmt.Errorf("Error fetching project for ForwardingRule: %s", err) - } - billingProject = project - - d.Partial(true) - - if d.HasChange("target") { - obj := make(map[string]interface{}) - - targetProp, err := expandComputeForwardingRuleTarget(d.Get("target"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, targetProp)) { - obj["target"] = targetProp - } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}/setTarget") - if err != nil { - return err - } - - // err == nil indicates that the billing_project value was found - if bp, err := getBillingProject(d, config); err == nil { - billingProject = bp - } - - res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("Error updating ForwardingRule %q: %s", d.Id(), err) - } else { - log.Printf("[DEBUG] Finished updating ForwardingRule %q: %#v", d.Id(), res) - } - - err = computeOperationWaitTime( - config, res, project, "Updating ForwardingRule", userAgent, - d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return err - } - } - if d.HasChange("allow_global_access") { - obj := make(map[string]interface{}) - - allowGlobalAccessProp, err := expandComputeForwardingRuleAllowGlobalAccess(d.Get("allow_global_access"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("allow_global_access"); ok || !reflect.DeepEqual(v, allowGlobalAccessProp) { - obj["allowGlobalAccess"] = allowGlobalAccessProp - } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") - if err != nil { - return err - } - - // err == nil indicates that the billing_project value was found - if bp, err := getBillingProject(d, config); err == nil { - billingProject = bp - } - - res, err := sendRequestWithTimeout(config, "PATCH", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("Error updating ForwardingRule %q: %s", d.Id(), err) - } else { - log.Printf("[DEBUG] Finished updating ForwardingRule %q: %#v", d.Id(), res) - } - - err = computeOperationWaitTime( - config, res, project, "Updating ForwardingRule", userAgent, - d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return err - } - } - - d.Partial(false) + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error updating ForwardingRule: %s", err) + } + + log.Printf("[DEBUG] Finished creating ForwardingRule %q: %#v", d.Id(), res) return resourceComputeForwardingRuleRead(d, meta) } func resourceComputeForwardingRuleDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) + project, err := getProject(d, config) if err != nil { return err } - - billingProject := "" - - project, err := getProject(d, config) + region, err := getRegion(d, config) if err != nil { - return fmt.Errorf("Error fetching project for ForwardingRule: %s", err) + return err } - billingProject = project - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") - if err != nil { - return err + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + AllPorts: dcl.Bool(d.Get("all_ports").(bool)), + AllowGlobalAccess: dcl.Bool(d.Get("allow_global_access").(bool)), + BackendService: dcl.String(d.Get("backend_service").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IsMirroringCollector: dcl.Bool(d.Get("is_mirroring_collector").(bool)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + Network: dcl.StringOrNil(d.Get("network").(string)), + NetworkTier: compute.ForwardingRuleNetworkTierEnumRef(d.Get("network_tier").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Ports: expandStringArray(d.Get("ports")), + Project: dcl.String(project), + Location: dcl.String(region), + ServiceLabel: dcl.String(d.Get("service_label").(string)), + Subnetwork: dcl.StringOrNil(d.Get("subnetwork").(string)), + Target: dcl.String(d.Get("target").(string)), } - var obj map[string]interface{} log.Printf("[DEBUG] Deleting ForwardingRule %q", d.Id()) - + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } - - res, err := sendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return handleNotFoundError(err, d, "ForwardingRule") - } - - err = computeOperationWaitTime( - config, res, project, "Deleting ForwardingRule", userAgent, - d.Timeout(schema.TimeoutDelete)) - - if err != nil { - return err + client := NewDCLComputeClient(config, userAgent, billingProject) + if err := client.DeleteForwardingRule(context.Background(), obj); err != nil { + return fmt.Errorf("Error deleting ForwardingRule: %s", err) } - log.Printf("[DEBUG] Finished deleting ForwardingRule %q: %#v", d.Id(), res) + log.Printf("[DEBUG] Finished deleting ForwardingRule %q", d.Id()) return nil } @@ -693,7 +536,7 @@ func resourceComputeForwardingRuleImport(d *schema.ResourceData, meta interface{ } // Replace import id for the resource id - id, err := replaceVars(d, config, "projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") + id, err := replaceVarsForId(d, config, "projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}") if err != nil { return nil, fmt.Errorf("Error constructing id: %s", err) } @@ -701,232 +544,3 @@ func resourceComputeForwardingRuleImport(d *schema.ResourceData, meta interface{ return []*schema.ResourceData{d}, nil } - -func flattenComputeForwardingRuleCreationTimestamp(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleIsMirroringCollector(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleIPAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleIPProtocol(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleBackendService(v interface{}, d *schema.ResourceData, config *Config) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) -} - -func flattenComputeForwardingRuleLoadBalancingScheme(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleName(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleNetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) -} - -func flattenComputeForwardingRulePortRange(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRulePorts(v interface{}, d *schema.ResourceData, config *Config) interface{} { - if v == nil { - return v - } - return schema.NewSet(schema.HashString, v.([]interface{})) -} - -func flattenComputeForwardingRuleSubnetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) -} - -func flattenComputeForwardingRuleTarget(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleAllowGlobalAccess(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleAllPorts(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleNetworkTier(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleServiceLabel(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleServiceName(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeForwardingRuleRegion(v interface{}, d *schema.ResourceData, config *Config) interface{} { - if v == nil { - return v - } - return NameFromSelfLinkStateFunc(v) -} - -func expandComputeForwardingRuleIsMirroringCollector(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleIPAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleIPProtocol(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleBackendService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - // This method returns a full self link from a partial self link. - if v == nil || v.(string) == "" { - // It does not try to construct anything from empty. - return "", nil - } else if strings.HasPrefix(v.(string), "https://") { - // Anything that starts with a URL scheme is assumed to be a self link worth using. - return v, nil - } else if strings.HasPrefix(v.(string), "projects/") { - // If the self link references a project, we'll just stuck the compute prefix on it - url, err := replaceVars(d, config, "{{ComputeBasePath}}"+v.(string)) - if err != nil { - return "", err - } - return url, nil - } else if strings.HasPrefix(v.(string), "regions/") || strings.HasPrefix(v.(string), "zones/") { - // For regional or zonal resources which include their region or zone, just put the project in front. - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/") - if err != nil { - return nil, err - } - return url + v.(string), nil - } - // Anything else is assumed to be a regional resource, with a partial link that begins with the resource name. - // This isn't very likely - it's a last-ditch effort to extract something useful here. We can do a better job - // as soon as MultiResourceRefs are working since we'll know the types that this field is supposed to point to. - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/") - if err != nil { - return nil, err - } - return url + v.(string), nil -} - -func expandComputeForwardingRuleLoadBalancingScheme(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - f, err := parseGlobalFieldValue("networks", v.(string), "project", d, config, true) - if err != nil { - return nil, fmt.Errorf("Invalid value for network: %s", err) - } - return f.RelativeLink(), nil -} - -func expandComputeForwardingRulePortRange(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRulePorts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v.(*schema.Set).List(), nil -} - -func expandComputeForwardingRuleSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - f, err := parseRegionalFieldValue("subnetworks", v.(string), "project", "region", "zone", d, config, true) - if err != nil { - return nil, fmt.Errorf("Invalid value for subnetwork: %s", err) - } - return f.RelativeLink(), nil -} - -func expandComputeForwardingRuleTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - // This method returns a full self link from a partial self link. - if v == nil || v.(string) == "" { - // It does not try to construct anything from empty. - return "", nil - } else if strings.HasPrefix(v.(string), "https://") { - // Anything that starts with a URL scheme is assumed to be a self link worth using. - return v, nil - } else if strings.HasPrefix(v.(string), "projects/") { - // If the self link references a project, we'll just stuck the compute prefix on it - url, err := replaceVars(d, config, "{{ComputeBasePath}}"+v.(string)) - if err != nil { - return "", err - } - return url, nil - } else if strings.HasPrefix(v.(string), "regions/") || strings.HasPrefix(v.(string), "zones/") { - // For regional or zonal resources which include their region or zone, just put the project in front. - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/") - if err != nil { - return nil, err - } - return url + v.(string), nil - } - // Anything else is assumed to be a regional resource, with a partial link that begins with the resource name. - // This isn't very likely - it's a last-ditch effort to extract something useful here. We can do a better job - // as soon as MultiResourceRefs are working since we'll know the types that this field is supposed to point to. - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/") - if err != nil { - return nil, err - } - return url + v.(string), nil -} - -func expandComputeForwardingRuleAllowGlobalAccess(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleAllPorts(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleNetworkTier(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleServiceLabel(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeForwardingRuleRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) - if err != nil { - return nil, fmt.Errorf("Invalid value for region: %s", err) - } - return f.RelativeLink(), nil -} diff --git a/google/resource_compute_forwarding_rule_generated_test.go b/google/resource_compute_forwarding_rule_generated_test.go index 9f50588257a..5c0f71eceb0 100644 --- a/google/resource_compute_forwarding_rule_generated_test.go +++ b/google/resource_compute_forwarding_rule_generated_test.go @@ -106,7 +106,7 @@ func TestAccComputeForwardingRule_forwardingRuleBasicExample(t *testing.T) { ResourceName: "google_compute_forwarding_rule.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backend_service", "network", "subnetwork", "region"}, + ImportStateVerifyIgnore: []string{"backend_service", "network", "subnetwork", "region", "port_range", "target"}, }, }, }) @@ -145,7 +145,7 @@ func TestAccComputeForwardingRule_forwardingRuleInternallbExample(t *testing.T) ResourceName: "google_compute_forwarding_rule.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backend_service", "network", "subnetwork", "region"}, + ImportStateVerifyIgnore: []string{"backend_service", "network", "subnetwork", "region", "port_range", "target"}, }, }, }) diff --git a/google/resource_compute_forwarding_rule_sweeper_test.go b/google/resource_compute_forwarding_rule_sweeper_test.go index cb3c5a941a2..4e25128bdb1 100644 --- a/google/resource_compute_forwarding_rule_sweeper_test.go +++ b/google/resource_compute_forwarding_rule_sweeper_test.go @@ -1,14 +1,15 @@ // ---------------------------------------------------------------------------- // -// *** AUTO GENERATED CODE *** Type: MMv1 *** +// *** AUTO GENERATED CODE *** Type: DCL *** // // ---------------------------------------------------------------------------- // -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. // -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose // // ---------------------------------------------------------------------------- @@ -17,22 +18,21 @@ package google import ( "context" "log" - "strings" "testing" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) func init() { - resource.AddTestSweepers("ComputeForwardingRule", &resource.Sweeper{ - Name: "ComputeForwardingRule", - F: testSweepComputeForwardingRule, + resource.AddTestSweepers("ComputeForwarding_rule", &resource.Sweeper{ + Name: "ComputeForwarding_rule", + F: testSweepComputeForwarding_rule, }) } -// At the time of writing, the CI only passes us-central1 as the region -func testSweepComputeForwardingRule(region string) error { - resourceName := "ComputeForwardingRule" +func testSweepComputeForwarding_rule(region string) error { + resourceName := "ComputeForwarding_rule" log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) config, err := sharedConfigForRegion(region) @@ -50,75 +50,23 @@ func testSweepComputeForwardingRule(region string) error { t := &testing.T{} billingId := getTestBillingAccountFromEnv(t) - // Setup variables to replace in list template - d := &ResourceDataMock{ - FieldsInSchema: map[string]interface{}{ - "project": config.Project, - "region": region, - "location": region, - "zone": "-", - "billing_account": billingId, - }, + // Setup variables to be used for Delete arguments. + d := map[string]string{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, } - listTemplate := strings.Split("https://compute.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/forwardingRules", "?")[0] - listUrl, err := replaceVars(d, config, listTemplate) + client := NewDCLComputeClient(config, config.userAgent, "") + err = client.DeleteAllForwardingRule(context.Background(), d["project"], d["location"], isDeletableComputeForwarding_rule) if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) - return nil - } - - res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) - return nil - } - - resourceList, ok := res["items"] - if !ok { - log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") - return nil - } - - rl := resourceList.([]interface{}) - - log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) - // Keep count of items that aren't sweepable for logging. - nonPrefixCount := 0 - for _, ri := range rl { - obj := ri.(map[string]interface{}) - if obj["name"] == nil { - log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) - return nil - } - - name := GetResourceNameFromSelfLink(obj["name"].(string)) - // Skip resources that shouldn't be sweeped - if !isSweepableTestResource(name) { - nonPrefixCount++ - continue - } - - deleteTemplate := "https://compute.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}" - deleteUrl, err := replaceVars(d, config, deleteTemplate) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) - return nil - } - deleteUrl = deleteUrl + name - - // Don't wait on operations as we may have a lot to delete - _, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) - } else { - log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) - } - } - - if nonPrefixCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + return err } - return nil } + +func isDeletableComputeForwarding_rule(r *compute.ForwardingRule) bool { + return isSweepableTestResource(*r.Name) +} diff --git a/google/resource_compute_global_forwarding_rule.go b/google/resource_compute_global_forwarding_rule.go index 9ec7061c106..04dbfdff4fd 100644 --- a/google/resource_compute_global_forwarding_rule.go +++ b/google/resource_compute_global_forwarding_rule.go @@ -1,27 +1,31 @@ // ---------------------------------------------------------------------------- // -// *** AUTO GENERATED CODE *** Type: MMv1 *** +// *** AUTO GENERATED CODE *** Type: DCL *** // // ---------------------------------------------------------------------------- // -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. // -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose // // ---------------------------------------------------------------------------- package google import ( + "context" "fmt" "log" - "reflect" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" ) func resourceComputeGlobalForwardingRule() *schema.Resource { @@ -36,484 +40,391 @@ func resourceComputeGlobalForwardingRule() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(4 * time.Minute), - Update: schema.DefaultTimeout(4 * time.Minute), - Delete: schema.DefaultTimeout(4 * time.Minute), + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(10 * time.Minute), }, 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.`, + 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](https://www.ietf.org/rfc/rfc1035.txt). 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.", }, + "target": { Type: schema.TypeString, Required: true, DiffSuppressFunc: compareSelfLinkRelativePaths, - Description: `The URL of the target resource to receive the matched traffic. -The forwarded traffic must be of a type appropriate to the target object. -For INTERNAL_SELF_MANAGED load balancing, only HTTP and HTTPS targets -are valid. + Description: "The URL of the target resource to receive the matched traffic. For regional forwarding rules, this target must live in the same region as the forwarding rule. For global forwarding rules, this target must be a global load balancing resource. The forwarded traffic must be of a type appropriate to the target object. For `INTERNAL_SELF_MANAGED` load balancing, only `targetHttpProxy` is valid, not `targetHttpsProxy`.", + }, -([Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) only) For global address with a purpose of PRIVATE_SERVICE_CONNECT and -addressType of INTERNAL, only "all-apis" and "vpc-sc" are valid.`, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "An optional description of this resource. Provide this property when you create the resource.", }, + "ip_address": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, DiffSuppressFunc: internalIpDiffSuppress, - Description: `The IP address that this forwarding rule serves. When a client sends -traffic to this IP address, the forwarding rule directs the traffic to -the target that you specify in the forwarding rule. The -loadBalancingScheme and the forwarding rule's target determine the -type of IP address that you can use. For detailed information, refer -to [IP address specifications](https://cloud.google.com/load-balancing/docs/forwarding-rule-concepts#ip_address_specifications). - -An address can be specified either by a literal IP address or a -reference to an existing Address resource. If you don't specify a -reserved IP address, an ephemeral IP address is assigned. - -The value must be set to 0.0.0.0 when the target is a targetGrpcProxy -that has validateForProxyless field set to true. - -For Private Service Connect forwarding rules that forward traffic to -Google APIs, IP address must be provided.`, + Description: "IP address that this forwarding rule serves. When a client sends traffic to this IP address, the forwarding rule directs the traffic to the target that you specify in the forwarding rule. If you don't specify a reserved IP address, an ephemeral IP address is assigned. Methods for specifying an IP address: * IPv4 dotted decimal, as in `100.1.2.3` * Full URL, as in `https://www.googleapis.com/compute/v1/projects/project_id/regions/region/addresses/address-name` * Partial URL or by name, as in: * `projects/project_id/regions/region/addresses/address-name` * `regions/region/addresses/address-name` * `global/addresses/address-name` * `address-name` The loadBalancingScheme and the forwarding rule's target determine the type of IP address that you can use. For detailed information, refer to [IP address specifications](/load-balancing/docs/forwarding-rule-concepts#ip_address_specifications).", }, + "ip_protocol": { Type: schema.TypeString, Computed: true, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"TCP", "UDP", "ESP", "AH", "SCTP", "ICMP", ""}, false), DiffSuppressFunc: caseDiffSuppress, - Description: `The IP protocol to which this rule applies. When the load balancing scheme is -INTERNAL_SELF_MANAGED, only TCP is valid. This field must not be set if the -global address is configured as a purpose of PRIVATE_SERVICE_CONNECT -and addressType of INTERNAL Possible values: ["TCP", "UDP", "ESP", "AH", "SCTP", "ICMP"]`, - }, - "description": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: `An optional description of this resource. Provide this property when -you create the resource.`, + Description: "The IP protocol to which this rule applies. For protocol forwarding, valid options are `TCP`, `UDP`, `ESP`, `AH`, `SCTP` or `ICMP`. For Internal TCP/UDP Load Balancing, the load balancing scheme is `INTERNAL`, and one of `TCP` or `UDP` are valid. For Traffic Director, the load balancing scheme is `INTERNAL_SELF_MANAGED`, and only `TCP`is valid. For Internal HTTP(S) Load Balancing, the load balancing scheme is `INTERNAL_MANAGED`, and only `TCP` is valid. For HTTP(S), SSL Proxy, and TCP Proxy Load Balancing, the load balancing scheme is `EXTERNAL` and only `TCP` is valid. For Network TCP/UDP Load Balancing, the load balancing scheme is `EXTERNAL`, and one of `TCP` or `UDP` is valid.", + ValidateFunc: validation.StringInSlice([]string{"TCP", "UDP", "ESP", "AH", "SCTP", "ICMP", "L3_DEFAULT", ""}, false), }, + "ip_version": { Type: schema.TypeString, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV6", ""}, false), - Description: `The IP Version that will be used by this global forwarding rule. Possible values: ["IPV4", "IPV6"]`, + Description: "The IP Version that will be used by this forwarding rule. Valid options are `IPV4` or `IPV6`. This can only be specified for an external global forwarding rule. Possible values: UNSPECIFIED_VERSION, IPV4, IPV6", + ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED_VERSION", "IPV4", "IPV6", ""}, false), }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: "Labels to apply to this rule.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "load_balancing_scheme": { Type: schema.TypeString, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"EXTERNAL", "INTERNAL_SELF_MANAGED", ""}, false), - Description: `This signifies what the GlobalForwardingRule will be used for. -The value of INTERNAL_SELF_MANAGED means that this will be used for -Internal Global HTTP(S) LB. The value of EXTERNAL means that this -will be used for External Global Load Balancing (HTTP(S) LB, -External TCP/UDP LB, SSL Proxy) - -([Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) only) Note: This field must be set "" if the global address is -configured as a purpose of PRIVATE_SERVICE_CONNECT and addressType of INTERNAL. Default value: "EXTERNAL" Possible values: ["EXTERNAL", "INTERNAL_SELF_MANAGED"]`, - Default: "EXTERNAL", + Description: "Specifies the forwarding rule type.\n\n* `EXTERNAL` is used for:\n * Classic Cloud VPN gateways\n * Protocol forwarding to VMs from an external IP address\n * The following load balancers: HTTP(S), SSL Proxy, TCP Proxy, and Network TCP/UDP\n* `INTERNAL` is used for:\n * Protocol forwarding to VMs from an internal IP address\n * Internal TCP/UDP load balancers\n* `INTERNAL_MANAGED` is used for:\n * Internal HTTP(S) load balancers\n* `INTERNAL_SELF_MANAGED` is used for:\n * Traffic Director\n\nFor more information about forwarding rules, refer to [Forwarding rule concepts](/load-balancing/docs/forwarding-rule-concepts). Possible values: INVALID, INTERNAL, INTERNAL_MANAGED, INTERNAL_SELF_MANAGED, EXTERNAL", + Default: "EXTERNAL", + ValidateFunc: validation.StringInSlice([]string{"INVALID", "INTERNAL", "INTERNAL_MANAGED", "INTERNAL_SELF_MANAGED", "EXTERNAL", ""}, false), }, + "metadata_filters": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Description: `Opaque filter criteria used by Loadbalancer to restrict routing -configuration to a limited set xDS compliant clients. In their xDS -requests to Loadbalancer, xDS clients present node metadata. If a -match takes place, the relevant routing configuration is made available -to those proxies. - -For each metadataFilter in this list, if its filterMatchCriteria is set -to MATCH_ANY, at least one of the filterLabels must match the -corresponding label provided in the metadata. If its filterMatchCriteria -is set to MATCH_ALL, then all of its filterLabels must match with -corresponding labels in the provided metadata. - -metadataFilters specified here can be overridden by those specified in -the UrlMap that this ForwardingRule references. - -metadataFilters only applies to Loadbalancers that have their -loadBalancingScheme set to INTERNAL_SELF_MANAGED.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "filter_labels": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - Description: `The list of label value pairs that must match labels in the -provided metadata based on filterMatchCriteria - -This list must not be empty and can have at the most 64 entries.`, - MinItems: 1, - MaxItems: 64, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: `Name of the metadata label. The length must be between -1 and 1024 characters, inclusive.`, - }, - "value": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: `The value that the label must match. The value has a maximum -length of 1024 characters.`, - }, - }, - }, - }, - "filter_match_criteria": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"MATCH_ANY", "MATCH_ALL"}, false), - Description: `Specifies how individual filterLabel matches within the list of -filterLabels contribute towards the overall metadataFilter match. - -MATCH_ANY - At least one of the filterLabels must have a matching -label in the provided metadata. -MATCH_ALL - All filterLabels must have matching labels in the -provided metadata. Possible values: ["MATCH_ANY", "MATCH_ALL"]`, - }, - }, - }, + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "Opaque filter criteria used by Loadbalancer to restrict routing configuration to a limited set of [xDS](https://github.com/envoyproxy/data-plane-api/blob/master/XDS_PROTOCOL.md) compliant clients. In their xDS requests to Loadbalancer, xDS clients present [node metadata](https://github.com/envoyproxy/data-plane-api/search?q=%22message+Node%22+in%3A%2Fenvoy%2Fapi%2Fv2%2Fcore%2Fbase.proto&). If a match takes place, the relevant configuration is made available to those proxies. Otherwise, all the resources (e.g. `TargetHttpProxy`, `UrlMap`) referenced by the `ForwardingRule` will not be visible to those proxies.\n\nFor each `metadataFilter` in this list, if its `filterMatchCriteria` is set to MATCH_ANY, at least one of the `filterLabel`s must match the corresponding label provided in the metadata. If its `filterMatchCriteria` is set to MATCH_ALL, then all of its `filterLabel`s must match with corresponding labels provided in the metadata.\n\n`metadataFilters` specified here will be applifed before those specified in the `UrlMap` that this `ForwardingRule` references.\n\n`metadataFilters` only applies to Loadbalancers that have their loadBalancingScheme set to `INTERNAL_SELF_MANAGED`.", + Elem: ComputeGlobalForwardingRuleMetadataFilterSchema(), + }, + + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "This field is not used for external load balancing. For `INTERNAL` and `INTERNAL_SELF_MANAGED` load balancing, this field identifies the network that the load balanced IP should belong to for this Forwarding Rule. If this field is not specified, the default network will be used.", }, + "port_range": { Type: schema.TypeString, Optional: true, ForceNew: true, DiffSuppressFunc: portRangeDiffSuppress, - Description: `This field is used along with the target field for TargetHttpProxy, -TargetHttpsProxy, TargetSslProxy, TargetTcpProxy, TargetVpnGateway, -TargetPool, TargetInstance. - -Applicable only when IPProtocol is TCP, UDP, or SCTP, only packets -addressed to ports in the specified range will be forwarded to target. -Forwarding rules with the same [IPAddress, IPProtocol] pair must have -disjoint port ranges. - -Some types of forwarding target have constraints on the acceptable -ports: - -* TargetHttpProxy: 80, 8080 -* TargetHttpsProxy: 443 -* TargetTcpProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, - 1883, 5222 -* TargetSslProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, - 1883, 5222 -* TargetVpnGateway: 500, 4500`, + Description: "When the load balancing scheme is `EXTERNAL`, `INTERNAL_SELF_MANAGED` and `INTERNAL_MANAGED`, you can specify a `port_range`. Use with a forwarding rule that points to a target proxy or a target pool. Do not use with a forwarding rule that points to a backend service. This field is used along with the `target` field for TargetHttpProxy, TargetHttpsProxy, TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, TargetInstance. Applicable only when `IPProtocol` is `TCP`, `UDP`, or `SCTP`, only packets addressed to ports in the specified range will be forwarded to `target`. Forwarding rules with the same `[IPAddress, IPProtocol]` pair must have disjoint port ranges. Some types of forwarding target have constraints on the acceptable ports:\n\n* TargetHttpProxy: 80, 8080\n* TargetHttpsProxy: 443\n* TargetTcpProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, 1688, 1883, 5222\n* TargetSslProxy: 25, 43, 110, 143, 195, 443, 465, 587, 700, 993, 995, 1688, 1883, 5222\n* TargetVpnGateway: 500, 4500\n\n@pattern: d+(?:-d+)?", }, + "project": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The project this resource belongs in.", + }, + + "label_fingerprint": { + Type: schema.TypeString, + Computed: true, + Description: "Used internally during label updates.", }, + "self_link": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Description: "[Output Only] Server-defined URL for the resource.", }, }, - UseJSONNumber: true, } } -func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) - if err != nil { - return err - } +func ComputeGlobalForwardingRuleMetadataFilterSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filter_labels": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: "The list of label value pairs that must match labels in the provided metadata based on `filterMatchCriteria`\n\nThis list must not be empty and can have at the most 64 entries.", + MaxItems: 64, + MinItems: 1, + Elem: ComputeGlobalForwardingRuleMetadataFilterFilterLabelSchema(), + }, - obj := make(map[string]interface{}) - descriptionProp, err := expandComputeGlobalForwardingRuleDescription(d.Get("description"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { - obj["description"] = descriptionProp - } - IPAddressProp, err := expandComputeGlobalForwardingRuleIPAddress(d.Get("ip_address"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ip_address"); !isEmptyValue(reflect.ValueOf(IPAddressProp)) && (ok || !reflect.DeepEqual(v, IPAddressProp)) { - obj["IPAddress"] = IPAddressProp - } - IPProtocolProp, err := expandComputeGlobalForwardingRuleIPProtocol(d.Get("ip_protocol"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ip_protocol"); !isEmptyValue(reflect.ValueOf(IPProtocolProp)) && (ok || !reflect.DeepEqual(v, IPProtocolProp)) { - obj["IPProtocol"] = IPProtocolProp - } - ipVersionProp, err := expandComputeGlobalForwardingRuleIpVersion(d.Get("ip_version"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("ip_version"); !isEmptyValue(reflect.ValueOf(ipVersionProp)) && (ok || !reflect.DeepEqual(v, ipVersionProp)) { - obj["ipVersion"] = ipVersionProp - } - loadBalancingSchemeProp, err := expandComputeGlobalForwardingRuleLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("load_balancing_scheme"); !isEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) { - obj["loadBalancingScheme"] = loadBalancingSchemeProp - } - metadataFiltersProp, err := expandComputeGlobalForwardingRuleMetadataFilters(d.Get("metadata_filters"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("metadata_filters"); !isEmptyValue(reflect.ValueOf(metadataFiltersProp)) && (ok || !reflect.DeepEqual(v, metadataFiltersProp)) { - obj["metadataFilters"] = metadataFiltersProp + "filter_match_criteria": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Specifies how individual `filterLabel` matches within the list of `filterLabel`s contribute towards the overall `metadataFilter` match.\n\nSupported values are:\n\n* MATCH_ANY: At least one of the `filterLabels` must have a matching label in the provided metadata.\n* MATCH_ALL: All `filterLabels` must have matching labels in the provided metadata. Possible values: NOT_SET, MATCH_ALL, MATCH_ANY", + ValidateFunc: validation.StringInSlice([]string{"NOT_SET", "MATCH_ALL", "MATCH_ANY", ""}, false), + }, + }, } - nameProp, err := expandComputeGlobalForwardingRuleName(d.Get("name"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { - obj["name"] = nameProp +} + +func ComputeGlobalForwardingRuleMetadataFilterFilterLabelSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Name of metadata label.\n\nThe name can have a maximum length of 1024 characters and must be at least 1 character long.", + }, + + "value": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The value of the label must match the specified value.\n\nvalue can have a maximum length of 1024 characters.", + }, + }, } - portRangeProp, err := expandComputeGlobalForwardingRulePortRange(d.Get("port_range"), d, config) +} + +func resourceComputeGlobalForwardingRuleCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) if err != nil { return err - } else if v, ok := d.GetOkExists("port_range"); !isEmptyValue(reflect.ValueOf(portRangeProp)) && (ok || !reflect.DeepEqual(v, portRangeProp)) { - obj["portRange"] = portRangeProp } - targetProp, err := expandComputeGlobalForwardingRuleTarget(d.Get("target"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(targetProp)) && (ok || !reflect.DeepEqual(v, targetProp)) { - obj["target"] = targetProp + + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + Target: dcl.String(d.Get("target").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IPVersion: compute.ForwardingRuleIPVersionEnumRef(d.Get("ip_version").(string)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + MetadataFilter: expandComputeGlobalForwardingRuleMetadataFilterArray(d.Get("metadata_filters")), + Network: dcl.StringOrNil(d.Get("network").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Project: dcl.String(project), } - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/forwardingRules") + id, err := replaceVarsForId(d, config, "projects/{{project}}/global/forwardingRules/{{name}}") if err != nil { - return err + return fmt.Errorf("Error constructing id: %s", err) } - - log.Printf("[DEBUG] Creating new GlobalForwardingRule: %#v", obj) - billingProject := "" - - project, err := getProject(d, config) + d.SetId(id) + createDirective := CreateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { - return fmt.Errorf("Error fetching project for GlobalForwardingRule: %s", err) + return err } - billingProject = project - + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.ApplyForwardingRule(context.Background(), obj, createDirective...) - res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutCreate)) - if err != nil { - return fmt.Errorf("Error creating GlobalForwardingRule: %s", err) - } - - // Store the ID now - id, err := replaceVars(d, config, "projects/{{project}}/global/forwardingRules/{{name}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - - err = computeOperationWaitTime( - config, res, project, "Creating GlobalForwardingRule", userAgent, - d.Timeout(schema.TimeoutCreate)) - - if err != nil { + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { // The resource didn't actually create d.SetId("") - return fmt.Errorf("Error waiting to create GlobalForwardingRule: %s", err) + return fmt.Errorf("Error creating ForwardingRule: %s", err) } - log.Printf("[DEBUG] Finished creating GlobalForwardingRule %q: %#v", d.Id(), res) + log.Printf("[DEBUG] Finished creating ForwardingRule %q: %#v", d.Id(), res) return resourceComputeGlobalForwardingRuleRead(d, meta) } func resourceComputeGlobalForwardingRuleRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) + project, err := getProject(d, config) if err != nil { return err } - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/forwardingRules/{{name}}") - if err != nil { - return err + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + Target: dcl.String(d.Get("target").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IPVersion: compute.ForwardingRuleIPVersionEnumRef(d.Get("ip_version").(string)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + MetadataFilter: expandComputeGlobalForwardingRuleMetadataFilterArray(d.Get("metadata_filters")), + Network: dcl.StringOrNil(d.Get("network").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Project: dcl.String(project), } - billingProject := "" - - project, err := getProject(d, config) + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { - return fmt.Errorf("Error fetching project for GlobalForwardingRule: %s", err) + return err } - billingProject = project - + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } - - res, err := sendRequest(config, "GET", billingProject, url, userAgent, nil) + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.GetForwardingRule(context.Background(), obj) if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("ComputeGlobalForwardingRule %q", d.Id())) + resourceName := fmt.Sprintf("ComputeGlobalForwardingRule %q", d.Id()) + return handleNotFoundDCLError(err, d, resourceName) } - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("name", res.Name); err != nil { + return fmt.Errorf("error setting name in state: %s", err) } - - if err := d.Set("description", flattenComputeGlobalForwardingRuleDescription(res["description"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("target", res.Target); err != nil { + return fmt.Errorf("error setting target in state: %s", err) + } + if err = d.Set("description", res.Description); err != nil { + return fmt.Errorf("error setting description in state: %s", err) + } + if err = d.Set("ip_address", res.IPAddress); err != nil { + return fmt.Errorf("error setting ip_address in state: %s", err) + } + if err = d.Set("ip_protocol", res.IPProtocol); err != nil { + return fmt.Errorf("error setting ip_protocol in state: %s", err) } - if err := d.Set("ip_address", flattenComputeGlobalForwardingRuleIPAddress(res["IPAddress"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("ip_version", res.IPVersion); err != nil { + return fmt.Errorf("error setting ip_version in state: %s", err) } - if err := d.Set("ip_protocol", flattenComputeGlobalForwardingRuleIPProtocol(res["IPProtocol"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("labels", res.Labels); err != nil { + return fmt.Errorf("error setting labels in state: %s", err) } - if err := d.Set("ip_version", flattenComputeGlobalForwardingRuleIpVersion(res["ipVersion"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("load_balancing_scheme", res.LoadBalancingScheme); err != nil { + return fmt.Errorf("error setting load_balancing_scheme in state: %s", err) } - if err := d.Set("load_balancing_scheme", flattenComputeGlobalForwardingRuleLoadBalancingScheme(res["loadBalancingScheme"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("metadata_filters", flattenComputeGlobalForwardingRuleMetadataFilterArray(res.MetadataFilter)); err != nil { + return fmt.Errorf("error setting metadata_filters in state: %s", err) } - if err := d.Set("metadata_filters", flattenComputeGlobalForwardingRuleMetadataFilters(res["metadataFilters"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("network", res.Network); err != nil { + return fmt.Errorf("error setting network in state: %s", err) } - if err := d.Set("name", flattenComputeGlobalForwardingRuleName(res["name"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("port_range", res.PortRange); err != nil { + return fmt.Errorf("error setting port_range in state: %s", err) } - if err := d.Set("port_range", flattenComputeGlobalForwardingRulePortRange(res["portRange"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("project", res.Project); err != nil { + return fmt.Errorf("error setting project in state: %s", err) } - if err := d.Set("target", flattenComputeGlobalForwardingRuleTarget(res["target"], d, config)); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("label_fingerprint", res.LabelFingerprint); err != nil { + return fmt.Errorf("error setting label_fingerprint in state: %s", err) } - if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { - return fmt.Errorf("Error reading GlobalForwardingRule: %s", err) + if err = d.Set("self_link", res.SelfLink); err != nil { + return fmt.Errorf("error setting self_link in state: %s", err) } return nil } - func resourceComputeGlobalForwardingRuleUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) + project, err := getProject(d, config) if err != nil { return err } - billingProject := "" - - project, err := getProject(d, config) + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + Target: dcl.String(d.Get("target").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IPVersion: compute.ForwardingRuleIPVersionEnumRef(d.Get("ip_version").(string)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + MetadataFilter: expandComputeGlobalForwardingRuleMetadataFilterArray(d.Get("metadata_filters")), + Network: dcl.StringOrNil(d.Get("network").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Project: dcl.String(project), + } + directive := UpdateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { - return fmt.Errorf("Error fetching project for GlobalForwardingRule: %s", err) + return err } - billingProject = project - - d.Partial(true) - - if d.HasChange("target") { - obj := make(map[string]interface{}) - - targetProp, err := expandComputeGlobalForwardingRuleTarget(d.Get("target"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("target"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, targetProp)) { - obj["target"] = targetProp - } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/forwardingRules/{{name}}/setTarget") - if err != nil { - return err - } - // err == nil indicates that the billing_project value was found - if bp, err := getBillingProject(d, config); err == nil { - billingProject = bp - } - - res, err := sendRequestWithTimeout(config, "POST", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("Error updating GlobalForwardingRule %q: %s", d.Id(), err) - } else { - log.Printf("[DEBUG] Finished updating GlobalForwardingRule %q: %#v", d.Id(), res) - } + billingProject := "" + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLComputeClient(config, userAgent, billingProject) + res, err := client.ApplyForwardingRule(context.Background(), obj, directive...) - err = computeOperationWaitTime( - config, res, project, "Updating GlobalForwardingRule", userAgent, - d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return err - } + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error updating ForwardingRule: %s", err) } - d.Partial(false) + log.Printf("[DEBUG] Finished creating ForwardingRule %q: %#v", d.Id(), res) return resourceComputeGlobalForwardingRuleRead(d, meta) } func resourceComputeGlobalForwardingRuleDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - userAgent, err := generateUserAgentString(d, config.userAgent) + project, err := getProject(d, config) if err != nil { return err } - billingProject := "" - - project, err := getProject(d, config) - if err != nil { - return fmt.Errorf("Error fetching project for GlobalForwardingRule: %s", err) + obj := &compute.ForwardingRule{ + Name: dcl.String(d.Get("name").(string)), + Target: dcl.String(d.Get("target").(string)), + Description: dcl.String(d.Get("description").(string)), + IPAddress: dcl.StringOrNil(d.Get("ip_address").(string)), + IPProtocol: compute.ForwardingRuleIPProtocolEnumRef(d.Get("ip_protocol").(string)), + IPVersion: compute.ForwardingRuleIPVersionEnumRef(d.Get("ip_version").(string)), + Labels: checkStringMap(d.Get("labels")), + LoadBalancingScheme: compute.ForwardingRuleLoadBalancingSchemeEnumRef(d.Get("load_balancing_scheme").(string)), + MetadataFilter: expandComputeGlobalForwardingRuleMetadataFilterArray(d.Get("metadata_filters")), + Network: dcl.StringOrNil(d.Get("network").(string)), + PortRange: dcl.String(d.Get("port_range").(string)), + Project: dcl.String(project), } - billingProject = project - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/forwardingRules/{{name}}") + log.Printf("[DEBUG] Deleting ForwardingRule %q", d.Id()) + userAgent, err := generateUserAgentString(d, config.userAgent) if err != nil { return err } - - var obj map[string]interface{} - log.Printf("[DEBUG] Deleting GlobalForwardingRule %q", d.Id()) - + billingProject := project // err == nil indicates that the billing_project value was found if bp, err := getBillingProject(d, config); err == nil { billingProject = bp } - - res, err := sendRequestWithTimeout(config, "DELETE", billingProject, url, userAgent, obj, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return handleNotFoundError(err, d, "GlobalForwardingRule") - } - - err = computeOperationWaitTime( - config, res, project, "Deleting GlobalForwardingRule", userAgent, - d.Timeout(schema.TimeoutDelete)) - - if err != nil { - return err + client := NewDCLComputeClient(config, userAgent, billingProject) + if err := client.DeleteForwardingRule(context.Background(), obj); err != nil { + return fmt.Errorf("Error deleting ForwardingRule: %s", err) } - log.Printf("[DEBUG] Finished deleting GlobalForwardingRule %q: %#v", d.Id(), res) + log.Printf("[DEBUG] Finished deleting ForwardingRule %q", d.Id()) return nil } @@ -528,7 +439,7 @@ func resourceComputeGlobalForwardingRuleImport(d *schema.ResourceData, meta inte } // Replace import id for the resource id - id, err := replaceVars(d, config, "projects/{{project}}/global/forwardingRules/{{name}}") + id, err := replaceVarsForId(d, config, "projects/{{project}}/global/forwardingRules/{{name}}") if err != nil { return nil, fmt.Errorf("Error constructing id: %s", err) } @@ -537,186 +448,117 @@ func resourceComputeGlobalForwardingRuleImport(d *schema.ResourceData, meta inte return []*schema.ResourceData{d}, nil } -func flattenComputeGlobalForwardingRuleDescription(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} - -func flattenComputeGlobalForwardingRuleIPAddress(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} +func expandComputeGlobalForwardingRuleMetadataFilterArray(o interface{}) []compute.ForwardingRuleMetadataFilter { + if o == nil { + return nil + } -func flattenComputeGlobalForwardingRuleIPProtocol(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} + objs := o.([]interface{}) + if len(objs) == 0 { + return nil + } -func flattenComputeGlobalForwardingRuleIpVersion(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} + items := make([]compute.ForwardingRuleMetadataFilter, 0, len(objs)) + for _, item := range objs { + i := expandComputeGlobalForwardingRuleMetadataFilter(item) + items = append(items, *i) + } -func flattenComputeGlobalForwardingRuleLoadBalancingScheme(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v + return items } -func flattenComputeGlobalForwardingRuleMetadataFilters(v interface{}, d *schema.ResourceData, config *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{}{ - "filter_match_criteria": flattenComputeGlobalForwardingRuleMetadataFiltersFilterMatchCriteria(original["filterMatchCriteria"], d, config), - "filter_labels": flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabels(original["filterLabels"], d, config), - }) +func expandComputeGlobalForwardingRuleMetadataFilter(o interface{}) *compute.ForwardingRuleMetadataFilter { + if o == nil { + return compute.EmptyForwardingRuleMetadataFilter } - return transformed -} -func flattenComputeGlobalForwardingRuleMetadataFiltersFilterMatchCriteria(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} -func flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabels(v interface{}, d *schema.ResourceData, config *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{}{ - "name": flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabelsName(original["name"], d, config), - "value": flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabelsValue(original["value"], d, config), - }) + obj := o.(map[string]interface{}) + return &compute.ForwardingRuleMetadataFilter{ + FilterLabel: expandComputeGlobalForwardingRuleMetadataFilterFilterLabelArray(obj["filter_labels"]), + FilterMatchCriteria: compute.ForwardingRuleMetadataFilterFilterMatchCriteriaEnumRef(obj["filter_match_criteria"].(string)), } - return transformed -} -func flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabelsName(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v } -func flattenComputeGlobalForwardingRuleMetadataFiltersFilterLabelsValue(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} +func flattenComputeGlobalForwardingRuleMetadataFilterArray(objs []compute.ForwardingRuleMetadataFilter) []interface{} { + if objs == nil { + return nil + } -func flattenComputeGlobalForwardingRuleName(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} + items := []interface{}{} + for _, item := range objs { + i := flattenComputeGlobalForwardingRuleMetadataFilter(&item) + items = append(items, i) + } -func flattenComputeGlobalForwardingRulePortRange(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v + return items } -func flattenComputeGlobalForwardingRuleTarget(v interface{}, d *schema.ResourceData, config *Config) interface{} { - return v -} +func flattenComputeGlobalForwardingRuleMetadataFilter(obj *compute.ForwardingRuleMetadataFilter) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "filter_labels": flattenComputeGlobalForwardingRuleMetadataFilterFilterLabelArray(obj.FilterLabel), + "filter_match_criteria": obj.FilterMatchCriteria, + } -func expandComputeGlobalForwardingRuleDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + return transformed -func expandComputeGlobalForwardingRuleIPAddress(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil } +func expandComputeGlobalForwardingRuleMetadataFilterFilterLabelArray(o interface{}) []compute.ForwardingRuleMetadataFilterFilterLabel { + if o == nil { + return nil + } -func expandComputeGlobalForwardingRuleIPProtocol(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + objs := o.([]interface{}) + if len(objs) == 0 { + return nil + } -func expandComputeGlobalForwardingRuleIpVersion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + items := make([]compute.ForwardingRuleMetadataFilterFilterLabel, 0, len(objs)) + for _, item := range objs { + i := expandComputeGlobalForwardingRuleMetadataFilterFilterLabel(item) + items = append(items, *i) + } -func expandComputeGlobalForwardingRuleLoadBalancingScheme(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil + return items } -func expandComputeGlobalForwardingRuleMetadataFilters(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedFilterMatchCriteria, err := expandComputeGlobalForwardingRuleMetadataFiltersFilterMatchCriteria(original["filter_match_criteria"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedFilterMatchCriteria); val.IsValid() && !isEmptyValue(val) { - transformed["filterMatchCriteria"] = transformedFilterMatchCriteria - } - - transformedFilterLabels, err := expandComputeGlobalForwardingRuleMetadataFiltersFilterLabels(original["filter_labels"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedFilterLabels); val.IsValid() && !isEmptyValue(val) { - transformed["filterLabels"] = transformedFilterLabels - } - - req = append(req, transformed) - } - return req, nil -} +func expandComputeGlobalForwardingRuleMetadataFilterFilterLabel(o interface{}) *compute.ForwardingRuleMetadataFilterFilterLabel { + if o == nil { + return compute.EmptyForwardingRuleMetadataFilterFilterLabel + } -func expandComputeGlobalForwardingRuleMetadataFiltersFilterMatchCriteria(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil + obj := o.(map[string]interface{}) + return &compute.ForwardingRuleMetadataFilterFilterLabel{ + Name: dcl.String(obj["name"].(string)), + Value: dcl.String(obj["value"].(string)), + } } -func expandComputeGlobalForwardingRuleMetadataFiltersFilterLabels(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedName, err := expandComputeGlobalForwardingRuleMetadataFiltersFilterLabelsName(original["name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { - transformed["name"] = transformedName - } - - transformedValue, err := expandComputeGlobalForwardingRuleMetadataFiltersFilterLabelsValue(original["value"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedValue); val.IsValid() && !isEmptyValue(val) { - transformed["value"] = transformedValue - } - - req = append(req, transformed) - } - return req, nil -} +func flattenComputeGlobalForwardingRuleMetadataFilterFilterLabelArray(objs []compute.ForwardingRuleMetadataFilterFilterLabel) []interface{} { + if objs == nil { + return nil + } -func expandComputeGlobalForwardingRuleMetadataFiltersFilterLabelsName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + items := []interface{}{} + for _, item := range objs { + i := flattenComputeGlobalForwardingRuleMetadataFilterFilterLabel(&item) + items = append(items, i) + } -func expandComputeGlobalForwardingRuleMetadataFiltersFilterLabelsValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil + return items } -func expandComputeGlobalForwardingRuleName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} +func flattenComputeGlobalForwardingRuleMetadataFilterFilterLabel(obj *compute.ForwardingRuleMetadataFilterFilterLabel) interface{} { + if obj == nil || obj.Empty() { + return nil + } + transformed := map[string]interface{}{ + "name": obj.Name, + "value": obj.Value, + } -func expandComputeGlobalForwardingRulePortRange(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} + return transformed -func expandComputeGlobalForwardingRuleTarget(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil } diff --git a/google/resource_compute_global_forwarding_rule_generated_test.go b/google/resource_compute_global_forwarding_rule_generated_test.go index 432c6a5ccca..7e708dddee9 100644 --- a/google/resource_compute_global_forwarding_rule_generated_test.go +++ b/google/resource_compute_global_forwarding_rule_generated_test.go @@ -39,9 +39,10 @@ func TestAccComputeGlobalForwardingRule_globalForwardingRuleHttpExample(t *testi Config: testAccComputeGlobalForwardingRule_globalForwardingRuleHttpExample(context), }, { - ResourceName: "google_compute_global_forwarding_rule.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_global_forwarding_rule.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"port_range", "target"}, }, }, }) diff --git a/google/resource_compute_global_forwarding_rule_sweeper_test.go b/google/resource_compute_global_forwarding_rule_sweeper_test.go index 0f98286a741..a20eb684ab4 100644 --- a/google/resource_compute_global_forwarding_rule_sweeper_test.go +++ b/google/resource_compute_global_forwarding_rule_sweeper_test.go @@ -1,14 +1,15 @@ // ---------------------------------------------------------------------------- // -// *** AUTO GENERATED CODE *** Type: MMv1 *** +// *** AUTO GENERATED CODE *** Type: DCL *** // // ---------------------------------------------------------------------------- // -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. // -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose // // ---------------------------------------------------------------------------- @@ -17,22 +18,21 @@ package google import ( "context" "log" - "strings" "testing" + compute "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/compute" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) func init() { - resource.AddTestSweepers("ComputeGlobalForwardingRule", &resource.Sweeper{ - Name: "ComputeGlobalForwardingRule", - F: testSweepComputeGlobalForwardingRule, + resource.AddTestSweepers("ComputeGlobal_forwarding_rule", &resource.Sweeper{ + Name: "ComputeGlobal_forwarding_rule", + F: testSweepComputeGlobal_forwarding_rule, }) } -// At the time of writing, the CI only passes us-central1 as the region -func testSweepComputeGlobalForwardingRule(region string) error { - resourceName := "ComputeGlobalForwardingRule" +func testSweepComputeGlobal_forwarding_rule(region string) error { + resourceName := "ComputeGlobal_forwarding_rule" log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) config, err := sharedConfigForRegion(region) @@ -50,75 +50,23 @@ func testSweepComputeGlobalForwardingRule(region string) error { t := &testing.T{} billingId := getTestBillingAccountFromEnv(t) - // Setup variables to replace in list template - d := &ResourceDataMock{ - FieldsInSchema: map[string]interface{}{ - "project": config.Project, - "region": region, - "location": region, - "zone": "-", - "billing_account": billingId, - }, + // Setup variables to be used for Delete arguments. + d := map[string]string{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, } - listTemplate := strings.Split("https://compute.googleapis.com/compute/v1/projects/{{project}}/global/forwardingRules", "?")[0] - listUrl, err := replaceVars(d, config, listTemplate) + client := NewDCLComputeClient(config, config.userAgent, "") + err = client.DeleteAllForwardingRule(context.Background(), d["project"], d["location"], isDeletableComputeGlobal_forwarding_rule) if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) - return nil - } - - res, err := sendRequest(config, "GET", config.Project, listUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) - return nil - } - - resourceList, ok := res["items"] - if !ok { - log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") - return nil - } - - rl := resourceList.([]interface{}) - - log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) - // Keep count of items that aren't sweepable for logging. - nonPrefixCount := 0 - for _, ri := range rl { - obj := ri.(map[string]interface{}) - if obj["name"] == nil { - log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) - return nil - } - - name := GetResourceNameFromSelfLink(obj["name"].(string)) - // Skip resources that shouldn't be sweeped - if !isSweepableTestResource(name) { - nonPrefixCount++ - continue - } - - deleteTemplate := "https://compute.googleapis.com/compute/v1/projects/{{project}}/global/forwardingRules/{{name}}" - deleteUrl, err := replaceVars(d, config, deleteTemplate) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) - return nil - } - deleteUrl = deleteUrl + name - - // Don't wait on operations as we may have a lot to delete - _, err = sendRequest(config, "DELETE", config.Project, deleteUrl, config.userAgent, nil) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) - } else { - log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) - } - } - - if nonPrefixCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + return err } - return nil } + +func isDeletableComputeGlobal_forwarding_rule(r *compute.ForwardingRule) bool { + return isSweepableTestResource(*r.Name) +} diff --git a/google/resource_compute_global_forwarding_rule_test.go b/google/resource_compute_global_forwarding_rule_test.go index 643637e262c..f71a9e56dd5 100644 --- a/google/resource_compute_global_forwarding_rule_test.go +++ b/google/resource_compute_global_forwarding_rule_test.go @@ -31,9 +31,10 @@ func TestAccComputeGlobalForwardingRule_updateTarget(t *testing.T) { ), }, { - ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"port_range", "target"}, }, { Config: testAccComputeGlobalForwardingRule_httpProxy(fr, "proxy2", proxy, proxyUpdated, backend, hc, urlmap), @@ -43,9 +44,10 @@ func TestAccComputeGlobalForwardingRule_updateTarget(t *testing.T) { ), }, { - ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"port_range", "target"}, }, }, }) @@ -73,9 +75,10 @@ func TestAccComputeGlobalForwardingRule_ipv6(t *testing.T) { ), }, { - ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"port_range", "target"}, }, }, })