Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terraform 0.14 destroy provisioner issues: Invalid value for "inputMap" parameter: argument must not be null. #28065

Closed
brikis98 opened this issue Mar 12, 2021 · 5 comments
Labels
bug confirmed a Terraform Core team member has reproduced this issue dependencies Auto-pinning explained a Terraform Core team member has described the root cause of this issue in code

Comments

@brikis98
Copy link
Contributor

brikis98 commented Mar 12, 2021

Terraform Version

v0.14.5

Terraform Configuration Files

resource "aws_acm_certificate" "cert" {
  for_each = local.acm_tls_certificates

  # ... (various params) ...

  tags = each.value.tags

  # Not sure if this lifecycle stuff is relevant to the bug, but including it here for completeness
  lifecycle {
    create_before_destroy = true
    ignore_changes = [subject_alternative_names]
  }

  # After much digging, we found out that this is what causes the error
  provisioner "local-exec" {
    when    = destroy
    # Our goal here is, on destroy, to run a specific script if a certain tag is set
    command = tobool(lookup(self.tags, "foo", false)) ? "${path.module}/script.sh ${self.arn}" : "true"
  }
}

Expected Behavior

terraform destroy runs successfully.

Actual Behavior

When running destroy, we get the error:

- Invalid function argument: Invalid value for "inputMap" parameter: argument must not be null.

Note: there is no file or line number in the error, so it took us a long time to figure out that it was the destroy provisioner! So at the very least, is there a way to improve this error message?

Steps to Reproduce

  1. terraform init
  2. terraform apply
  3. terraform destroy

Additional Context

We are looking up data in self.tags as a workaround for destroy provisioners not being able to reference any other resources as of 0.13. This code worked fine with 0.13, but it seems that as of 0.14, destroy provisioners are even more restricted in some way? I'm not sure, as the error message is vague, and doesn't provide any detail of what's actually wrong.

@brikis98 brikis98 added bug new new issue not yet triaged labels Mar 12, 2021
@brikis98
Copy link
Contributor Author

Update: removing the tobool(lookup(self.tags, "foo", false)) check makes the error go away, so it's something to do with that.

@brikis98
Copy link
Contributor Author

Ah, OK, this looks like a bug with self.tags. Consider this new version:

resource "aws_acm_certificate" "cert" {
  # ... (various params) ...

  tags = {
    foo = "bar"
  }

  provisioner "local-exec" {
    when    = destroy
    command = "echo 'tags = ${jsonencode(self.tags)}'"
  }
}

Note how tags is hard-coded with foo = "bar". When I run apply and destroy, I see the following:

tags = {"foo":"bar"}

This is as expected. But now, let's hard-code tags to an empty map instead:

resource "aws_acm_certificate" "cert" {
  # ... (various params) ...

  tags = {}

  provisioner "local-exec" {
    when    = destroy
    command = "echo 'tags = ${jsonencode(self.tags)}'"
  }
}

Now when I run apply and destroy, I get:

tags = null

So self.tags returns null instead of an empty map, and then that null causes an error with lookup. This seems like a bug?

@brikis98
Copy link
Contributor Author

I believe the workaround is to check for null explicitly. Note that as && is not short-circuiting, we have to do this via nested ternary expressions:

    command = (
      self.tags != null
        ? tobool(lookup(self.tags, "foo", false)) ? "${path.module}/script.sh ${self.arn}" : "true"
        : "true"
    )

@jbardin jbardin added confirmed a Terraform Core team member has reproduced this issue dependencies Auto-pinning and removed new new issue not yet triaged labels Mar 12, 2021
@jbardin
Copy link
Member

jbardin commented Mar 12, 2021

Hi @brikis98,

Thanks for the followup! Looking a little more closely, the cause of the behavior seen here is due to the provider itself, or more specifically the legacy SDK used by most providers. The logs from applying the resource will contain a line like:

[WARN]  Provider "registry.terraform.io/hashicorp/aws" produced an invalid plan for aws_acm_certificate.cert, but we are tolerating it because it is using the legacy plugin SDK.
    The following problems may be the cause of any confusing errors from downstream operations:
      - .tags: planned value cty.NullVal(cty.Map(cty.String)) does not match config value cty.MapValEmpty(cty.String)

The provider here is returning a null value rather than the configured empty map, which is what is ultimately passed to the provisioner. Because the legacy SDK cannot readily differentiate between empty and null values, it's a shortcoming we have to accept for the time being.

I am going to close this out however, since there is nothing we can do to mitigate this in Terraform itself. Thanks!

@jbardin jbardin closed this as completed Mar 12, 2021
@jbardin jbardin added the explained a Terraform Core team member has described the root cause of this issue in code label Mar 12, 2021
@ghost
Copy link

ghost commented Apr 12, 2021

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug confirmed a Terraform Core team member has reproduced this issue dependencies Auto-pinning explained a Terraform Core team member has described the root cause of this issue in code
Projects
None yet
Development

No branches or pull requests

2 participants