Skip to content

Commit 184d847

Browse files
committed
Merge branch 'release/v0.5.0'
2 parents 6c4dc8f + 83472b1 commit 184d847

File tree

11 files changed

+233
-18
lines changed

11 files changed

+233
-18
lines changed

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ resource "linux_file" "file" {
4444
recycle_path = "/tmp/recycle"
4545
}
4646
47+
48+
locals {
49+
package_name = "apache2"
50+
}
51+
4752
resource "linux_script" "install_package" {
4853
lifecycle_commands {
4954
create = "apt update && apt install -y $PACKAGE_NAME=$PACKAGE_VERSION"
@@ -52,9 +57,12 @@ resource "linux_script" "install_package" {
5257
delete = "apt remove -y $PACKAGE_NAME"
5358
}
5459
environment = {
55-
PACKAGE_NAME = "apache2"
60+
PACKAGE_NAME = local.package_name
5661
PACKAGE_VERSION = "2.4.18-2ubuntu3.4"
5762
}
63+
triggers = {
64+
PACKAGE_NAME = local.package_name"
65+
}
5866
}
5967
```
6068

docs/data-sources/script.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# linux_script
2+
3+
Read arbritrary resource by specifying commands that will be uploaded and executed remotely.
4+
5+
## Example Usage
6+
7+
```hcl
8+
locals {
9+
package_name = "apache2"
10+
}
11+
resource "linux_script" "install_package" {
12+
lifecycle_commands {
13+
read = "apt-cache policy $PACKAGE_NAME | grep 'Installed:' | grep -v '(none)' | awk '{ print $2 }' | xargs | tr -d '\n'"
14+
}
15+
environment = {
16+
PACKAGE_NAME = local.package_name
17+
PACKAGE_VERSION = "2.4.18-2ubuntu3.4"
18+
}
19+
}
20+
```
21+
22+
## Argument Reference
23+
24+
The following arguments are supported:
25+
26+
- `lifecycle_commands` - (Required) see [lifecycle_commands](#lifecycle_commands).
27+
- `interpreter` - (Optional, string list) Interpreter for running each `lifecycle_commands`. Default empty list.
28+
- `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+
32+
### lifecycle_commands
33+
34+
Block that contains commands to be uploaded and remotely executed in Terraform.
35+
36+
- `read` - (Required, string) Commands that will be executed to obtain data regarding the arbritrary resource. Terraform will record the output of these commands inside `output` attributes.
37+
38+
## Attribute Reference
39+
40+
- `output` - (string) The raw output of `read` commands.

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ require (
77
github.com/Masterminds/goutils v1.1.0 // indirect
88
github.com/Masterminds/semver v1.5.0 // indirect
99
github.com/Masterminds/sprig v2.22.0+incompatible
10-
github.com/alessio/shellescape v1.3.0
10+
github.com/alessio/shellescape v1.3.1
1111
github.com/google/uuid v1.1.2
1212
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
1313
github.com/hashicorp/terraform v0.13.5
14-
github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0
14+
github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0
1515
github.com/huandu/xstrings v1.3.2 // indirect
1616
github.com/spf13/cast v1.3.1
1717
github.com/stretchr/testify v1.6.1
1818
go.uber.org/zap v1.16.0
19-
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102
19+
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
2020
)
2121

2222
replace github.com/hashicorp/terraform => ./internal/workaround/hashicorp/terraform

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBb
5252
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
5353
github.com/alessio/shellescape v1.3.0 h1:rlgsKOIa8j5fkSs7uqjlU2FkIdhuJWSQC1rQQybVD54=
5454
github.com/alessio/shellescape v1.3.0/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
55+
github.com/alessio/shellescape v1.3.1 h1:cY65176tt6U1YAH9JsxT1DyXdluB2NTR8aiZFaFUXxs=
56+
github.com/alessio/shellescape v1.3.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
5557
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
5658
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
5759
github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
@@ -209,6 +211,8 @@ github.com/hashicorp/terraform-plugin-go v0.1.0 h1:kyXZ0nkHxiRev/q18N40IbRRk4AV0
209211
github.com/hashicorp/terraform-plugin-go v0.1.0/go.mod h1:10V6F3taeDWVAoLlkmArKttR3IULlRWFAGtQIQTIDr4=
210212
github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0 h1:2m4uKA97R8ijHGLwhHdpSJyI8Op1FpS/ozpoF21jK7s=
211213
github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0/go.mod h1:+12dJQebYjuU/yiq94iZUPuC66abfRBrXdpVJia3ojk=
214+
github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0 h1:Egv+R1tOOjPNz643KBTx3tLT6RdFGGYJcZlyLvrPcEU=
215+
github.com/hashicorp/terraform-plugin-sdk/v2 v2.3.0/go.mod h1:+12dJQebYjuU/yiq94iZUPuC66abfRBrXdpVJia3ojk=
212216
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
213217
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
214218
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
@@ -402,6 +406,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN
402406
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
403407
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
404408
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
409+
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
410+
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
405411
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
406412
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
407413
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

linux/directory-resource.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package linux
33
import (
44
"context"
55
"errors"
6+
"regexp"
67

78
"github.com/google/uuid"
89
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1012
"github.com/spf13/cast"
1113
)
1214

@@ -36,9 +38,10 @@ var schemaDirectoryResource = map[string]*schema.Schema{
3638
Default: 0,
3739
},
3840
attrDirectoryMode: {
39-
Type: schema.TypeString,
40-
Optional: true,
41-
Default: "755",
41+
Type: schema.TypeString,
42+
Optional: true,
43+
Default: "755",
44+
ValidateFunc: validation.StringMatch(regexp.MustCompile("[0-7]{3}"), "Invalid linux permission"),
4245
},
4346
attrDirectoryOverwrite: {
4447
Type: schema.TypeBool,

linux/file-resource.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package linux
33
import (
44
"context"
55
"errors"
6+
"regexp"
67

78
"github.com/google/uuid"
89
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1012
"github.com/spf13/cast"
1113
)
1214

@@ -45,9 +47,10 @@ var schemaFileResource = map[string]*schema.Schema{
4547
Default: 0,
4648
},
4749
attrFileMode: {
48-
Type: schema.TypeString,
49-
Optional: true,
50-
Default: "644",
50+
Type: schema.TypeString,
51+
Optional: true,
52+
Default: "644",
53+
ValidateFunc: validation.StringMatch(regexp.MustCompile("[0-7]{3}"), "Invalid linux permission"),
5154
},
5255
attrFileIgnoreContent: {
5356
Type: schema.TypeBool,

linux/provider.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ func Provider() *schema.Provider {
175175
}
176176
return l, diags
177177
},
178-
178+
DataSourcesMap: map[string]*schema.Resource{
179+
"linux_script": scriptDataSource(),
180+
},
179181
ResourcesMap: map[string]*schema.Resource{
180182
"linux_file": fileResource(),
181183
"linux_directory": directoryResource(),

linux/script-datasource.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package linux
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
)
9+
10+
var schemaScriptDataSource = func() (m map[string]*schema.Schema) {
11+
m = make(map[string]*schema.Schema)
12+
for k, v := range schemaScriptResource {
13+
switch k {
14+
default:
15+
m[k] = v
16+
17+
case attrScriptLifecycleCommands:
18+
m[k] = new(schema.Schema)
19+
*m[k] = *v
20+
m[k].Elem = &schema.Resource{
21+
Schema: map[string]*schema.Schema{
22+
attrScriptLifecycleCommandRead: v.Elem.(*schema.Resource).Schema[attrScriptLifecycleCommandRead],
23+
},
24+
}
25+
26+
case attrScriptTriggers:
27+
case attrScriptDirtyOutput:
28+
case attrScriptFaultyOutput:
29+
}
30+
}
31+
return
32+
}()
33+
34+
type handlerScriptDataSource struct {
35+
hsr handlerScriptResource
36+
}
37+
38+
func (h handlerScriptDataSource) Read(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) {
39+
err := h.hsr.read(ctx, rd, meta.(*linux))
40+
if err != nil {
41+
d = diag.FromErr(err)
42+
}
43+
rd.SetId("static")
44+
return
45+
}
46+
47+
func scriptDataSource() *schema.Resource {
48+
h := handlerScriptDataSource{hsr: handlerScriptResource{}}
49+
return &schema.Resource{
50+
Schema: schemaScriptDataSource,
51+
ReadContext: h.Read,
52+
}
53+
}

linux/script-datasource_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package linux
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
"testing"
8+
9+
"github.com/MakeNowJust/heredoc"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestAccLinuxDataScriptBasic(t *testing.T) {
16+
file := fmt.Sprintf(`"/tmp/linux-%s.yml"`, acctest.RandString(16))
17+
conf := tfConf{
18+
Provider: testAccProvider,
19+
Script: tfScript{
20+
Interpreter: tfList{`"sh"`, `"-c"`},
21+
LifecycleCommands: tfmap{
22+
attrScriptLifecycleCommandRead: `"cat $FILE"`,
23+
attrScriptLifecycleCommandCreate: `"echo -n $CONTENT > $FILE"`,
24+
attrScriptLifecycleCommandUpdate: `"echo -n $CONTENT > $FILE"`,
25+
attrScriptLifecycleCommandDelete: `"rm $FILE"`,
26+
},
27+
Environment: tfmap{
28+
"FILE": file,
29+
"CONTENT": `"helloworld"`,
30+
},
31+
},
32+
DataScript: tfScript{
33+
Interpreter: tfList{`"sh"`, `"-c"`},
34+
LifecycleCommands: tfmap{
35+
attrScriptLifecycleCommandRead: `"cat $FILE"`,
36+
},
37+
Environment: tfmap{
38+
"FILE": file,
39+
},
40+
},
41+
}
42+
failedScripte := conf.Copy(func(tc *tfConf) {
43+
tc.DataScript.LifecycleCommands.With(attrScriptLifecycleCommandRead, `"cat $FILE.notexist"`)
44+
})
45+
updatedContent := conf.Copy(func(tc *tfConf) {
46+
tc.Script.Environment.With("CONTENT", `"helloworld1"`)
47+
})
48+
49+
resource.Test(t, resource.TestCase{
50+
ExternalProviders: map[string]resource.ExternalProvider{"null": {}},
51+
PreCheck: testAccPreCheckConnection(t),
52+
Providers: testAccProviders,
53+
Steps: []resource.TestStep{
54+
{
55+
Config: testAccLinuxDataScriptBasicConfig(t, conf),
56+
Check: resource.ComposeAggregateTestCheckFunc(
57+
resource.TestCheckResourceAttr("null_resource.output", "triggers.output", strings.Trim(conf.Script.Environment["CONTENT"], `"`)),
58+
),
59+
},
60+
{
61+
Config: testAccLinuxDataScriptBasicConfig(t, failedScripte),
62+
ExpectError: regexp.MustCompile("No such file or directory"),
63+
},
64+
{
65+
Config: testAccLinuxDataScriptBasicConfig(t, updatedContent),
66+
Check: resource.ComposeAggregateTestCheckFunc(
67+
resource.TestCheckResourceAttr("null_resource.output", "triggers.output", strings.Trim(updatedContent.Script.Environment["CONTENT"], `"`)),
68+
),
69+
},
70+
},
71+
})
72+
}
73+
74+
func testAccLinuxDataScriptBasicConfig(t *testing.T, conf tfConf) (s string) {
75+
tf := heredoc.Doc(`
76+
provider "linux" {
77+
{{- .Provider.Serialize | nindent 4 }}
78+
}
79+
80+
resource "linux_script" "linux_script" {
81+
{{ .Script.Serialize | nindent 4 }}
82+
}
83+
84+
data "linux_script" "linux_script" {
85+
depends_on = [ linux_script.linux_script ]
86+
{{ .DataScript.Serialize | nindent 4 }}
87+
}
88+
89+
resource "null_resource" "output" {
90+
triggers = {
91+
output = data.linux_script.linux_script.output
92+
}
93+
}
94+
`)
95+
96+
s, err := conf.compile(tf)
97+
t.Log(s)
98+
require.NoError(t, err, "compile template failed")
99+
return
100+
}

linux/script-resource.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,6 @@ func (h handlerScriptResource) restoreOldResourceData(rd *schema.ResourceData, e
285285
}
286286

287287
func (h handlerScriptResource) UpdateCommands(ctx context.Context, rd *schema.ResourceData, meta interface{}) (d diag.Diagnostics) {
288-
_ = h.restoreOldResourceData(rd, h.attrs(h.attrCommands(), h.attrInternal())) // just to be sure
289-
290288
if rd.HasChange(attrScriptLifecycleCommands + ".0." + attrScriptLifecycleCommandRead) {
291289
err := h.read(ctx, rd, meta.(*linux))
292290
if err != nil {

0 commit comments

Comments
 (0)