Skip to content

Commit e6d90bd

Browse files
authored
fix: rewrite onlyDataResources (#9263)
1 parent d37f6d8 commit e6d90bd

File tree

2 files changed

+144
-10
lines changed

2 files changed

+144
-10
lines changed

provisioner/terraform/executor.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -264,18 +264,21 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l
264264
}, nil
265265
}
266266

267-
func onlyDataResources(sm *tfjson.StateModule) *tfjson.StateModule {
268-
sm2 := *sm
269-
sm2.Resources = make([]*tfjson.StateResource, 0, len(sm.Resources))
267+
func onlyDataResources(sm tfjson.StateModule) tfjson.StateModule {
268+
filtered := sm
269+
filtered.Resources = []*tfjson.StateResource{}
270270
for _, r := range sm.Resources {
271271
if r.Mode == "data" {
272-
sm2.Resources = append(sm2.Resources, r)
272+
filtered.Resources = append(filtered.Resources, r)
273273
}
274274
}
275+
276+
filtered.ChildModules = []*tfjson.StateModule{}
275277
for _, c := range sm.ChildModules {
276-
sm2.ChildModules = append(sm2.ChildModules, onlyDataResources(c))
278+
filteredChild := onlyDataResources(*c)
279+
filtered.ChildModules = append(filtered.ChildModules, &filteredChild)
277280
}
278-
return &sm2
281+
return filtered
279282
}
280283

281284
// planResources must only be called while the lock is held.
@@ -300,10 +303,9 @@ func (e *executor) planResources(ctx, killCtx context.Context, planfilePath stri
300303
// We don't want all prior resources, because Quotas (and
301304
// future features) would never know which resources are getting
302305
// deleted by a stop.
303-
modules = append(
304-
modules,
305-
onlyDataResources(plan.PriorState.Values.RootModule),
306-
)
306+
307+
filtered := onlyDataResources(*plan.PriorState.Values.RootModule)
308+
modules = append(modules, &filtered)
307309
}
308310
modules = append(modules, plan.PlannedValues.RootModule)
309311

provisioner/terraform/executor_internal_test.go

+132
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package terraform
22

33
import (
4+
"encoding/json"
45
"testing"
56

7+
tfjson "github.com/hashicorp/terraform-json"
68
"github.com/stretchr/testify/require"
79

810
"github.com/coder/coder/v2/provisionersdk/proto"
@@ -41,3 +43,133 @@ From standing in the English rain`))
4143
}
4244
require.Equal(t, expected, logr.logs)
4345
}
46+
47+
func TestOnlyDataResources(t *testing.T) {
48+
t.Parallel()
49+
50+
tests := []struct {
51+
name string
52+
stateMod *tfjson.StateModule
53+
expected *tfjson.StateModule
54+
}{
55+
{
56+
name: "empty state module",
57+
stateMod: &tfjson.StateModule{},
58+
expected: &tfjson.StateModule{},
59+
},
60+
{
61+
name: "only data resources",
62+
stateMod: &tfjson.StateModule{
63+
Resources: []*tfjson.StateResource{
64+
{Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"},
65+
{Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"},
66+
},
67+
ChildModules: []*tfjson.StateModule{
68+
{
69+
Resources: []*tfjson.StateResource{
70+
{Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"},
71+
{Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"},
72+
},
73+
Address: "child-module-1",
74+
},
75+
},
76+
Address: "fake-module",
77+
},
78+
expected: &tfjson.StateModule{
79+
Resources: []*tfjson.StateResource{
80+
{Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"},
81+
{Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"},
82+
},
83+
ChildModules: []*tfjson.StateModule{
84+
{
85+
Resources: []*tfjson.StateResource{
86+
{Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"},
87+
{Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"},
88+
},
89+
Address: "child-module-1",
90+
},
91+
},
92+
Address: "fake-module",
93+
},
94+
},
95+
{
96+
name: "only non-data resources",
97+
stateMod: &tfjson.StateModule{
98+
Resources: []*tfjson.StateResource{
99+
{Name: "cat", Type: "coder_parameter", Mode: "foobar", Address: "cat-address"},
100+
{Name: "cow", Type: "foobaz", Mode: "foo", Address: "cow-address"},
101+
},
102+
ChildModules: []*tfjson.StateModule{
103+
{
104+
Resources: []*tfjson.StateResource{
105+
{Name: "child-cat", Type: "coder_parameter", Mode: "foobar", Address: "child-cat-address"},
106+
{Name: "child-dog", Type: "foobar", Mode: "foobaz", Address: "child-dog-address"},
107+
},
108+
Address: "child-module-1",
109+
},
110+
},
111+
Address: "fake-module",
112+
},
113+
expected: &tfjson.StateModule{
114+
Address: "fake-module",
115+
ChildModules: []*tfjson.StateModule{
116+
{Address: "child-module-1"},
117+
},
118+
},
119+
},
120+
{
121+
name: "mixed resources",
122+
stateMod: &tfjson.StateModule{
123+
Resources: []*tfjson.StateResource{
124+
{Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"},
125+
{Name: "dog", Type: "foobar", Mode: "magic", Address: "dog-address"},
126+
{Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"},
127+
},
128+
ChildModules: []*tfjson.StateModule{
129+
{
130+
Resources: []*tfjson.StateResource{
131+
{Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"},
132+
{Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"},
133+
{Name: "child-cow", Type: "foobaz", Mode: "magic", Address: "child-cow-address"},
134+
},
135+
Address: "child-module-1",
136+
},
137+
},
138+
Address: "fake-module",
139+
},
140+
expected: &tfjson.StateModule{
141+
Resources: []*tfjson.StateResource{
142+
{Name: "cat", Type: "coder_parameter", Mode: "data", Address: "cat-address"},
143+
{Name: "cow", Type: "foobaz", Mode: "data", Address: "cow-address"},
144+
},
145+
ChildModules: []*tfjson.StateModule{
146+
{
147+
Resources: []*tfjson.StateResource{
148+
{Name: "child-cat", Type: "coder_parameter", Mode: "data", Address: "child-cat-address"},
149+
{Name: "child-dog", Type: "foobar", Mode: "data", Address: "child-dog-address"},
150+
},
151+
Address: "child-module-1",
152+
},
153+
},
154+
Address: "fake-module",
155+
},
156+
},
157+
}
158+
159+
for _, tt := range tests {
160+
tt := tt
161+
162+
t.Run(tt.name, func(t *testing.T) {
163+
t.Parallel()
164+
165+
filtered := onlyDataResources(*tt.stateMod)
166+
167+
expected, err := json.Marshal(tt.expected)
168+
require.NoError(t, err)
169+
got, err := json.Marshal(filtered)
170+
require.NoError(t, err)
171+
172+
require.Equal(t, string(expected), string(got))
173+
})
174+
}
175+
}

0 commit comments

Comments
 (0)