hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
41.66k stars 9.41k forks source link

How to specify TypeSet parameters with hcl2 format - they do not work with new syntax #19407

Closed ravitandonrt closed 4 years ago

ravitandonrt commented 5 years ago

Terraform Version

2018/11/19 12:32:36 [INFO] Terraform version: 0.12.0 alpha2
2018/11/19 12:32:36 [INFO] Go runtime version: go1.11.1

Terraform Configuration Files

resource "oci_core_security_list" "securitylist1" {
  display_name   = "public"
  compartment_id = "${oci_core_virtual_network.vcn1.compartment_id}"
  vcn_id         = "${oci_core_virtual_network.vcn1.id}"

  egress_security_rules = [{
    protocol    = "all"
    destination = "0.0.0.0/0"
  }]

  ingress_security_rules = [
    {
      protocol = "6"
      source   = "0.0.0.0/0"

      tcp_options = {
        "min" = 80
        "max" = 80
      }

      protocol = "6"
      source   = "0.0.0.0/0"

      tcp_options = {
        "min" = 443
        "max" = 443
      }
    },
  ]
}

Full TF Config available at: https://github.com/terraform-providers/terraform-provider-oci/blob/master/docs/examples/load_balancer/lb_full/lb_full.tf#L120

Note: You will need to remove multi-line comments and provide = for tcp_options for that published tf config to work

Debug Output

2018/11/19 12:35:28 [ERROR] : eval: *terraform.EvalValidateResource, err: 2 problems:

Error: Unsupported attribute

on /Users/ratandon/projects/go/src/github.com/terraform-providers/terraform-provider-oci/docs/examples/load_balancer/lb_full/lb_full.tf line 104, in resource "oci_core_security_list" "securitylist1": 104: egress_security_rules = [{

An attribute named "egress_security_rules" is not expected here. Did you mean to define a block of type "egress_security_rules"?

Error: Unsupported attribute

on /Users/ratandon/projects/go/src/github.com/terraform-providers/terraform-provider-oci/docs/examples/load_balancer/lb_full/lb_full.tf line 109, in resource "oci_core_security_list" "securitylist1": 109: ingress_security_rules = [

An attribute named "ingress_security_rules" is not expected here. Did you mean to define a block of type "ingress_security_rules"?

Crash Output

Expected Behavior

The existing TF config should have worked with Terraform v.12-alpha2 or gave an error with how to specify blocks.

Actual Behavior

Terraform errored out with Unsupported attribute for both egress_security_rules and ingress_security_rules

Steps to Reproduce

  1. terraform init
  2. terraform plan or terraform apply

Additional Context

The currently published TF config uses = equal operator for TypeSets, which failed with above error.

Following a suggestion by @mbfrahry I also tried removing the = for TypeSets for it to be considered a block but that failed with a different error

Error: Argument or block definition required

on lb_full.tf line 104: 104: egress_security_rules [{

An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value.

Error: Argument or block definition required

on lb_full.tf line 109: 109: ingress_security_rules [

An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value.

References

The source for oci_security_list that contains schema definition for egress_security_rules (TypeSet) is here: https://github.com/terraform-providers/terraform-provider-oci/blob/master/oci/core_security_list_resource.go#L33

apparentlymart commented 5 years ago

Hi @ravitandonrt,

The correct syntax for nested blocks is to use a separate block construct for each item:

resource "oci_core_security_list" "securitylist1" {
  display_name   = "public"
  compartment_id = "${oci_core_virtual_network.vcn1.compartment_id}"
  vcn_id         = "${oci_core_virtual_network.vcn1.id}"

  egress_security_rules {
    protocol    = "all"
    destination = "0.0.0.0/0"
  }

  ingress_security_rules {
      protocol = "6"
      source   = "0.0.0.0/0"

      tcp_options {
        min = 80
        max = 80
      }
  }

  ingress_security_rules {
    protocol = "6"
    source   = "0.0.0.0/0"

    tcp_options {
      min = 443
      max = 443
    }
  }
}

Any attribute defined the the provider schema as having an Elem of type *schema.Resource is a nested block. It was a bug in Terraform 0.11 and earlier that attribute syntax worked for these in some cases, caused by missing validation. (Indeed, several strange behaviors in v0.11 and prior had this missing validation as a root cause, because Terraform's internals consider attribute and block syntax to be two separate ideas.)

These should always be named with singular names so that they make sense to use as repeated blocks. I notice that this resource incorrectly uses plural names, and so the result above is confusing due to there being one ingress_security_rules for each rule, but it is what Terraform expects for the schema as given.

ravitandonrt commented 5 years ago

@apparentlymart Thank you for the reply and pointers. I was able to modify the existing config but that resulted in propping up other issues around other nested elements that are optional but are getting flagged due to MinItems.

The bigger concern I have with this change is that although this may have been caused by missing validation, it is a significant change for any TF config that uses older syntax. Would the upgrade tool handle such changes to split the usage of the attribute and block syntax to update the syntax to match the intent?

apparentlymart commented 5 years ago

Yes, the upgrade tool will recognize this sort of incorrect usage and update it to the canonical form that is now required.

cdaniluk commented 5 years ago

Any attribute defined the the provider schema as having an Elem of type *schema.Resource is a nested block. It was a bug in Terraform 0.11 and earlier that attribute syntax worked for these in some cases, caused by missing validation. (Indeed, several strange behaviors in v0.11 and prior had this missing validation as a root cause, because Terraform's internals consider attribute and block syntax to be two separate ideas.)

The docs seem to contradict this:

https://www.terraform.io/docs/configuration/attr-as-blocks.html

Unless I'm conflating two separate issues, it looks like the example above worked exactly because of the alternate syntax described in that appendix.

apparentlymart commented 5 years ago

The "Attributes as Blocks" mode is a special case that a provider developer can opt into on a per-attribute basis, for the situation described in the introduction on that page. That situation doesn't seem to apply to the nested blocks being discussed here (egress_security_rules and ingress_security_rules are defined as blocks rather than attributes), though it potentially could if those blocks were redefined to be attributes before the first 0.12.0-compatible release of this provider, and if their documentation was updated to link to the "Attributes as Blocks" guide, to indicate that this syntax is possible.

cdaniluk commented 5 years ago

Ah, I didn't realize they were defined as blocks in oci_core_security_list. Should have checked first. I was curious about the distinction as there does not seem to be a way to dynamically set TypeSets using for_each and was hoping re-interpreting this as a bug would help my cause as defining TypeSets through a dynamic block seems intuitive in spite of the syntax issues it evidently creates.

apparentlymart commented 5 years ago

A dynamic "egress_security_rules" or dynamic "ingress_security_rules" block should allow creation of these, just as with any block type. If that's not working for you, please open a new issue about it and we'll investigate.

cdaniluk commented 5 years ago

I’m dealing with it on a different provider but still a TypeSet. I will do some more testing and open an issue. Could still be user error.

teamterraform commented 4 years ago

Hi all!

It looks like the original question was answered here, so we're going to close this out. If there are any related problems, please feel free to open a new issue for each one. The community forum is a good place for general questions, as opposed to bug reports or feature requests.

ghost commented 4 years ago

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.