Skip to content

Commit

Permalink
Merge branch 'release/v0.3.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
rucciva committed Nov 11, 2020
2 parents 443394e + d16cf6b commit 53092b8
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 30 deletions.
14 changes: 8 additions & 6 deletions docs/resources/script.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# linux_script

Manage arbritrary resource by specifying commands that will be executed remotely.
Manage arbritrary resource by specifying commands that will be uploaded and executed remotely.

## Example Usage

Expand Down Expand Up @@ -32,16 +32,18 @@ The following arguments are supported:

### lifecycle_commands

Block that contains commands to be remotely executed respective to terraform's **Create**,**Read**,**Update**, and **Delete** phase. For complex commands, use [the file function](https://www.terraform.io/docs/configuration/functions/file.html). The following arguments are supported:
Block that contains commands to be uploaded and remotely executed respective to the terraform's [**Create**, **Read**, **Update**, and **Delete** phase](https://learn.hashicorp.com/tutorials/terraform/provider-use?in=terraform/providers). For complex commands, use [the file function](https://www.terraform.io/docs/configuration/functions/file.html). The following arguments are supported:

- `create` - (Required, string) Commands that will be executed in **Create** phase.
- `read` - (Required, string) Commands that will be executed in **Read** phase and after execution of `create` or `update` commands. Terraform will record the output of these commands inside `output` attributes and trigger update/recreation when it changes (in **Read** phase only). If the result of running these commands produce an error, then it will give a signal for resource recreation. In this scenario, user have three options before applying the changes: (1) do nothing since the resource has indeed become absent, (2) manually modifying the linux machine so no error will be produced in the next run, (3) update the commands. It is recommended that this operations does not do any kind of 'write' operation.
- `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.
- `read` - (Required, string) Commands that will be executed in **Read** phase and after execution of `create` or `update` commands. Terraform will record the output of these commands inside `output` attributes and trigger update/recreation when it changes (in **Read** phase only). If the result of running these commands instead produce an error, then it will give a signal for resource recreation. In this scenario, user have three options before applying the changes: (1) do nothing and apply the changes since the resource has indeed become absent, (2) manually modifying the linux machine so no error will be produced in the next run, or (3) update the commands. If (1) is choosen then `delete` script will not be executed in **Delete** phases. It is recommended that this operations does not do any kind of 'write' operation or at least safe to be retried.
- `update` - (Optional, string) Commands that will be executed in **Update** phase. The previous `output` are accessible from stdin. Omiting this will trigger resource recreation (**Delete** -> **Create**) each time terraform detect changes.
- `delete` - (Required, string) Commands that will be executed in **Delete** phase.

### Resource Update
### Updating Resource

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.
This resource is somewhat differ from regular terraform resource because the state does not only consist of information about the actual resource, but also the instructions to CRUD the resource. Among these arguments, `lifecycle_commands` and `interpreter` are considered as instructions while the rest are considered as the actual data. A special course of actions must be taken when these arguments are updated, or else user would get undesired behavior such as `update` command being executed when updating only the `delete` commands.

As such, if `lifecycle_commands` and/or `interpreter` are updated, then no commands will be executed--except for the current `read` commands using the existing `interpreter`, where the outcomes will be ignored--. At the same time, no changes to other arguments are allowed, or else an error will be thrown. When successfully updated through `terraform apply`, the next terraform execution will use these new instructions and update to other arguments are allowed.

## Attribute Reference

Expand Down
11 changes: 7 additions & 4 deletions linux/script-resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ func (h handlerScriptResource) Create(ctx context.Context, rd *schema.ResourceDa
return diag.FromErr(err)
}

if err := h.read(ctx, rd, l); err != nil {
return diag.FromErr(err)
}

id, err := uuid.NewRandom()
if err != nil {
return diag.FromErr(err)
}
rd.SetId(id.String())

if err := h.read(ctx, rd, l); err != nil {
return diag.FromErr(err)
}
return
}

Expand Down Expand Up @@ -285,6 +285,9 @@ func (h handlerScriptResource) Update(ctx context.Context, rd *schema.ResourceDa
}

func (h handlerScriptResource) Delete(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) {
if cast.ToBool(rd.Get(attrScriptReadFailed)) {
return
}
l := meta.(*linux)
sc := h.newScript(rd, l, attrScriptLifecycleCommandDelete)
if _, err := sc.exec(ctx); err != nil {
Expand Down
32 changes: 12 additions & 20 deletions linux/script-resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,16 @@ func TestAccLinuxScriptNoUpdate(t *testing.T) {
"Version": "1.0.0",
},
}
conf2 := tfConf{
Provider: testAccProvider,
Script: conf1.Script.Copy(),
Extra: conf1.Extra.Copy().With("Version", "2.0.0"),
}
conf3 := tfConf{
Provider: testAccProvider,
Script: tfScript{
Environment: conf2.Script.Environment.Copy().With("FILE", fmt.Sprintf(`"/tmp/linux1/%s"`, acctest.RandString(16))),
},
Extra: conf2.Extra.Copy(),
}
conf4 := tfConf{
Provider: testAccProvider,
Script: conf2.Script.Copy(),
Extra: conf2.Extra.Copy().With("Taint", `\n`),
}
conf2 := conf1.Copy(func(tc *tfConf) {
tc.Extra.With("Version", "2.0.0")
})
conf3 := conf2.Copy(func(tc *tfConf) {
tc.Script.Environment.
With("FILE", fmt.Sprintf(`"/tmp/linux1/%s"`, acctest.RandString(16)))
})
conf4 := conf2.Copy(func(tc *tfConf) {
tc.Extra.With("Taint", `\n`)
})

resource.Test(t, resource.TestCase{
ExternalProviders: map[string]resource.ExternalProvider{"null": {}},
Expand Down Expand Up @@ -434,7 +427,7 @@ func TestAccLinuxScriptFailedRead(t *testing.T) {
attrScriptLifecycleCommandCreate: `"echo -n $CONTENT > $FILE"`,
attrScriptLifecycleCommandRead: `"cat $FILE"`,
attrScriptLifecycleCommandUpdate: `"echo -n '\n'$CONTENT >> $FILE"`,
attrScriptLifecycleCommandDelete: `"rm $FILE || true"`,
attrScriptLifecycleCommandDelete: `"rm $FILE"`,
},
Environment: tfmap{
"FILE": `"/tmp/linux-test"`,
Expand All @@ -452,8 +445,7 @@ func TestAccLinuxScriptFailedRead(t *testing.T) {
scriptUpdatedWithOtherArguments := createFile.Copy(func(tc *tfConf) {
tc.Extra.Without("ShouldDelete")
tc.Script.LifecycleCommands.
With(attrScriptLifecycleCommandRead, `"cat $FILE || echo"`).
With(attrScriptLifecycleCommandDelete, `"rm $FILE"`)
With(attrScriptLifecycleCommandRead, `"cat $FILE || echo"`)
tc.Script.Environment.With("CONTENT", `"test2"`)
})
scriptUpdated := scriptUpdatedWithOtherArguments.Copy(func(tc *tfConf) {
Expand Down

0 comments on commit 53092b8

Please sign in to comment.