terraform icon indicating copy to clipboard operation
terraform copied to clipboard

[ BUG ] Dynamic attribute block attempts to add an empty block when using map(string)

Open dreinhardt89 opened this issue 10 months ago • 1 comments

Terraform Version

1.7.5

Terraform Configuration Files

locals {
  bypass_pull_request_allowances = {
    users = var.pull_request_bypassers # list of strings
    apps  = var.gh_app_ids # list of strings
  }
}
resource "github_branch_protection_v3" "master_with_reviews" {
  repository     = "example"
  branch         = "main"
  enforce_admins = false

  required_pull_request_reviews {
    require_code_owner_reviews      = true
    required_approving_review_count = var.number_of_approvers
    dynamic "bypass_pull_request_allowances" {
      for_each = (length(var.pull_request_bypassers) > 0 || length(var.gh_app_ids) > 0) ? [1] : []
      content {
        users = local.bypass_pull_request_allowances.users
        apps  = local.bypass_pull_request_allowances.apps
      }
    }
  }
}

Debug Output

  # module.example_module.github_branch_protection_v3.master_with_reviews[0] will be updated in-place
  ~ resource "github_branch_protection_v3" "master_with_reviews" {
        id                              = "example:main"
        # (6 unchanged attributes hidden)

      ~ required_pull_request_reviews {
            # (7 unchanged attributes hidden)

          + bypass_pull_request_allowances {}
        }

        # (1 unchanged block hidden)
    }

Expected Behavior

Terraform should not try to add an empty block if the foreach is set to empty.

Actual Behavior

Empty block is added.

Steps to Reproduce

Run terraform plan with the above config.

Additional Context

This was brought up before here: #24496

I bring this up as this is not a purely cosmetic thing in the github providers case (which errors out if you try to add an empty block) so I believe this should be fixed for those instances where a provider doesn't allow an empty block.

References

  • #24496

dreinhardt89 avatar Apr 16 '24 19:04 dreinhardt89

Hi @dreinhardt-terminus! Thanks for reporting this.

I would expect the behavior similar to what you observed here if either var.pull_request_bypassers or var.gh_app_ids had a value that can't be determined during the apply step, because then the result of your conditional would be an unknown list of number and therefore Terraform can't predict how many bypass_pull_request_allowances would be generated.

Providers using the legacy plugin SDK (which includes this GitHub provider) can't understand the idea of the number of blocks being unknown, because the legacy SDK predates that being made possible in Terraform v0.12, and so Terraform Core describes that situation to a provider by sending one block whose arguments are all set to unknown values.

However, I'm not sure if that's what's happening here, because I can't see your values for var.pull_request_bypassers and var.gh_app_ids. Can you temporarily add output values returning those values verbatim, and then share the values that Terraform plans for them? For example:

output "pull_request_bypassers" {
  value = var.pull_request_bypassers
}

output "gh_app_ids" {
  value = var.gh_app_ids
}

If those output values both show up as having known values during planning (that is, if they are reported as anything other than (known after apply)) then that would disprove my idea above, in which case we can try something else to look for the real explanation for this behavior.

Thanks!

apparentlymart avatar Apr 17 '24 00:04 apparentlymart