Skip to content

Commit 6754fba

Browse files
author
Liam Cervante
committed
Merge branch 'main' of github.com:hashicorp/terraform into liamcervante/34960
2 parents b813d39 + ed76d19 commit 6754fba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+3264
-1385
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'terraform test: expected diagnostics will be included in test output when running in verbose mode"'
3+
time: 2025-07-23T12:29:22.244611+02:00
4+
custom:
5+
Issue: "37362"

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
## 1.14.0 (Unreleased)
22

33

4+
ENHANCEMENTS:
5+
6+
* terraform test: expected diagnostics will be included in test output when running in verbose mode" ([#37362](https://github.com/hashicorp/terraform/issues/37362))
7+
8+
49
EXPERIMENTS:
510

611
Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases.

docs/plugin-protocol/tfplugin5.proto

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,8 @@ message GetProviderSchema {
463463
map<string, Function> functions = 7;
464464
map<string, Schema> ephemeral_resource_schemas = 8;
465465
map<string, Schema> list_resource_schemas = 9;
466-
map<string, ActionSchema> action_schemas = 10;
466+
reserved 10; // Field number 10 is used by state stores in version 6
467+
map<string, ActionSchema> action_schemas = 11;
467468
repeated Diagnostic diagnostics = 4;
468469
Schema provider_meta = 5;
469470
ServerCapabilities server_capabilities = 6;
@@ -936,9 +937,9 @@ message PlanAction {
936937
// linked resources, this should match the order the resources are specified in the schema.
937938
repeated LinkedResource linked_resources = 2;
938939
// config of the action, based on the schema of the actual action
939-
DynamicValue config = 6;
940+
DynamicValue config = 3;
940941
// metadata
941-
ClientCapabilities client_capabilities = 8;
942+
ClientCapabilities client_capabilities = 4;
942943
}
943944

944945
message Response {

docs/plugin-protocol/tfplugin6.proto

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,9 @@ message PlanAction {
974974
// linked resources, this should match the order the resources are specified in the schema.
975975
repeated LinkedResource linked_resources = 2;
976976
// config of the action, based on the schema of the actual action
977-
DynamicValue config = 6;
977+
DynamicValue config = 3;
978978
// metadata
979-
ClientCapabilities client_capabilities = 8;
979+
ClientCapabilities client_capabilities = 4;
980980
}
981981

982982
message Response {

internal/addrs/action.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -333,25 +333,6 @@ type configActionKey string
333333

334334
func (k configActionKey) uniqueKeySigil() {}
335335

336-
// AbsActionInvocationInstance describes the invocation of an action as part of a plan / apply.
337-
type AbsActionInvocationInstance struct {
338-
TriggeringResource AbsResourceInstance
339-
Action AbsActionInstance
340-
TriggerIndex int
341-
342-
// TriggerBlockSourceRange is the location of the action_trigger block
343-
// within the resources lifecycle block that triggered this action.
344-
TriggerBlockSourceRange *tfdiags.SourceRange
345-
346-
// ActionReferenceSourceRange is the location of the action reference
347-
// in the actions list within the action_trigger block.
348-
ActionReferenceSourceRange *tfdiags.SourceRange
349-
}
350-
351-
func (a AbsActionInvocationInstance) String() string {
352-
return fmt.Sprintf("%s.%d.%s", a.TriggeringResource.String(), a.TriggerIndex, a.Action.String())
353-
}
354-
355336
// ParseAbsActionInstanceStr is a helper wrapper around
356337
// ParseAbsActionInstance that takes a string and parses it with the HCL
357338
// native syntax traversal parser before interpreting it.

internal/addrs/action_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,15 @@ func TestActionInstanceEqual(t *testing.T) {
109109
func TestAbsActionInstanceEqual(t *testing.T) {
110110
actions := []AbsActionInstance{
111111
{
112-
RootModuleInstance,
113-
ActionInstance{
112+
Module: RootModuleInstance,
113+
Action: ActionInstance{
114114
Action: Action{Type: "foo", Name: "bar"},
115115
Key: NoKey,
116116
},
117117
},
118118
{
119-
mustParseModuleInstanceStr("module.child"),
120-
ActionInstance{
119+
Module: mustParseModuleInstanceStr("module.child"),
120+
Action: ActionInstance{
121121
Action: Action{Type: "the", Name: "bloop"},
122122
Key: StringKey("fish"),
123123
},
@@ -139,15 +139,15 @@ func TestAbsActionInstanceEqual(t *testing.T) {
139139
}{
140140
{ // different keys
141141
AbsActionInstance{
142-
RootModuleInstance,
143-
ActionInstance{
142+
Module: RootModuleInstance,
143+
Action: ActionInstance{
144144
Action: Action{Type: "foo", Name: "bar"},
145145
Key: NoKey,
146146
},
147147
},
148148
AbsActionInstance{
149-
RootModuleInstance,
150-
ActionInstance{
149+
Module: RootModuleInstance,
150+
Action: ActionInstance{
151151
Action: Action{Type: "foo", Name: "bar"},
152152
Key: IntKey(1),
153153
},
@@ -156,15 +156,15 @@ func TestAbsActionInstanceEqual(t *testing.T) {
156156

157157
{ // different module
158158
AbsActionInstance{
159-
RootModuleInstance,
160-
ActionInstance{
159+
Module: RootModuleInstance,
160+
Action: ActionInstance{
161161
Action: Action{Type: "foo", Name: "bar"},
162162
Key: NoKey,
163163
},
164164
},
165165
AbsActionInstance{
166-
mustParseModuleInstanceStr("module.child[1]"),
167-
ActionInstance{
166+
Module: mustParseModuleInstanceStr("module.child[1]"),
167+
Action: ActionInstance{
168168
Action: Action{Type: "foo", Name: "bar"},
169169
Key: NoKey,
170170
},
@@ -173,15 +173,15 @@ func TestAbsActionInstanceEqual(t *testing.T) {
173173

174174
{ // totally different
175175
AbsActionInstance{
176-
RootModuleInstance,
177-
ActionInstance{
176+
Module: RootModuleInstance,
177+
Action: ActionInstance{
178178
Action: Action{Type: "oof", Name: "rab"},
179179
Key: NoKey,
180180
},
181181
},
182182
AbsActionInstance{
183-
mustParseModuleInstanceStr("module.foo"),
184-
ActionInstance{
183+
Module: mustParseModuleInstanceStr("module.foo"),
184+
Action: ActionInstance{
185185
Action: Action{Type: "foo", Name: "bar"},
186186
Key: IntKey(11),
187187
},

internal/addrs/map.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
package addrs
55

6+
import "iter"
7+
68
// Map represents a mapping whose keys are address types that implement
79
// UniqueKeyer.
810
//
@@ -135,3 +137,13 @@ func (m Map[K, V]) Values() []V {
135137
}
136138
return ret
137139
}
140+
141+
func (m Map[K, V]) Iter() iter.Seq2[K, V] {
142+
return func(yield func(K, V) bool) {
143+
for _, elem := range m.Elements() {
144+
if !yield(elem.Key, elem.Value) {
145+
return
146+
}
147+
}
148+
}
149+
}

internal/backend/local/backend_plan.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,30 @@ func (b *Local) opPlan(
4141
return
4242
}
4343

44-
// Local planning requires a config, unless we're planning to destroy.
45-
if op.PlanMode != plans.DestroyMode && !op.HasConfig() {
46-
diags = diags.Append(tfdiags.Sourceless(
47-
tfdiags.Error,
48-
"No configuration files",
49-
"Plan requires configuration to be present. Planning without a configuration would "+
50-
"mark everything for destruction, which is normally not what is desired. If you "+
51-
"would like to destroy everything, run plan with the -destroy option. Otherwise, "+
52-
"create a Terraform configuration file (.tf file) and try again.",
53-
))
54-
op.ReportResult(runningOp, diags)
55-
return
44+
if !op.HasConfig() {
45+
switch {
46+
case op.Query:
47+
// Special diag for terraform query command
48+
diags = diags.Append(tfdiags.Sourceless(
49+
tfdiags.Error,
50+
"No configuration files",
51+
"Query requires a query configuration to be present. Create a Terraform query configuration file (.tfquery.hcl file) and try again.",
52+
))
53+
op.ReportResult(runningOp, diags)
54+
return
55+
case op.PlanMode != plans.DestroyMode:
56+
// Local planning requires a config, unless we're planning to destroy.
57+
diags = diags.Append(tfdiags.Sourceless(
58+
tfdiags.Error,
59+
"No configuration files",
60+
"Plan requires configuration to be present. Planning without a configuration would "+
61+
"mark everything for destruction, which is normally not what is desired. If you "+
62+
"would like to destroy everything, run plan with the -destroy option. Otherwise, "+
63+
"create a Terraform configuration file (.tf file) and try again.",
64+
))
65+
op.ReportResult(runningOp, diags)
66+
return
67+
}
5668
}
5769

5870
if len(op.GenerateConfigOut) > 0 {

internal/command/fmt.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"bytes"
88
"fmt"
99
"io"
10-
"io/ioutil"
1110
"log"
1211
"os"
1312
"os/exec"
@@ -53,6 +52,10 @@ func (c *FmtCommand) Run(args []string) int {
5352
c.input = os.Stdin
5453
}
5554

55+
if c.Meta.AllowExperimentalFeatures {
56+
fmtSupportedExts = append(fmtSupportedExts, ".tfquery.hcl")
57+
}
58+
5659
args = c.Meta.process(args)
5760
cmdFlags := c.Meta.defaultFlagSet("fmt")
5861
cmdFlags.BoolVar(&c.list, "list", true, "list")
@@ -174,7 +177,7 @@ func (c *FmtCommand) processFile(path string, r io.Reader, w io.Writer, isStdout
174177

175178
log.Printf("[TRACE] terraform fmt: Formatting %s", path)
176179

177-
src, err := ioutil.ReadAll(r)
180+
src, err := io.ReadAll(r)
178181
if err != nil {
179182
diags = diags.Append(fmt.Errorf("Failed to read %s", path))
180183
return diags
@@ -201,7 +204,7 @@ func (c *FmtCommand) processFile(path string, r io.Reader, w io.Writer, isStdout
201204
fmt.Fprintln(w, path)
202205
}
203206
if c.write {
204-
err := ioutil.WriteFile(path, result, 0644)
207+
err := os.WriteFile(path, result, 0644)
205208
if err != nil {
206209
diags = diags.Append(fmt.Errorf("Failed to write %s", path))
207210
return diags
@@ -232,7 +235,7 @@ func (c *FmtCommand) processDir(path string, stdout io.Writer) tfdiags.Diagnosti
232235

233236
log.Printf("[TRACE] terraform fmt: looking for files in %s", path)
234237

235-
entries, err := ioutil.ReadDir(path)
238+
entries, err := os.ReadDir(path)
236239
if err != nil {
237240
switch {
238241
case os.IsNotExist(err):
@@ -551,8 +554,8 @@ func (c *FmtCommand) Help() string {
551554
Usage: terraform [global options] fmt [options] [target...]
552555
553556
Rewrites all Terraform configuration files to a canonical format. All
554-
configuration files (.tf), variables files (.tfvars), and testing files
555-
(.tftest.hcl) are updated. JSON files (.tf.json, .tfvars.json, or
557+
configuration files (.tf), variables files (.tfvars), and testing files
558+
(.tftest.hcl) are updated. JSON files (.tf.json, .tfvars.json, or
556559
.tftest.json) are not modified.
557560
558561
By default, fmt scans the current directory for configuration files. If you
@@ -590,14 +593,14 @@ func (c *FmtCommand) Synopsis() string {
590593
}
591594

592595
func bytesDiff(b1, b2 []byte, path string) (data []byte, err error) {
593-
f1, err := ioutil.TempFile("", "")
596+
f1, err := os.CreateTemp("", "")
594597
if err != nil {
595598
return
596599
}
597600
defer os.Remove(f1.Name())
598601
defer f1.Close()
599602

600-
f2, err := ioutil.TempFile("", "")
603+
f2, err := os.CreateTemp("", "")
601604
if err != nil {
602605
return
603606
}

0 commit comments

Comments
 (0)