forked from terraform-linters/tflint
/
aws_instance_default_standard_volume.go
112 lines (93 loc) · 3.34 KB
/
aws_instance_default_standard_volume.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package awsrules
import (
"log"
"github.com/hashicorp/hcl2/hcl"
"github.com/wata727/tflint/issue"
"github.com/wata727/tflint/project"
"github.com/wata727/tflint/tflint"
)
// AwsInstanceDefaultStandardVolumeRule checks whether the volume type is unspecified
type AwsInstanceDefaultStandardVolumeRule struct {
resourceType string
}
// NewAwsInstanceDefaultStandardVolumeRule returns new rule with default attributes
func NewAwsInstanceDefaultStandardVolumeRule() *AwsInstanceDefaultStandardVolumeRule {
return &AwsInstanceDefaultStandardVolumeRule{
resourceType: "aws_instance",
}
}
// Name returns the rule name
func (r *AwsInstanceDefaultStandardVolumeRule) Name() string {
return "aws_instance_default_standard_volume"
}
// Enabled returns whether the rule is enabled by default
func (r *AwsInstanceDefaultStandardVolumeRule) Enabled() bool {
return true
}
// Type returns the rule severity
func (r *AwsInstanceDefaultStandardVolumeRule) Type() string {
return issue.WARNING
}
// Link returns the rule reference link
func (r *AwsInstanceDefaultStandardVolumeRule) Link() string {
return project.ReferenceLink(r.Name())
}
// Check checks whether `volume_type` is defined for `root_block_device` or `ebs_block_device`
func (r *AwsInstanceDefaultStandardVolumeRule) Check(runner *tflint.Runner) error {
log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath())
if err := runner.WalkResourceBlocks(r.resourceType, "root_block_device", func(block *hcl.Block) error {
return r.blockWalker(runner, block)
}); err != nil {
return err
}
if err := runner.WalkResourceBlocks(r.resourceType, "ebs_block_device", func(block *hcl.Block) error {
return r.blockWalker(runner, block)
}); err != nil {
return err
}
// Since Terraform v0.12, block device definitions must be defined as block, but it walks attributes for the backward compatibility.
if err := runner.WalkResourceAttributes(r.resourceType, "root_block_device", func(attribute *hcl.Attribute) error {
return r.attributeWalker(runner, attribute)
}); err != nil {
return err
}
if err := runner.WalkResourceAttributes(r.resourceType, "ebs_block_device", func(attribute *hcl.Attribute) error {
return r.attributeWalker(runner, attribute)
}); err != nil {
return err
}
return nil
}
func (r *AwsInstanceDefaultStandardVolumeRule) message() string {
return "\"volume_type\" is not specified. Default standard volume type is not recommended. You can use \"gp2\", \"io1\", etc instead."
}
func (r *AwsInstanceDefaultStandardVolumeRule) blockWalker(runner *tflint.Runner, block *hcl.Block) error {
body, _, diags := block.Body.PartialContent(&hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{
Name: "volume_type",
},
},
})
if diags.HasErrors() {
return diags
}
if volumeType, ok := body.Attributes["volume_type"]; ok {
if runner.IsNullExpr(volumeType.Expr) {
runner.EmitIssue(r, r.message(), volumeType.Expr.Range())
}
} else {
runner.EmitIssue(r, r.message(), block.TypeRange)
}
return nil
}
func (r *AwsInstanceDefaultStandardVolumeRule) attributeWalker(runner *tflint.Runner, attribute *hcl.Attribute) error {
var val map[string]string
err := runner.EvaluateExpr(attribute.Expr, &val)
return runner.EnsureNoError(err, func() error {
if _, ok := val["volume_type"]; !ok {
runner.EmitIssue(r, r.message(), attribute.Range)
}
return nil
})
}