Backport of command/output: Ignore warnings in JSON mode into v1.15 (#38531)

* backport of commit c34ce2988a

* backport of commit f2b45bbd40

---------

Co-authored-by: Radek Simko <radek.simko@gmail.com>
pull/38532/head
github-actions[bot] 2 weeks ago committed by GitHub
parent fcf1963206
commit 60d9aeed50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
kind: BUG FIXES
body: Avoid printing warnings from 'terraform output -json'
time: 2026-05-06T09:58:57.334037+01:00
custom:
Issue: "38530"

@ -5,11 +5,13 @@ package command
import (
"bytes"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
@ -463,3 +465,84 @@ func TestOutputRaw_warningsSuppressed(t *testing.T) {
t.Fatalf("expected output \"bar\", got: %#v", actual)
}
}
func TestOutputJson_warningsSuppressed(t *testing.T) {
// Pre-populate the inmem backend with a state containing an output value
inmem.Reset()
originalState := states.BuildState(func(s *states.SyncState) {
s.SetOutputValue(
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
cty.StringVal("bar"),
false,
)
})
// Register a backend that wraps inmem with a deprecation warning,
// simulating a backend like S3 whose PrepareConfig warns about
// deprecated attributes (e.g. dynamodb_table).
backendInit.Set("inmem", func() backend.Backend {
return &deprecatedInmemBackend{Backend: inmem.New()}
})
defer backendInit.Set("inmem", inmem.New)
td := t.TempDir()
testCopyDir(t, testFixturePath("output-backend-with-deprecation"), td)
t.Chdir(td)
// Write the state into the inmem backend's default workspace
b := inmem.New()
b.Configure(cty.ObjectVal(map[string]cty.Value{
"lock_id": cty.NullVal(cty.String),
}))
sMgr, sDiags := b.StateMgr(backend.DefaultStateName)
if sDiags.HasErrors() {
t.Fatalf("unexpected error: %s", sDiags.Err())
}
sMgr.WriteState(originalState)
if err := sMgr.PersistState(nil); err != nil {
t.Fatalf("unexpected error: %s", err)
}
view, done := testView(t)
c := &OutputCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
View: view,
},
}
args := []string{"-json"}
code := c.Run(args)
output := done(t)
if code != 0 {
t.Fatalf("unexpected exit code %d\nstderr:\n%s", code, output.Stderr())
}
stderr := output.Stderr()
if strings.Contains(stderr, "deprecated") {
t.Fatalf("warnings should be suppressed, got:\n%s", stderr)
}
expectedJson := `{
"foo":{
"sensitive":false,
"type":"string",
"value":"bar"
}
}`
if diff := cmp.Diff(expectedJson, output.Stdout(), transformJSON); diff != "" {
t.Fatalf("unexpected output: %s", diff)
}
}
var transformJSON = cmp.FilterValues(func(x, y string) bool {
xBytes := []byte(x)
yBytes := []byte(y)
return json.Valid(xBytes) && json.Valid(yBytes)
}, cmp.Transformer("ParseJSON", func(in string) (out any) {
inBytes := []byte(in)
if err := json.Unmarshal(inBytes, &out); err != nil {
panic(err)
}
return out
}))

@ -258,7 +258,10 @@ func (v *OutputJSON) Output(name string, outputs map[string]*states.OutputValue)
}
func (v *OutputJSON) Diagnostics(diags tfdiags.Diagnostics) {
v.view.Diagnostics(diags)
// filter out warnings as we cannot change the current format
// to introduce them gracefully (without breaking existing usage)
errsOnly := diags.ErrorsOnly()
v.view.Diagnostics(errsOnly)
}
// For text and raw output modes, an empty map of outputs is considered a

Loading…
Cancel
Save