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
42.53k stars 9.52k forks source link

Allow YAML variable definition files; terraform.yml.tfvars #28938

Open TeamDman opened 3 years ago

TeamDman commented 3 years ago

Current Terraform Version

Terraform v0.15.1

Use-cases

YAML has anchors and references, which are useful for reducing duplication and still allowing overrides of default values.
Would allow default values without having to use (currently experimental) optional fields in variable definitions paired with coalesce statements.

Example terraform.yml.tfvars

# "ignored", used to supply anchor
template: 
  probe: &probe
    interval: 30
    minimum_servers: 0
    path: /
    pick_host_name_from_backend_http_settings: false
    port: 443
    protocol: Https
    timeout: 30
    unhealthy_threshold: 3
    success_status_codes:
      - 200-404

probes:
# use references to anchors to pull default values
  - <<: *probe
    name: myProbe
    path: /api
    port: 80
    protocol: http
  - <<: *probe
    name: myOtherProbe
    path: /other

variables.tf

variable "probes" {
  type = object({
    name                                      = string
    interval                                  = number
    minimum_servers                           = number
    path                                      = string
    pick_host_name_from_backend_http_settings = bool
    port                                      = number
    protocol                                  = string
    timeout                                   = number
    unhealthy_threshold                       = number
    success_status_codes                      = set(string)
  })
}

Attempted Solutions

Yaml files can be loaded in as a local value, but this lacks the checking and safety of variable declarations.

Doesn't support custom validators or secret values.

(terraform docs on variables for reference)

locals {
    probes = yamldecode(file("./probes.yml")).probes
}

Additionally, for optional fields, try must be used instead of coalesce due to undefined fields throwing errors rather than returning null.

Functions aren't allowed in variable defaults, so something like this doesn't work:

variable "probes" {
  type = object({
    name                                      = string
    interval                                  = number
    minimum_servers                           = number
    path                                      = string
    pick_host_name_from_backend_http_settings = bool
    port                                      = number
    protocol                                  = string
    timeout                                   = number
    unhealthy_threshold                       = number
    success_status_codes                      = set(string)
  })
  default=yamldecode(file("terraform.yml.tfvars"))
}

Proposal

Terraform already supports terraform.json.tfvars files.
One hacky solution would be a preprocessor to convert the yaml to json with existing HCL functions before passing it to whatever mechanisms consume the normal json file.

jsonencode(yamldecode(file("terraform.yaml.tfvars"))

References

mohsiur commented 3 years ago

I did a hack solution of this here https://mohsiur.medium.com/terraform-yaml-%EF%B8%8F-3550a3642dd3 , I'm yet to try using anchors but also wondering if there's interest in using yaml files as .tfvars