Skip to content

Commit 6ace801

Browse files
authored
workspace_remote: Suppress issues in Terraform v1.1+ (#156)
1 parent a0d166d commit 6ace801

File tree

3 files changed

+120
-24
lines changed

3 files changed

+120
-24
lines changed

docs/rules/terraform_workspace_remote.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# terraform_workspace_remote
22

3-
`terraform.workspace` should not be used with a "remote" backend with remote execution.
3+
`terraform.workspace` should not be used with a "remote" backend with remote execution in Terraform v1.0.x.
44

55
If remote operations are [disabled](https://www.terraform.io/docs/cloud/run/index.html#disabling-remote-operations) for your workspace, you can safely disable this rule:
66

@@ -10,12 +10,15 @@ rule "terraform_workspace_remote" {
1010
}
1111
```
1212

13+
This rule looks at `required_version` for Terraform version estimation. If the `required_version` is not declared, it is assumed that you are using a more recent version.
14+
1315
> This rule is enabled by "recommended" preset.
1416
1517
## Example
1618

1719
```hcl
1820
terraform {
21+
required_version = ">= 1.0"
1922
backend "remote" {
2023
# ...
2124
}
@@ -35,24 +38,24 @@ $ tflint
3538
Warning: terraform.workspace should not be used with a 'remote' backend (terraform_workspace_remote)
3639
3740
on example.tf line 8:
38-
8: tags = {
39-
9: workspace = terraform.workspace
40-
10: }
41+
9: tags = {
42+
10: workspace = terraform.workspace
43+
11: }
4144
42-
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.1.0/docs/rules/terraform_workspace_remote.md
45+
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.5.0/docs/rules/terraform_workspace_remote.md
4346
```
4447

4548
## Why
4649

47-
Terraform configuration may include the name of the [current workspace](https://www.terraform.io/docs/state/workspaces.html#current-workspace-interpolation) using the `${terraform.workspace}` interpolation sequence. However, when Terraform Cloud workspaces are executing Terraform runs remotely, the Terraform CLI always uses the `default` workspace.
50+
Terraform configuration may include the name of the [current workspace](https://developer.hashicorp.com/terraform/language/state/workspaces#current-workspace-interpolation) using the `${terraform.workspace}` interpolation sequence. However, when Terraform Cloud workspaces are executing Terraform runs remotely, the Terraform v1.0.x always uses the `default` workspace.
4851

49-
The [remote](https://www.terraform.io/docs/backends/types/remote.html) backend is used with Terraform Cloud workspaces. Even if you set a `prefix` in the `workspaces` block, this value will be ignored during remote runs.
52+
The [remote](https://developer.hashicorp.com/terraform/language/settings/backends/remote) backend is used with Terraform Cloud workspaces. Even if you set a `prefix` in the `workspaces` block, this value will be ignored during remote runs.
5053

51-
For more information, see the [`remote` backend workspaces documentation](https://www.terraform.io/docs/backends/types/remote.html#workspaces).
54+
For more information, see the [`remote` backend workspaces documentation](https://developer.hashicorp.com/terraform/language/settings/backends/remote#workspace-names).
5255

5356
## How To Fix
5457

55-
Consider adding a variable to your configuration and setting it in each cloud workspace:
58+
If you still need support for Terarform v1.0.x, consider adding a variable to your configuration and setting it in each cloud workspace:
5659

5760
```tf
5861
variable "workspace" {
@@ -62,3 +65,5 @@ variable "workspace" {
6265
```
6366

6467
You can also name the variable based on what the workspace suffix represents in your configuration (e.g. environment).
68+
69+
If you don't need support for Terraform v1.0.x, you can suppress the issue by updating the `required_version` to not contain 1.0.x.

rules/terraform_workspace_remote.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package rules
22

33
import (
4+
"github.com/hashicorp/go-version"
45
"github.com/hashicorp/hcl/v2"
56
"github.com/hashicorp/hcl/v2/hclsyntax"
67
"github.com/hashicorp/hcl/v2/json"
@@ -41,6 +42,22 @@ func (r *TerraformWorkspaceRemoteRule) Link() string {
4142
return project.ReferenceLink(r.Name())
4243
}
4344

45+
// @see https://releases.hashicorp.com/terraform/
46+
var tf10Versions = []*version.Version{
47+
version.Must(version.NewVersion("1.0.0")),
48+
version.Must(version.NewVersion("1.0.1")),
49+
version.Must(version.NewVersion("1.0.2")),
50+
version.Must(version.NewVersion("1.0.3")),
51+
version.Must(version.NewVersion("1.0.4")),
52+
version.Must(version.NewVersion("1.0.5")),
53+
version.Must(version.NewVersion("1.0.6")),
54+
version.Must(version.NewVersion("1.0.7")),
55+
version.Must(version.NewVersion("1.0.8")),
56+
version.Must(version.NewVersion("1.0.9")),
57+
version.Must(version.NewVersion("1.0.10")),
58+
version.Must(version.NewVersion("1.0.11")),
59+
}
60+
4461
// Check checks for a "remote" backend and if found emits issues for
4562
// each use of terraform.workspace in an expression.
4663
func (r *TerraformWorkspaceRemoteRule) Check(runner tflint.Runner) error {
@@ -58,6 +75,9 @@ func (r *TerraformWorkspaceRemoteRule) Check(runner tflint.Runner) error {
5875
{
5976
Type: "terraform",
6077
Body: &hclext.BodySchema{
78+
Attributes: []hclext.AttributeSchema{
79+
{Name: "required_version"},
80+
},
6181
Blocks: []hclext.BlockSchema{
6282
{
6383
Type: "backend",
@@ -74,14 +94,34 @@ func (r *TerraformWorkspaceRemoteRule) Check(runner tflint.Runner) error {
7494
}
7595

7696
var remoteBackend bool
97+
var tf10Support bool
7798
for _, terraform := range body.Blocks {
99+
for _, requiredVersion := range terraform.Body.Attributes {
100+
err := runner.EvaluateExpr(requiredVersion.Expr, func(v string) error {
101+
constraints, err := version.NewConstraint(v)
102+
if err != nil {
103+
return err
104+
}
105+
106+
for _, tf10Version := range tf10Versions {
107+
if constraints.Check(tf10Version) {
108+
tf10Support = true
109+
}
110+
}
111+
return nil
112+
}, nil)
113+
if err != nil {
114+
return err
115+
}
116+
}
117+
78118
for _, backend := range terraform.Body.Blocks {
79119
if backend.Labels[0] == "remote" {
80120
remoteBackend = true
81121
}
82122
}
83123
}
84-
if !remoteBackend {
124+
if !remoteBackend || !tf10Support {
85125
return nil
86126
}
87127

rules/terraform_workspace_remote_test.go

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func Test_TerraformWorkspaceRemoteRule(t *testing.T) {
1818
Name: "terraform.workspace in resource with remote backend",
1919
Content: `
2020
terraform {
21+
required_version = ">= 1.0"
2122
backend "remote" {}
2223
}
2324
resource "null_resource" "a" {
@@ -31,15 +32,18 @@ resource "null_resource" "a" {
3132
Message: "terraform.workspace should not be used with a 'remote' backend",
3233
Range: hcl.Range{
3334
Filename: "config.tf",
34-
Start: hcl.Pos{Line: 7, Column: 7},
35-
End: hcl.Pos{Line: 7, Column: 26},
35+
Start: hcl.Pos{Line: 8, Column: 7},
36+
End: hcl.Pos{Line: 8, Column: 26},
3637
},
3738
},
3839
},
3940
},
4041
{
4142
Name: "terraform.workspace with no backend",
4243
Content: `
44+
terraform {
45+
required_version = ">= 1.0"
46+
}
4347
resource "null_resource" "a" {
4448
triggers = {
4549
w = terraform.workspace
@@ -51,8 +55,46 @@ resource "null_resource" "a" {
5155
Name: "terraform.workspace with non-remote backend",
5256
Content: `
5357
terraform {
58+
required_version = ">= 1.0"
5459
backend "local" {}
5560
}
61+
resource "null_resource" "a" {
62+
triggers = {
63+
w = terraform.workspace
64+
}
65+
}`,
66+
Expected: helper.Issues{},
67+
},
68+
{
69+
Name: "terraform.workspace with remote backend, but required_version does not support 1.0.x",
70+
Content: `
71+
terraform {
72+
required_version = ">= 1.1"
73+
backend "remote" {}
74+
}
75+
resource "null_resource" "a" {
76+
triggers = {
77+
w = terraform.workspace
78+
}
79+
}`,
80+
Expected: helper.Issues{},
81+
},
82+
{
83+
Name: "terraform.workspace with remote backend, but required_version is not declared",
84+
Content: `
85+
terraform {
86+
backend "remote" {}
87+
}
88+
resource "null_resource" "a" {
89+
triggers = {
90+
w = terraform.workspace
91+
}
92+
}`,
93+
Expected: helper.Issues{},
94+
},
95+
{
96+
Name: "terraform.workspace without terraform setting",
97+
Content: `
5698
resource "null_resource" "a" {
5799
triggers = {
58100
w = terraform.workspace
@@ -64,6 +106,7 @@ resource "null_resource" "a" {
64106
Name: "terraform.workspace in data source with remote backend",
65107
Content: `
66108
terraform {
109+
required_version = ">= 1.0"
67110
backend "remote" {}
68111
}
69112
data "null_data_source" "a" {
@@ -77,8 +120,8 @@ data "null_data_source" "a" {
77120
Message: "terraform.workspace should not be used with a 'remote' backend",
78121
Range: hcl.Range{
79122
Filename: "config.tf",
80-
Start: hcl.Pos{Line: 7, Column: 7},
81-
End: hcl.Pos{Line: 7, Column: 26},
123+
Start: hcl.Pos{Line: 8, Column: 7},
124+
End: hcl.Pos{Line: 8, Column: 26},
82125
},
83126
},
84127
},
@@ -87,6 +130,7 @@ data "null_data_source" "a" {
87130
Name: "terraform.workspace in module call with remote backend",
88131
Content: `
89132
terraform {
133+
required_version = ">= 1.0"
90134
backend "remote" {}
91135
}
92136
module "a" {
@@ -99,8 +143,8 @@ module "a" {
99143
Message: "terraform.workspace should not be used with a 'remote' backend",
100144
Range: hcl.Range{
101145
Filename: "config.tf",
102-
Start: hcl.Pos{Line: 7, Column: 6},
103-
End: hcl.Pos{Line: 7, Column: 25},
146+
Start: hcl.Pos{Line: 8, Column: 6},
147+
End: hcl.Pos{Line: 8, Column: 25},
104148
},
105149
},
106150
},
@@ -109,6 +153,7 @@ module "a" {
109153
Name: "terraform.workspace in provider config with remote backend",
110154
Content: `
111155
terraform {
156+
required_version = ">= 1.0"
112157
backend "remote" {}
113158
}
114159
provider "aws" {
@@ -122,8 +167,8 @@ provider "aws" {
122167
Message: "terraform.workspace should not be used with a 'remote' backend",
123168
Range: hcl.Range{
124169
Filename: "config.tf",
125-
Start: hcl.Pos{Line: 7, Column: 14},
126-
End: hcl.Pos{Line: 7, Column: 33},
170+
Start: hcl.Pos{Line: 8, Column: 14},
171+
End: hcl.Pos{Line: 8, Column: 33},
127172
},
128173
},
129174
},
@@ -132,6 +177,7 @@ provider "aws" {
132177
Name: "terraform.workspace in locals with remote backend",
133178
Content: `
134179
terraform {
180+
required_version = ">= 1.0"
135181
backend "remote" {}
136182
}
137183
locals {
@@ -143,8 +189,8 @@ locals {
143189
Message: "terraform.workspace should not be used with a 'remote' backend",
144190
Range: hcl.Range{
145191
Filename: "config.tf",
146-
Start: hcl.Pos{Line: 6, Column: 6},
147-
End: hcl.Pos{Line: 6, Column: 25},
192+
Start: hcl.Pos{Line: 7, Column: 6},
193+
End: hcl.Pos{Line: 7, Column: 25},
148194
},
149195
},
150196
},
@@ -153,6 +199,7 @@ locals {
153199
Name: "terraform.workspace in output with remote backend",
154200
Content: `
155201
terraform {
202+
required_version = ">= 1.0"
156203
backend "remote" {}
157204
}
158205
output "o" {
@@ -164,8 +211,8 @@ output "o" {
164211
Message: "terraform.workspace should not be used with a 'remote' backend",
165212
Range: hcl.Range{
166213
Filename: "config.tf",
167-
Start: hcl.Pos{Line: 6, Column: 10},
168-
End: hcl.Pos{Line: 6, Column: 29},
214+
Start: hcl.Pos{Line: 7, Column: 10},
215+
End: hcl.Pos{Line: 7, Column: 29},
169216
},
170217
},
171218
},
@@ -174,6 +221,7 @@ output "o" {
174221
Name: "nonmatching expressions with remote backend",
175222
Content: `
176223
terraform {
224+
required_version = ">= 1.0"
177225
backend "remote" {}
178226
}
179227
locals {
@@ -186,6 +234,7 @@ locals {
186234
Name: "meta-arguments",
187235
Content: `
188236
terraform {
237+
required_version = ">= 1.0"
189238
backend "remote" {}
190239
}
191240
resource "aws_instance" "foo" {
@@ -206,6 +255,7 @@ resource "aws_instance" "foo" {
206255
Content: `
207256
{
208257
"terraform": {
258+
"required_version": ">= 1.0",
209259
"backend": {
210260
"remote": {}
211261
}
@@ -226,8 +276,8 @@ resource "aws_instance" "foo" {
226276
Message: "terraform.workspace should not be used with a 'remote' backend",
227277
Range: hcl.Range{
228278
Filename: "config.tf.json",
229-
Start: hcl.Pos{Line: 8, Column: 15},
230-
End: hcl.Pos{Line: 16, Column: 4},
279+
Start: hcl.Pos{Line: 9, Column: 15},
280+
End: hcl.Pos{Line: 17, Column: 4},
231281
},
232282
},
233283
},
@@ -236,6 +286,7 @@ resource "aws_instance" "foo" {
236286
Name: "with ignore_changes",
237287
Content: `
238288
terraform {
289+
required_version = ">= 1.0"
239290
backend "remote" {}
240291
}
241292
resource "kubernetes_secret" "my_secret" {

0 commit comments

Comments
 (0)