Closed cytopia closed 3 years ago
Are you able to replicate this without using for_each
? The following doesn't show the problem and the state looks correct.
resource "cloudflare_filter" "wordpress" {
zone_id = var.cloudflare_zone_id
description = "Wordpress break-in attempts that are outside of the office"
expression = "(http.request.uri.path ~ \".*wp-login.php\" or http.request.uri.path ~ \".*xmlrpc.php\") and ip.src ne 192.0.2.1"
}
resource "cloudflare_firewall_rule" "wordpress" {
zone_id = var.cloudflare_zone_id
description = "Block wordpress break-in attempts"
filter_id = cloudflare_filter.wordpress.id
action = "block"
}
$ terraform apply -auto-approve
cloudflare_filter.wordpress: Creating...
cloudflare_filter.wordpress: Creation complete after 1s [id=d44f063cb8b743c7a442d25f2a40a4ea]
cloudflare_firewall_rule.wordpress: Creating...
cloudflare_firewall_rule.wordpress: Creation complete after 1s [id=cf5ef17dfee34f268132e6cdc1db49ba]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
$ terraform apply -auto-approve
cloudflare_filter.wordpress: Refreshing state... [id=d44f063cb8b743c7a442d25f2a40a4ea]
cloudflare_firewall_rule.wordpress: Refreshing state... [id=cf5ef17dfee34f268132e6cdc1db49ba]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
$ cat terraform.tfstate | jq '.resources[].instances[]'
{
"schema_version": 0,
"attributes": {
"description": "Wordpress break-in attempts that are outside of the office",
"expression": "(http.request.uri.path ~ \".*wp-login.php\" or http.request.uri.path ~ \".*xmlrpc.php\") and ip.src ne 192.0.2.1",
"id": "d44f063cb8b743c7a442d25f2a40a4ea",
"paused": false,
"ref": "",
"zone_id": "0da42c8d2132a9ddaf714f9e7c920711"
},
"sensitive_attributes": [],
"private": "bnVsbA=="
}
{
"schema_version": 0,
"attributes": {
"action": "block",
"description": "Block wordpress break-in attempts",
"filter_id": "d44f063cb8b743c7a442d25f2a40a4ea",
"id": "cf5ef17dfee34f268132e6cdc1db49ba",
"paused": false,
"priority": 0,
"products": [],
"zone_id": "0da42c8d2132a9ddaf714f9e7c920711"
},
"sensitive_attributes": [],
"private": "bnVsbA==",
"dependencies": [
"cloudflare_filter.wordpress"
]
}
You are not settings the products
param in your example btw.
What I've tried is to explicitly set it to []
(hardcoded):
resource "cloudflare_firewall_rule" "rules" {
for_each = local.rules
zone_id = lookup(data.cloudflare_zones.domain.zones[0], "id")
filter_id = cloudflare_filter.filters[each.value.expression].id
priority = each.value.priority
description = each.value.description
paused = each.value.paused
action = each.value.action
products = []
}
The addition that terraform plan
reports is:
+ resource "cloudflare_firewall_rule" "rules" {
+ action = "challenge"
+ description = "TEST"
+ filter_id = (known after apply)
+ id = (known after apply)
+ paused = false
+ priority = 41
+ zone_id = "REMOVED"
}
As you can see from above, it does not even include products
within the resource to be created.
However, when looking at the Changes to Outputs
section which is defined as so:
output "rules" {
description = "Created Cloudflare rules for the current zone."
value = cloudflare_firewall_rule.rules
}
Then I see that the fetched products
is again returned as null
Plan: 2 to add, 2 to change, 0 to destroy.
Changes to Outputs:
~ rules = {
+ (ip.geoip.asnum eq 00000) = {
+ action = "challenge"
+ description = "TEST"
+ filter_id = (known after apply)
+ id = (known after apply)
+ paused = false
+ priority = 41
+ products = null
+ zone_id = "<REMOVED>"
}
# (38 unchanged elements hidden)
}
So anyways in both examples, the initial issue post and the newly added one they do apply correctly and everything is set fine at Cloudflare level. However the Terraform state does not seem to be correct and reports wrong values for the output. This is then also the reason that I need to apply twice in order for it to get the correct output values.
Thanks, you're right, that example was missing the products
attribute (I copied in the wrong example).
Appreciate the updated comments which sheds more light here as the issue isn't actually with the resource, it's using output
s where the problem rears its head.
The apply
only takes a single run and the state is correct (an empty list) as intended so that seems fine. We don't do anything special for outputs within the provider and the handling of those values are all performed by Terraform core so I think you may need to open a bug with the core team to find out what is going on here. Only thing that hints at this behaviour is the following output on 1.x
Outputs:
rules = {
"action" = "block"
"description" = "Block wordpress break-in attempts"
"filter_id" = "8c1b942df69643c1b706946135723975"
"id" = "2cf7bdc06f1045a4b1c372ef8544cfd9"
"paused" = false
"priority" = 0
"products" = toset(null) /* of string */
"zone_id" = "0da42c8d2132a9ddaf714f9e7c920711"
}
Running this in the console shows the outcome you are seeing.
$ terraform console
> toset(null)
null
Closing as this looks like a Terraform core issue, not something we control or can fix in the provider.
Confirmation
Terraform and Cloudflare provider version
Terraform v1.0.7 on linux_amd64
Affected resource(s)
cloudflare_firewall_rule
Terraform configuration files
Debug output
Panic output
No response
Expected output
It is expected that
products
is set to an empty list:[]
instead ofnull
during the initial first runActual output
During the first run,
products
is set tonull
Steps to reproduce
terraform.tfvars
:The issue lies within
products = each.value.products
. Even though it is set to an empty list ([]
). The firstterraform apply
will set it tonull
. See below for roll out:If I now do another plan, it tells me that changes were detected outside terraform and that it now wants to set
products
to an empty list instead (which is what I've told it initially to do).Additional factoids
No response
References
Might be related to this one: https://github.com/cloudflare/terraform-provider-cloudflare/issues/1224