diff --git a/docs/guides/compatibility.md b/docs/guides/compatibility.md index 8e5f2c327..8d1caef13 100644 --- a/docs/guides/compatibility.md +++ b/docs/guides/compatibility.md @@ -13,7 +13,15 @@ Like Terraform, it supports the `--var`,` --var-file` options, automatic loading ## Named Values -[Named values](https://www.terraform.io/docs/configuration/expressions.html#references-to-named-values) are supported only for [input variables](https://www.terraform.io/docs/configuration/variables.html) and [workspaces](https://www.terraform.io/docs/state/workspaces.html). Expressions that contain anything else are excluded from the inspection. +[Named values](https://www.terraform.io/docs/configuration/expressions.html#references-to-named-values) are supported partially. The following named values are available: + +- `var.` +- `path.module` +- `path.root` +- `path.cwd` +- `terraform.workspace` + +Expressions that reference named values not included above are excluded from the inspection. ## Built-in Functions diff --git a/tflint/runner.go b/tflint/runner.go index f52ee451f..79387c587 100644 --- a/tflint/runner.go +++ b/tflint/runner.go @@ -543,6 +543,8 @@ func isEvaluable(expr hcl.Expression) bool { // noop case addrs.TerraformAttr: // noop + case addrs.PathAttr: + // noop default: return false } diff --git a/tflint/runner_test.go b/tflint/runner_test.go index 4911348ff..79ff0d2de 100644 --- a/tflint/runner_test.go +++ b/tflint/runner_test.go @@ -19,6 +19,12 @@ import ( ) func Test_EvaluateExpr_string(t *testing.T) { + dir, err := ioutil.TempDir("", "string") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + cases := []struct { Name string Content string @@ -144,14 +150,24 @@ resource "null_resource" "test" { }`, Expected: "Hello World", }, + { + Name: "path.root", + Content: ` +resource "null_resource" "test" { + key = path.root +}`, + Expected: filepath.ToSlash(dir), + }, + { + Name: "path.module", + Content: ` +resource "null_resource" "test" { + key = path.module +}`, + Expected: filepath.ToSlash(dir), + }, } - dir, err := ioutil.TempDir("", "string") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - for _, tc := range cases { err := ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) if err != nil { @@ -184,6 +200,53 @@ resource "null_resource" "test" { } } +func Test_EvaluateExpr_pathCwd(t *testing.T) { + dir, err := ioutil.TempDir("", "string") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + content := ` +resource "null_resource" "test" { + key = path.cwd +}` + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + expected := filepath.ToSlash(cwd) + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + cfg, err := loadConfigHelper(dir) + if err != nil { + t.Fatal(err) + } + attribute, err := extractAttributeHelper("key", cfg) + if err != nil { + t.Fatal(err) + } + + runner, err := NewRunner(EmptyConfig(), map[string]Annotations{}, cfg, map[string]*terraform.InputValue{}) + if err != nil { + t.Fatalf("Unexpected error: %s", err) + } + + var ret string + err = runner.EvaluateExpr(attribute.Expr, &ret) + if err != nil { + t.Fatalf("Unexpected error: `%s`", err) + } + + if expected != ret { + t.Fatalf("expected value is `%s`, but get `%s`", expected, ret) + } +} + func Test_EvaluateExpr_integer(t *testing.T) { cases := []struct { Name string @@ -833,6 +896,14 @@ resource "null_resource" "test" { }`, Expected: false, }, + { + Name: "path attributes", + Content: ` +resource "null_resource" "test" { + key = path.cwd +}`, + Expected: true, + }, } dir, err := ioutil.TempDir("", "isEvaluable")