Merge branch 'master' into toml_encoder

This commit is contained in:
Mike Farah 2025-12-16 14:27:22 +11:00
commit aa858520a8
8 changed files with 104 additions and 4 deletions

1
.gitignore vendored
View File

@ -43,6 +43,7 @@ yq*.snap
test.yml
test*.yml
test*.tf
test*.xml
test*.toml
test*.yaml

View File

@ -363,6 +363,8 @@ gah install yq
- [Load content from other files](https://mikefarah.gitbook.io/yq/operators/load)
- [Convert to/from json/ndjson](https://mikefarah.gitbook.io/yq/v/v4.x/usage/convert)
- [Convert to/from xml](https://mikefarah.gitbook.io/yq/v/v4.x/usage/xml)
- [Convert to/from hcl (terraform)](https://mikefarah.gitbook.io/yq/v/v4.x/usage/hcl)
- [Convert to/from toml](https://mikefarah.gitbook.io/yq/v/v4.x/usage/toml)
- [Convert to/from properties](https://mikefarah.gitbook.io/yq/v/v4.x/usage/properties)
- [Convert to/from csv/tsv](https://mikefarah.gitbook.io/yq/usage/csv-tsv)
- [General shell completion scripts (bash/zsh/fish/powershell)](https://mikefarah.gitbook.io/yq/v/v4.x/commands/shell-completion)
@ -413,7 +415,7 @@ Flags:
-h, --help help for yq
-I, --indent int sets indent level for output (default 2)
-i, --inplace update the file in place of first file given.
-p, --input-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|lua|l|ini|i] parse format for input. (default "auto")
-p, --input-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|hcl|h|lua|l|ini|i] parse format for input. (default "auto")
--lua-globals output keys as top-level global variables
--lua-prefix string prefix (default "return ")
--lua-suffix string suffix (default ";\n")
@ -422,7 +424,7 @@ Flags:
-N, --no-doc Don't print document separators (---)
-0, --nul-output Use NUL char to separate values. If unwrap scalar is also set, fail if unwrapped scalar contains NUL char.
-n, --null-input Don't read input, simply evaluate the expression given. Useful for creating docs from scratch.
-o, --output-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|shell|s|lua|l|ini|i] output format type. (default "auto")
-o, --output-format string [auto|a|yaml|y|json|j|props|p|csv|c|tsv|t|xml|x|base64|uri|toml|hcl|h|shell|s|lua|l|ini|i] output format type. (default "auto")
-P, --prettyPrint pretty print, shorthand for '... style = ""'
--properties-array-brackets use [x] in array paths (e.g. for SpringBoot)
--properties-separator string separator to use between keys and values (default " = ")

View File

@ -6,6 +6,7 @@ setUp() {
rm test*.csv 2>/dev/null || true
rm test*.tsv 2>/dev/null || true
rm test*.xml 2>/dev/null || true
rm test*.tf 2>/dev/null || true
}
testInputProperties() {
@ -255,4 +256,61 @@ EOM
assertEquals "$expected" "$X"
}
testInputTerraform() {
cat >test.tf <<EOL
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
tags = {
Environment = "Dev"
Project = "Test"
}
}
EOL
read -r -d '' expected << EOM
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
tags = {
Environment = "Dev"
Project = "Test"
}
}
EOM
X=$(./yq test.tf)
assertEquals "$expected" "$X"
X=$(./yq ea test.tf)
assertEquals "$expected" "$X"
}
testInputTerraformGithubAction() {
cat >test.tf <<EOL
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
tags = {
Environment = "Dev"
Project = "Test"
}
}
EOL
read -r -d '' expected << EOM
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
tags = {
Environment = "Dev"
Project = "Test"
}
}
EOM
X=$(cat /dev/null | ./yq test.tf)
assertEquals "$expected" "$X"
X=$(cat /dev/null | ./yq ea test.tf)
assertEquals "$expected" "$X"
}
source ./scripts/shunit2

27
examples/sample.tf Normal file
View File

@ -0,0 +1,27 @@
# main.tf
# Define required providers and minimum Terraform version
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.2"
}
# Configure the AWS provider
provider "aws" {
region = var.aws_region
}
# Define an S3 bucket resource
resource "aws_s3_bucket" "example_bucket" {
bucket = var.bucket_name
tags = {
Environment = "Development"
Project = "TerraformExample"
}
}

View File

@ -43,6 +43,9 @@ func (he *hclEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
func (he *hclEncoder) Encode(writer io.Writer, node *CandidateNode) error {
log.Debugf("I need to encode %v", NodeToString(node))
if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n")
}
f := hclwrite.NewEmptyFile()
body := f.Body()
@ -490,7 +493,7 @@ func (he *hclEncoder) encodeBlockIfMapping(body *hclwrite.Body, key string, valu
// encodeNode encodes a CandidateNode directly to HCL, preserving style information
func (he *hclEncoder) encodeNode(body *hclwrite.Body, node *CandidateNode) error {
if node.Kind != MappingNode {
return fmt.Errorf("HCL encoder expects a mapping at the root level")
return fmt.Errorf("HCL encoder expects a mapping at the root level, got %v", kindToString(node.Kind))
}
for i := 0; i < len(node.Content); i += 2 {

View File

@ -67,7 +67,7 @@ var TomlFormat = &Format{"toml", []string{},
func() Decoder { return NewTomlDecoder() },
}
var HclFormat = &Format{"hcl", []string{"h"},
var HclFormat = &Format{"hcl", []string{"h", "tf"},
func() Encoder { return NewHclEncoder(ConfiguredHclPreferences) },
func() Decoder { return NewHclDecoder() },
}

View File

@ -325,6 +325,14 @@ var hclFormatScenarios = []formatScenario{
expected: "# Configuration\nport = 8080\n",
scenarioType: "roundtrip",
},
{
description: "Roundtrip: extraction",
skipDoc: true,
input: simpleSample,
expression: ".shouty_message",
expected: "upper(message)\n",
scenarioType: "roundtrip",
},
{
description: "Roundtrip: With templates, functions and arithmetic",
input: simpleSample,

View File

@ -1,5 +1,6 @@
4.50.1:
- Added HCL support!
- Fixing handling of CRLF #2352
- Bumped dependencies
4.49.2: