terraform icon indicating copy to clipboard operation
terraform copied to clipboard

`yamldecode()` should support files with `%YAML 1.2` directive

Open asaba-hashi opened this issue 1 year ago • 4 comments

Terraform Version

Terraform v1.7.3
on darwin_arm64

Terraform Configuration Files

locals {
   doc = <<EOT
%YAML 1.2
---
root:
  key: value
EOT
   val = yamldecode(local.doc)["root"]["key"]
}

output "val" {
   value = local.val
}

Debug Output

https://gist.github.com/asaba-hashi/bb070ec6caadf4c588209cbd2350344c

Expected Behavior

The "doc" contents should be correctly parsed as YAML.


Changes to Outputs:
  + val = "value"

Actual Behavior

terraform reported an error

╷
│ Error: Error in function call
│
│   on test.tf line 8, in locals:
│    8:    val = yamldecode(local.doc)["root"]["key"]
│     ├────────────────
│     │ while calling yamldecode(src)
│     │ local.doc is "%YAML 1.2\n---\nroot:\n  key: value\n"
│
│ Call to function "yamldecode" failed: found incompatible YAML document.

Steps to Reproduce

  1. terraform init
  2. terraform plan

Additional Context

YAML 1.2 introduces the %YAML directive to direct parsers to treat the document as version 1.1 or 1.2.

In particular, YAML 1.2 introduces a Failsafe Schema that does not include the additional "truthy" values like on, no etc. , so this may be the path towards fixes/workarounds for problems like #34611. The workaround would be for such documents to include a %YAML 1.2 directive.

References

No response

asaba-hashi avatar Feb 15 '24 21:02 asaba-hashi

Thanks for this feature request! If you are viewing this issue and would like to indicate your interest, please use the 👍 reaction on the issue description to upvote this issue. We also welcome additional use case descriptions. Thanks again!

crw avatar Feb 20 '24 19:02 crw

The YAML 1.2 spec says:

A version 1.2 YAML processor must accept documents with an explicit “%YAML 1.2” directive, as well as documents lacking a “YAML” directive. Such documents are assumed to conform to the 1.2 version specification.

While the docs for yamldecode do say that only a "limited" portion of 1.2 is supported, the parser is behaving more like 1.1 parser, so I do still think this is a bug (whether in the docs or implementation), WDTY?

asaba-hashi avatar Feb 21 '24 15:02 asaba-hashi

Here is a workaround for interoperating where you can work with strictly 1.1 docs, which will work with a more compliant parser/encoder like raumel.yamls roundtrip encoder:

locals {
   doc = <<EOT
%YAML 1.1
---
root:
  notaboolvalue: 'no'
  'no': no
EOT
   val1 = yamldecode(trimprefix(local.doc, "%YAML 1.1\n"))["root"]["no"]
   val2 = yamldecode(trimprefix(local.doc, "%YAML 1.1\n"))["root"]["notaboolvalue"]
}

output "notaboolkey" {
   value = local.val1
}

output "notaboolvalue" {
   value = local.val2
}

asaba-hashi avatar Feb 21 '24 18:02 asaba-hashi

The enhancement determination was made due to the "limited" disclaimer in the docs, so the thought in triage with @apparentlymart is that any increase in functionality is a new feature (otherwise it would just be documented as supported). Thanks for the work-around!

crw avatar Feb 21 '24 20:02 crw