Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions docs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,111 @@ terraform.moved_blocks({"from": "any"}, {})
]
```

## `terraform.imports`

```rego
blocks := terraform.imports(schema, options)
```

Returns Terraform imports blocks.

- `schema` (schema): schema for attributes referenced in rules.
- `options` (object[string: string]): options to change the retrieve/evaluate behavior.

Returns:

- `blocks` (array[object<config: body, decl_range: range>]): Terraform "import" blocks.

The `schema` and `options` are equivalent to the arguments of the `terraform.resources` function.

Examples:

```hcl
import {
to = aws_instance.example
id = "i-abcd1234"
}
```

```rego
terraform.imports({"id": "string"}, {})
```

```json
[
{
"config": {
"id": {
"value": "i-abcd1234",
"unknown": false,
"sensitive": false,
"range": {...}
}
},
"decl_range": {...}
}
]
```

## `terraform.checks`

```rego
blocks := terraform.checks(schema, options)
```

Returns Terraform check blocks.

- `schema` (schema): schema for attributes referenced in rules.
- `options` (object[string: string]): options to change the retrieve/evaluate behavior.

Returns:

- `blocks` (array[object<config: body, decl_range: range>]): Terraform "check" blocks.

The `schema` and `options` are equivalent to the arguments of the `terraform.resources` function.

Examples:

```hcl
check "health_check" {
data "http" "terraform_io" {
url = "https://www.terraform.io"
}

assert {
condition = data.http.terraform_io.status_code == 200
error_message = "${data.http.terraform_io.url} returned an unhealthy status code"
}
}
```

```rego
terraform.checks({"assert": {"condition": "bool"}}, {})
```

```json
[
{
"config": {
"assert": [
{
"config": {
"condition": {
"unknown": true,
"sensitive": false,
"range": {...}
}
},
"labels": null,
"decl_range": {...}
}
]
},
"decl_range": {...}
}
]
```

## `terraform.module_range`

```rego
Expand Down
9 changes: 9 additions & 0 deletions integration/checks/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugin "terraform" {
enabled = false
}

plugin "opa" {
enabled = true

policy_dir = "policies"
}
17 changes: 17 additions & 0 deletions integration/checks/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
check "health_check" {
data "http" "terraform_io" {
url = "https://www.terraform.io"
}

assert {
condition = data.http.terraform_io.status_code == 200
error_message = "${data.http.terraform_io.url} returned an unhealthy status code"
}
}

check "deterministic" {
assert {
condition = 200 == 200
error_message = "condition should be true"
}
}
9 changes: 9 additions & 0 deletions integration/checks/policies/main.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package tflint

deny_deterministic_check_condition[issue] {
checks := terraform.checks({"assert": {"condition": "bool"}}, {})
condition = checks[_].config.assert[_].config.condition
condition.unknown == false

issue := tflint.issue("deterministic check condtion is not allowed", condition.range)
}
24 changes: 24 additions & 0 deletions integration/checks/policies/main_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package tflint
import future.keywords

mock_checks(schema, options) := terraform.mock_checks(schema, options, {"main.tf": `
check "deterministic" {
assert {
condition = 200 == 200
error_message = "condition should be true"
}
}`})

test_deny_deterministic_check_condition_passed if {
issues := deny_deterministic_check_condition with terraform.checks as mock_checks

count(issues) == 1
issue := issues[_]
issue.msg == "deterministic check condtion is not allowed"
}

test_deny_deterministic_check_condition_failed if {
issues := deny_deterministic_check_condition with terraform.checks as mock_checks

count(issues) == 0
}
25 changes: 25 additions & 0 deletions integration/checks/result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_deny_deterministic_check_condition",
"severity": "error",
"link": "policies/main.rego:3"
},
"message": "deterministic check condtion is not allowed",
"range": {
"filename": "main.tf",
"start": {
"line": 14,
"column": 17
},
"end": {
"line": 14,
"column": 27
}
},
"callers": []
}
],
"errors": []
}
25 changes: 25 additions & 0 deletions integration/checks/result_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_test_deny_deterministic_check_condition_failed",
"severity": "error",
"link": "policies/main_test.rego:20"
},
"message": "test failed",
"range": {
"filename": "",
"start": {
"line": 0,
"column": 0
},
"end": {
"line": 0,
"column": 0
}
},
"callers": []
}
],
"errors": []
}
9 changes: 9 additions & 0 deletions integration/imports/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugin "terraform" {
enabled = false
}

plugin "opa" {
enabled = true

policy_dir = "policies"
}
4 changes: 4 additions & 0 deletions integration/imports/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {
to = aws_instance.example
id = "i-abcd1234"
}
8 changes: 8 additions & 0 deletions integration/imports/policies/main.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package tflint

deny_import_blocks[issue] {
imports := terraform.imports({}, {})
count(imports) > 0

issue := tflint.issue("import blocks are not allowed", imports[0].decl_range)
}
22 changes: 22 additions & 0 deletions integration/imports/policies/main_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package tflint
import future.keywords

mock_imports(schema, options) := terraform.mock_imports(schema, options, {"main.tf": `
import {
to = aws_instance.example
id = "i-abcd1234"
}`})

test_deny_import_blocks_passed if {
issues := deny_import_blocks with terraform.imports as mock_imports

count(issues) == 1
issue := issues[_]
issue.msg == "import blocks are not allowed"
}

test_deny_import_blocks_failed if {
issues := deny_import_blocks with terraform.imports as mock_imports

count(issues) == 0
}
25 changes: 25 additions & 0 deletions integration/imports/result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_deny_import_blocks",
"severity": "error",
"link": "policies/main.rego:3"
},
"message": "import blocks are not allowed",
"range": {
"filename": "main.tf",
"start": {
"line": 1,
"column": 1
},
"end": {
"line": 1,
"column": 7
}
},
"callers": []
}
],
"errors": []
}
25 changes: 25 additions & 0 deletions integration/imports/result_test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"issues": [
{
"rule": {
"name": "opa_test_deny_import_blocks_failed",
"severity": "error",
"link": "policies/main_test.rego:18"
},
"message": "test failed",
"range": {
"filename": "",
"start": {
"line": 0,
"column": 0
},
"end": {
"line": 0,
"column": 0
}
},
"callers": []
}
],
"errors": []
}
22 changes: 22 additions & 0 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ func TestIntegration(t *testing.T) {
dir: "moved",
test: true,
},
{
name: "imports",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "imports",
},
{
name: "imports (test)",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "imports",
test: true,
},
{
name: "checks",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "checks",
},
{
name: "checks (test)",
command: exec.Command("tflint", "--format", "json", "--force"),
dir: "checks",
test: true,
},
}

dir, _ := os.Getwd()
Expand Down
Loading