Skip to content

Commit b638d2f

Browse files
authored
Add support for Terraform v1.10 (#2178)
* Bump tflint-plugin-sdk to v0.22.0 * Add `ephemeralasnull` function Follow up of hashicorp/terraform#35363 Follow up of hashicorp/terraform#35652 * Introduce ephemeral input variables Follow up of hashicorp/terraform#35273 Follow up of hashicorp/terraform#35985 Terraform throws an error if you use ephemeral values for the count meta-argument, but TFLint does not. This is because the reason for throwing an error is that plan cannot have ephemeral values, which is not an issue in the context of static analysis. In the future, we can throw an error if we need to match this behavior. * Functions that allow marks must also deal with unknown values Follow up of hashicorp/terraform#35985 * Add `terraform.applying` symbol Follow up of hashicorp/terraform@7c928fc * Introduce ephemeral resources Follow up of hashicorp/terraform#35727 Follow up of hashicorp/terraform#35728 Ephemeral resource addresses are like resources in that they always resolve to unknown values, but they differ in that they are marked as ephemeral, which can have a subtle effect on the return value of the ephemeralasnull function. * `issensitive` must return unknown for unknown args without `sensitive` Follow up of hashicorp/terraform#36012 * Fix `templatefile` function for unknown/marked values Follow up of hashicorp/terraform#36118 Follow up of hashicorp/terraform#36127 * Update collections to use for-range method Follow up of hashicorp/terraform#35818 * Include context when variable default has nested problem Follow up of hashicorp/terraform#35465 * Allow marked values in dynamic block `for_each` Follow up of hashicorp/hcl#679 Previously, for_each in dynamic blocks did not allow marked values such as sensitive. However, hashicorp/hcl#679 now supports this by propagating the marks to expanded children. The reason behind this is to add a new mark called "ephemeral", so we'll pull the changes to support Terraform 1.10. Note that tfhcl's dynamic block support has incomplete mark propagation since marked values resolve to unknown values. This is because in the past the marked values could not be sent over the wire protocol, and may be fixed in the near future. * Do not return ephemeral values to unsupported plugins Because ephemeral values are likely to contain secrets, return ErrSensitive for plugins that do not support it to prevent unintended disclosure. * Add E2E tests for ephemeral values and marked dynamic blocks * Update Terraform compatibility guide
1 parent 0686ef9 commit b638d2f

40 files changed

+1126
-222
lines changed

docs/developer-guide/api_compatibility.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ TFLint version: v0.42.0+
1111
- https://github.com/terraform-linters/tflint/pull/1722
1212
- https://github.com/terraform-linters/tflint-plugin-sdk/pull/235
1313
- https://github.com/terraform-linters/tflint-plugin-sdk/pull/239
14+
- Ephemeral value is introduced in SDK v0.22.0 and TFLint v0.55.0. TFLint returns ErrSensitive instead of ephemeral values to plugins built with SDK v0.21.0.
15+
- https://github.com/terraform-linters/tflint/pull/2178
16+
- https://github.com/terraform-linters/tflint-plugin-sdk/pull/358

docs/user-guide/compatibility.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ TFLint interprets the [Terraform language](https://developer.hashicorp.com/terra
44

55
The parser supports Terraform v1.x syntax and semantics. The language compatibility on Terraform v1.x is defined by [Compatibility Promises](https://developer.hashicorp.com/terraform/language/v1-compatibility-promises). TFLint follows this promise. New features are only supported in newer TFLint versions, and bug and experimental features compatibility are not guaranteed.
66

7-
The latest supported version is Terraform v1.9.
7+
The latest supported version is Terraform v1.10.
88

99
## Input Variables
1010

@@ -32,7 +32,7 @@ resource "aws_instance" "foo" {
3232
}
3333
```
3434

35-
Sensitive variables are ignored. This is to avoid unintended disclosure.
35+
Sensitive or ephemeral variables are ignored. This is to avoid unintended disclosure.
3636

3737
```hcl
3838
variable "instance_type" {
@@ -101,7 +101,7 @@ resource "aws_instance" "foo" {
101101
}
102102
```
103103

104-
## The `path.*` and `terraform.workspace` Values
104+
## The `path.*` and `terraform.*` Values
105105

106106
TFLint supports [filesystem and workspace info](https://developer.hashicorp.com/terraform/language/expressions/references#filesystem-and-workspace-info).
107107

@@ -110,14 +110,20 @@ TFLint supports [filesystem and workspace info](https://developer.hashicorp.com/
110110
- `path.cwd`
111111
- `terraform.workspace`.
112112

113+
The [`terraform.applying`](https://developer.hashicorp.com/terraform/language/functions/terraform-applying) always resolves to false.
114+
113115
## Unsupported Named Values
114116

115-
The values below are state-dependent and cannot be determined statically, so TFLint resolves them to unknown values.
117+
The values below are state-dependent or cannot be determined statically, so TFLint resolves them to unknown values.
116118

117119
- `<RESOURCE TYPE>.<NAME>`
120+
- `resource.<RESOURCE TYPE>.<NAME>`
121+
- `ephemeral.<RESOURCE TYPE>.<NAME>`
118122
- `module.<MODULE NAME>`
119123
- `data.<DATA TYPE>.<NAME>`
120-
- `self`
124+
- `self.<NAME>`
125+
126+
The `ephemeral.<RESOURCE TYPE>.<NAME>` always resolves to an unknown value marked as ephemeral, which is the same in most cases as anything else, but some rules may treat it differently.
121127

122128
## Functions
123129

@@ -143,7 +149,9 @@ resource "aws_instance" "dynamic" {
143149
}
144150
```
145151

146-
Similar to support for meta-arguments, some rules may process a dynamic block as-is without expansion. If the `for_each` is unknown, the block will be empty.
152+
Similar to support for meta-arguments, some rules may process a dynamic block as-is without expansion.
153+
154+
If the `for_each` is unknown, the expanded block will be empty. If the `for_each` is sensitive or ephemeral, TFLint expands dynamic blocks like Terraform does, but the mark does not propagate to children and expressions containing iterators resolve to unknown. This is a backwards compatibility limitation that may be resolved in a future version.
147155

148156
## Modules
149157

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ require (
2525
github.com/sourcegraph/go-lsp v0.0.0-20200429204803-219e11d77f5d
2626
github.com/sourcegraph/jsonrpc2 v0.2.0
2727
github.com/spf13/afero v1.11.0
28-
github.com/terraform-linters/tflint-plugin-sdk v0.21.0
28+
github.com/terraform-linters/tflint-plugin-sdk v0.22.0
2929
github.com/terraform-linters/tflint-ruleset-terraform v0.10.0
3030
github.com/xeipuuv/gojsonschema v1.2.0
3131
github.com/zclconf/go-cty v1.16.0
3232
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940
3333
github.com/zclconf/go-cty-yaml v1.1.0
3434
golang.org/x/crypto v0.32.0
35-
golang.org/x/net v0.33.0
35+
golang.org/x/net v0.34.0
3636
golang.org/x/oauth2 v0.25.0
3737
golang.org/x/text v0.21.0
3838
google.golang.org/grpc v1.69.2
@@ -139,17 +139,17 @@ require (
139139
go.uber.org/multierr v1.11.0 // indirect
140140
go.uber.org/zap v1.27.0 // indirect
141141
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
142-
golang.org/x/mod v0.20.0 // indirect
142+
golang.org/x/mod v0.22.0 // indirect
143143
golang.org/x/sync v0.10.0 // indirect
144144
golang.org/x/sys v0.29.0 // indirect
145145
golang.org/x/term v0.28.0 // indirect
146146
golang.org/x/time v0.5.0 // indirect
147-
golang.org/x/tools v0.23.0 // indirect
147+
golang.org/x/tools v0.29.0 // indirect
148148
google.golang.org/api v0.172.0 // indirect
149149
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect
150150
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
151151
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
152-
google.golang.org/protobuf v1.35.1 // indirect
152+
google.golang.org/protobuf v1.36.2 // indirect
153153
gopkg.in/ini.v1 v1.67.0 // indirect
154154
gopkg.in/yaml.v3 v3.0.1 // indirect
155155
k8s.io/klog/v2 v2.120.1 // indirect

go.sum

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
696696
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
697697
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
698698
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
699-
github.com/terraform-linters/tflint-plugin-sdk v0.21.0 h1:RoorxuuWh1RuL09PWAmaCKw/hmb9QP5dukGXZiB0fs8=
700-
github.com/terraform-linters/tflint-plugin-sdk v0.21.0/go.mod h1:f7ruoYh44RQvnZRxpWhn8JFkpEVlQFT8wC9MhIF0Rp4=
699+
github.com/terraform-linters/tflint-plugin-sdk v0.22.0 h1:holOVJW0hjf0wkjtnYyPWRooQNp8ETUcKE86rdYkH5U=
700+
github.com/terraform-linters/tflint-plugin-sdk v0.22.0/go.mod h1:Cag3YJjBpHdQzI/limZR+Cj7WYPLTIE61xsCdIXoeUI=
701701
github.com/terraform-linters/tflint-ruleset-terraform v0.10.0 h1:L+3K3oGvZe5UdQ9F6PMQ6n69A2+Q11dBSg+5nTvxJi8=
702702
github.com/terraform-linters/tflint-ruleset-terraform v0.10.0/go.mod h1:wT8nMRBpCg1cIL0Td3LQ3XPcnTTHwBhbCNrFp4jWFrI=
703703
github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI=
@@ -818,8 +818,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
818818
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
819819
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
820820
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
821-
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
822-
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
821+
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
822+
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
823823
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
824824
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
825825
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -867,8 +867,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
867867
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
868868
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
869869
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
870-
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
871-
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
870+
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
871+
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
872872
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
873873
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
874874
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1055,8 +1055,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
10551055
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
10561056
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
10571057
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
1058-
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
1059-
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
1058+
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
1059+
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
10601060
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
10611061
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
10621062
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1284,8 +1284,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
12841284
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
12851285
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
12861286
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
1287-
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
1288-
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
1287+
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
1288+
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
12891289
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12901290
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12911291
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

integrationtest/inspection/inspection_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ func TestIntegration(t *testing.T) {
181181
Dir: "eval-on-root-context",
182182
},
183183
{
184-
Name: "sensitive variable",
184+
Name: "marked values",
185185
Command: "tflint --format json",
186-
Dir: "sensitive",
186+
Dir: "marked",
187187
},
188188
{
189189
Name: "just attributes",
File renamed without changes.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
variable "no_marked" {
2+
default = "t2.micro"
3+
}
4+
5+
variable "sensitive" {
6+
sensitive = true
7+
default = "t2.micro"
8+
}
9+
10+
variable "ephemeral" {
11+
ephemeral = true
12+
default = "t2.micro"
13+
}
14+
15+
variable "marked_set" {
16+
sensitive = true
17+
default = [true]
18+
}
19+
20+
resource "aws_instance" "no_marked" {
21+
instance_type = var.no_marked
22+
}
23+
24+
resource "aws_instance" "sensitive" {
25+
instance_type = var.sensitive
26+
}
27+
28+
resource "aws_instance" "ephemeral" {
29+
instance_type = var.ephemeral
30+
}
31+
32+
resource "aws_s3_bucket" "main" {
33+
dynamic "lifecycle_rule" {
34+
for_each = var.marked_set
35+
36+
content {
37+
enabled = lifecycle_rule.value
38+
}
39+
}
40+
41+
dynamic "lifecycle_rule" {
42+
for_each = var.marked_set
43+
44+
content {
45+
enabled = true
46+
}
47+
}
48+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{
2+
"issues": [
3+
{
4+
"rule": {
5+
"name": "aws_instance_example_type",
6+
"severity": "error",
7+
"link": ""
8+
},
9+
"message": "instance type is t2.micro",
10+
"range": {
11+
"filename": "main.tf",
12+
"start": {
13+
"line": 21,
14+
"column": 19
15+
},
16+
"end": {
17+
"line": 21,
18+
"column": 32
19+
}
20+
},
21+
"callers": []
22+
},
23+
{
24+
"rule": {
25+
"name": "aws_s3_bucket_example_lifecycle_rule",
26+
"severity": "error",
27+
"link": ""
28+
},
29+
"message": "`lifecycle_rule` block found",
30+
"range": {
31+
"filename": "main.tf",
32+
"start": {
33+
"line": 33,
34+
"column": 3
35+
},
36+
"end": {
37+
"line": 33,
38+
"column": 27
39+
}
40+
},
41+
"callers": []
42+
},
43+
{
44+
"rule": {
45+
"name": "aws_s3_bucket_example_lifecycle_rule",
46+
"severity": "error",
47+
"link": ""
48+
},
49+
"message": "`lifecycle_rule` block found",
50+
"range": {
51+
"filename": "main.tf",
52+
"start": {
53+
"line": 41,
54+
"column": 3
55+
},
56+
"end": {
57+
"line": 41,
58+
"column": 27
59+
}
60+
},
61+
"callers": []
62+
},
63+
{
64+
"rule": {
65+
"name": "aws_s3_bucket_example_lifecycle_rule",
66+
"severity": "error",
67+
"link": ""
68+
},
69+
"message": "`enabled` attribute found: true",
70+
"range": {
71+
"filename": "main.tf",
72+
"start": {
73+
"line": 45,
74+
"column": 17
75+
},
76+
"end": {
77+
"line": 45,
78+
"column": 21
79+
}
80+
},
81+
"callers": []
82+
}
83+
],
84+
"errors": []
85+
}

integrationtest/inspection/sensitive/main.tf

Lines changed: 0 additions & 17 deletions
This file was deleted.

integrationtest/inspection/sensitive/result.json

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)