Skip to content

Commit 443394e

Browse files
committed
Merge branch 'release/v0.3.5'
2 parents aeff111 + c8b295b commit 443394e

File tree

4 files changed

+52
-37
lines changed

4 files changed

+52
-37
lines changed

docs/resources/script.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ resource "linux_script" "install_package" {
2424
The following arguments are supported:
2525

2626
- `lifecycle_commands` - (Required) see [lifecycle_commands](#lifecycle_commands).
27-
- `triggers` - (Optional, string map) Attribute that will trigger resource recreation on changes just like the one in [null_resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource#triggers). Default empty map.
28-
- `environment` - (Optional, string map) A list of linux environment that will be available in each `lifecycle_commands`. Default empty map.
29-
- `sensitive_environment` - (Optional, string map) Just like `environment` except they don't show up in log files. In case of duplication, environment variables defined here will take precedence over the ones in `environment`. Default empty map.
3027
- `interpreter` - (Optional, string list) Interpreter for running each `lifecycle_commands`. Default empty list.
3128
- `working_directory` - (Optional, string) The working directory where each `lifecycle_commands` is executed. Default empty string.
29+
- `environment` - (Optional, string map) A list of linux environment that will be available in each `lifecycle_commands`. Default empty map.
30+
- `sensitive_environment` - (Optional, string map) Just like `environment` except they don't show up in log files. In case of duplication, environment variables defined here will take precedence over the ones in `environment`. Default empty map.
31+
- `triggers` - (Optional, string map) Attribute that will trigger resource recreation on changes just like the one in [null_resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource#triggers). Default empty map.
3232

3333
### lifecycle_commands
3434

@@ -39,7 +39,9 @@ Block that contains commands to be remotely executed respective to terraform's *
3939
- `update` - (Optional, string) Commands that will be executed in **Update** phase. Previous `output` are accessible from stdin. Omiting this will trigger resource recreation (**Delete** -> **Create**) each time terraform detect changes.
4040
- `delete` - (Required, string) Commands that will be executed in **Delete** phase.
4141

42-
When any of the commands is updated, then nothing will be executed (except for the current `read` commands since it will always be executed before changes are detected). This is to mimic the behavior of an updated provider's logic, that is no previous logics will be executed. If at the same time another arguments is updated, then error will be thrown.
42+
### Resource Update
43+
44+
When any of the `lifecycle_commands` and/or `interpreter` are updated, then nothing will be executed (except for the current `read` commands with existing `interpreter` since it will always be executed before changes are detected). This is to mimic the behavior of an updated provider's instructions, where no previous instructions are executed. Changes to these two arguments must not be followed with changes to other arguments at the same time, or else an error will be thrown.
4345

4446
## Attribute Reference
4547

linux/script-resource.go

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import (
1313
"github.com/spf13/cast"
1414
)
1515

16+
type haschange interface {
17+
HasChange(key string) bool
18+
}
19+
1620
const (
1721
attrScriptLifecycleCommands = "lifecycle_commands"
1822
attrScriptLifecycleCommandCreate = "create"
@@ -107,16 +111,19 @@ var schemaScriptResource = map[string]*schema.Schema{
107111
},
108112
}
109113

110-
type handlerScriptResource struct{}
114+
type handlerScriptResource struct {
115+
}
111116

112117
func (h handlerScriptResource) attrCommands() map[string]bool {
113-
return map[string]bool{attrScriptLifecycleCommands: true}
118+
return map[string]bool{
119+
attrScriptLifecycleCommands: true,
120+
attrScriptInterpreter: true,
121+
}
114122
}
115123
func (h handlerScriptResource) attrInputs() map[string]bool {
116124
return map[string]bool{
117125
attrScriptEnvironment: true,
118126
attrScriptSensitiveEnvironment: true,
119-
attrScriptInterpreter: true,
120127
attrScriptWorkingDirectory: true,
121128
}
122129
}
@@ -147,6 +154,21 @@ func (h handlerScriptResource) attrs() (m map[string]bool) {
147154
return
148155
}
149156

157+
func (h handlerScriptResource) changed(rd haschange, attrs map[string]bool) (changed []string) {
158+
for k := range attrs {
159+
if rd.HasChange(k) {
160+
changed = append(changed, k)
161+
}
162+
}
163+
return
164+
}
165+
func (h handlerScriptResource) changedAttrInputs(rd haschange) (changed []string) {
166+
return h.changed(rd, h.attrInputs())
167+
}
168+
func (h handlerScriptResource) changedAttrCommands(rd haschange) (changed []string) {
169+
return h.changed(rd, h.attrCommands())
170+
}
171+
150172
func (h handlerScriptResource) newScript(rd *schema.ResourceData, l *linux, attrLifeCycle string) (s *script) {
151173
if rd == nil {
152174
return
@@ -183,8 +205,7 @@ func (h handlerScriptResource) Read(ctx context.Context, rd *schema.ResourceData
183205
old := cast.ToString(rd.Get(attrScriptOutput))
184206

185207
err := h.read(ctx, rd, meta.(*linux))
186-
var errExit *remote.ExitError
187-
switch {
208+
switch errExit := (*remote.ExitError)(nil); {
188209
case errors.As(err, &errExit):
189210
_ = rd.Set(attrScriptReadFailed, true)
190211
_ = rd.Set(attrScriptReadError, err.Error())
@@ -225,14 +246,9 @@ func (h handlerScriptResource) Create(ctx context.Context, rd *schema.ResourceDa
225246
}
226247

227248
// WARN: see https://github.com/hashicorp/terraform-plugin-sdk/issues/476
228-
func (h handlerScriptResource) restoreOldResourceData(rd *schema.ResourceData, except ...string) (err error) {
229-
var exceptMap = map[string]bool{}
230-
for _, k := range except {
231-
exceptMap[k] = true
232-
}
233-
249+
func (h handlerScriptResource) restoreOldResourceData(rd *schema.ResourceData, except map[string]bool) (err error) {
234250
for k := range h.attrs() {
235-
if exceptMap[k] {
251+
if except != nil && except[k] {
236252
continue
237253
}
238254
o, _ := rd.GetChange(k)
@@ -245,11 +261,11 @@ func (h handlerScriptResource) restoreOldResourceData(rd *schema.ResourceData, e
245261
}
246262

247263
func (h handlerScriptResource) Update(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) {
248-
if rd.HasChange(attrScriptLifecycleCommands) {
264+
if len(h.changedAttrCommands(rd)) > 0 {
249265
// mimic the behaviour when terraform provider is updated,
250266
// that is no old logic are executed and
251267
// the new logic are run with the existing state and diff
252-
_ = h.restoreOldResourceData(rd, attrScriptLifecycleCommands)
268+
_ = h.restoreOldResourceData(rd, h.attrCommands())
253269
return
254270
}
255271

@@ -258,7 +274,7 @@ func (h handlerScriptResource) Update(ctx context.Context, rd *schema.ResourceDa
258274
oldOutput := cast.ToString(rd.Get(attrScriptOutput))
259275
sc.stdin = strings.NewReader(oldOutput)
260276
if _, err := sc.exec(ctx); err != nil {
261-
_ = h.restoreOldResourceData(rd)
277+
_ = h.restoreOldResourceData(rd, nil)
262278
return diag.FromErr(err)
263279
}
264280

@@ -282,15 +298,10 @@ func (h handlerScriptResource) CustomizeDiff(c context.Context, rd *schema.Resou
282298
return // no state
283299
}
284300

285-
if rd.HasChange(attrScriptLifecycleCommands) {
286-
var forbidden []string
287-
for key := range h.attrInputs() {
288-
if rd.HasChange(key) {
289-
forbidden = append(forbidden, key)
290-
}
291-
}
292-
if len(forbidden) > 0 {
293-
return fmt.Errorf("update to `%s` should not be combined with update to other arguments: %s", attrScriptLifecycleCommands, strings.Join(forbidden, ","))
301+
if cmd := h.changedAttrCommands(rd); len(cmd) > 0 {
302+
if fbd := h.changedAttrInputs(rd); len(fbd) > 0 {
303+
return fmt.Errorf("update to '%s' should not be combined with update to other arguments: %s",
304+
strings.Join(cmd, ","), strings.Join(fbd, ","))
294305
}
295306
return // updated commands. let Update handle it.
296307
}
@@ -314,8 +325,6 @@ func (h handlerScriptResource) CustomizeDiff(c context.Context, rd *schema.Resou
314325
case strings.HasPrefix(key, attrScriptEnvironment):
315326
fallthrough
316327
case strings.HasPrefix(key, attrScriptSensitiveEnvironment):
317-
fallthrough
318-
case strings.HasPrefix(key, attrScriptInterpreter):
319328
parts := strings.Split(key, ".")
320329
key = strings.Join(parts[:len(parts)-1], ".")
321330
}

linux/script-resource_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ func TestAccLinuxScriptBasic(t *testing.T) {
2727
},
2828
},
2929
}
30-
conf2 := tfConf{
31-
Provider: testAccProvider,
32-
Script: conf1.Script.Copy(),
33-
}
34-
conf2.Script.Environment = conf2.Script.Environment.With("FILE", fmt.Sprintf(`"/tmp/linux/%s"`, acctest.RandString(16)))
30+
conf2 := conf1.Copy(func(tc *tfConf) {
31+
tc.Script.Environment.With("FILE", fmt.Sprintf(`"/tmp/linux/%s"`, acctest.RandString(16)))
32+
})
3533

3634
resource.Test(t, resource.TestCase{
3735
ExternalProviders: map[string]resource.ExternalProvider{"null": {}},
@@ -352,6 +350,9 @@ func TestAccLinuxScriptUpdatedScript(t *testing.T) {
352350
UpdateFilePt2 := UpdateFilePt1.Copy(func(tc *tfConf) {
353351
tc.Script.Environment = createFilePt2.Script.Environment.Copy().With("CONTENT", `"world1"`)
354352
})
353+
interpreterUpdated := UpdateFilePt2.Copy(func(tc *tfConf) {
354+
tc.Script.Interpreter = tfList{`"/bin/sh"`}
355+
})
355356

356357
resource.Test(t, resource.TestCase{
357358
PreCheck: testAccPreCheckConnection(t),
@@ -402,6 +403,10 @@ func TestAccLinuxScriptUpdatedScript(t *testing.T) {
402403
Config: testAccLinuxScriptUpdatedScriptConfig(t, UpdateFilePt2),
403404
Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world\nworld1"),
404405
},
406+
{
407+
Config: testAccLinuxScriptUpdatedScriptConfig(t, interpreterUpdated),
408+
Check: resource.TestCheckResourceAttr("linux_script.script", "output", "world\nworld1"),
409+
},
405410
},
406411
})
407412
}

linux/template_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ func tNewTFMapFile() tfmap {
8484
type tfList []string
8585

8686
func (l tfList) Copy() (c tfList) {
87-
copy(c, l)
88-
return
87+
return append(c, l...)
8988
}
9089

9190
func (l tfList) Serialize() (s string, err error) {

0 commit comments

Comments
 (0)