mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
wrap JSON strings as jsonencode calls on generate-config-out (#1595)
Signed-off-by: ollevche <ollevche@gmail.com> Signed-off-by: Oleksandr Levchenkov <ollevche@gmail.com>
This commit is contained in:
parent
82a6797894
commit
b7098f50cb
@ -6,6 +6,7 @@ NEW FEATURES:
|
||||
|
||||
ENHANCEMENTS:
|
||||
* Added `tofu test -json` types to website Machine-Readable UI documentation ([1408](https://github.com/opentofu/opentofu/issues/1408))
|
||||
* Made `tofu plan` with `generate-config-out` flag replace JSON strings with `jsonencode` functions calls. ([#1595](https://github.com/opentofu/opentofu/pull/1595))
|
||||
|
||||
BUG FIXES:
|
||||
* Fixed crash in gcs backend when using certain commands ([#1618](https://github.com/opentofu/opentofu/pull/1618))
|
||||
|
@ -6,6 +6,7 @@
|
||||
package genconfig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -13,6 +14,7 @@ import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hclwrite"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/json"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
@ -160,7 +162,7 @@ func writeConfigAttributesFromExisting(addr addrs.AbsResourceInstance, buf *stri
|
||||
if attrS.Sensitive || val.IsMarked() {
|
||||
buf.WriteString("null # sensitive")
|
||||
} else {
|
||||
tok := hclwrite.TokensForValue(val)
|
||||
tok := tryWrapAsJsonEncodeFunctionCall(val)
|
||||
if _, err := tok.WriteTo(buf); err != nil {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagWarning,
|
||||
@ -592,3 +594,40 @@ func omitUnknowns(val cty.Value) cty.Value {
|
||||
panic(fmt.Sprintf("omitUnknowns cannot handle %#v", val))
|
||||
}
|
||||
}
|
||||
|
||||
func tryWrapAsJsonEncodeFunctionCall(v cty.Value) hclwrite.Tokens {
|
||||
tokens, err := wrapAsJSONEncodeFunctionCall(v)
|
||||
if err != nil {
|
||||
return hclwrite.TokensForValue(v)
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func wrapAsJSONEncodeFunctionCall(v cty.Value) (hclwrite.Tokens, error) {
|
||||
if v.IsNull() || v.Type() != cty.String || !v.IsKnown() {
|
||||
return nil, errors.New("value cannot be treated as JSON string")
|
||||
}
|
||||
|
||||
s := []byte(strings.TrimSpace(v.AsString()))
|
||||
if len(s) == 0 {
|
||||
return nil, errors.New("empty value")
|
||||
}
|
||||
|
||||
if s[0] != '{' && s[0] != '[' {
|
||||
return nil, errors.New("value is not a JSON object, nor a JSON array")
|
||||
}
|
||||
|
||||
t, err := json.ImpliedType(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot define implied cty type (possibly not a JSON string): %w", err)
|
||||
}
|
||||
|
||||
v, err = json.Unmarshal(s, t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot unmarshal using implied type (possible not a JSON string): %w", err)
|
||||
}
|
||||
|
||||
tokens := hclwrite.TokensForFunctionCall("jsonencode", hclwrite.TokensForValue(v))
|
||||
|
||||
return tokens, nil
|
||||
}
|
||||
|
@ -423,6 +423,73 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
list = null
|
||||
map = null
|
||||
single = null
|
||||
}`,
|
||||
},
|
||||
"jsonencode_wrapping": {
|
||||
schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"juststr": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"jsonobj": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"jsonarr": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"sensitivejsonobj": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"secrets": {
|
||||
Type: cty.Object(map[string]cty.Type{
|
||||
"main": cty.String,
|
||||
"secondary": cty.String,
|
||||
}),
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
addr: addrs.AbsResourceInstance{
|
||||
Module: nil,
|
||||
Resource: addrs.ResourceInstance{
|
||||
Resource: addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "tfcoremock_simple_resource",
|
||||
Name: "example",
|
||||
},
|
||||
Key: nil,
|
||||
},
|
||||
},
|
||||
provider: addrs.LocalProviderConfig{
|
||||
LocalName: "tfcoremock",
|
||||
},
|
||||
value: cty.ObjectVal(map[string]cty.Value{
|
||||
"juststr": cty.StringVal("{a=b}"),
|
||||
"jsonobj": cty.StringVal(`{"SomeDate":"2012-10-17"}`),
|
||||
"jsonarr": cty.StringVal(`[{"a": 1}]`),
|
||||
"sensitivejsonobj": cty.StringVal(`{"SomePassword":"dontstealplease"}`),
|
||||
"secrets": cty.ObjectVal(map[string]cty.Value{
|
||||
"main": cty.StringVal(`{"v":"mypass"}`),
|
||||
"secondary": cty.StringVal(`{"v":"mybackup"}`),
|
||||
}),
|
||||
}),
|
||||
expected: `
|
||||
resource "tfcoremock_simple_resource" "example" {
|
||||
jsonarr = jsonencode([{
|
||||
a = 1
|
||||
}])
|
||||
jsonobj = jsonencode({
|
||||
SomeDate = "2012-10-17"
|
||||
})
|
||||
juststr = "{a=b}"
|
||||
secrets = null # sensitive
|
||||
sensitivejsonobj = null # sensitive
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user