Skip to content

Commit

Permalink
aws_elasticache_replication_group - fixes #140 Add tests fir aws_elas…
Browse files Browse the repository at this point in the history
…ticache_replication_group # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Mon Jul 19 15:34:06 2021 -0400 # # On branch aws_elasticache_replication_group # Changes to be committed: # modified: docs/rules/aws_elasticache_cluster_default_parameter_group.md # new file: docs/rules/aws_elasticache_replication_group_default_parameter_group.md # new file: rules/aws_elasticache_replication_group_default_parameter_group.go # new file: rules/aws_elasticache_replication_group_default_parameter_group_test.go # new file: rules/aws_elasticache_replication_group_invalid_type.go # new file: rules/aws_elasticache_replication_group_invalid_type_test.go #
  • Loading branch information
James Ray committed Jul 19, 2021
1 parent ef81b2c commit eaa469f
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 2 deletions.
4 changes: 2 additions & 2 deletions docs/rules/aws_elasticache_cluster_default_parameter_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ $ tflint
Notice: "default.redis3.2" is default parameter group. You cannot edit it. (aws_elasticache_cluster_default_parameter_group)
on template.tf line 9:
9: parameter_group_name = "default.redis3.2" // default paramete group!
9: parameter_group_name = "default.redis3.2" // default parameter group!
```

## Why
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# aws_elasticache_replication_group_default_parameter_group

Disallow using default parameter group.

## Example

```hcl
resource "aws_elasticache_replication_group" "redis" {
cluster_id = "app"
engine = "redis"
engine_version = "3.2.4"
maintenance_window = "sun:00:00-sun:06:00"
node_type = "cache.m4.large"
num_cache_nodes = 1
port = 6379
parameter_group_name = "default.redis3.2" // default paramete group!
subnet_group_name = "app-subnet-group"
security_group_ids = ["${aws_security_group.redis.id}"]
}
```

```
$ tflint
1 issue(s) found:
Notice: "default.redis3.2" is default parameter group. You cannot edit it. (aws_elasticache_replication_group_default_parameter_group)
on template.tf line 9:
9: parameter_group_name = "default.redis3.2" // default parameter group!
```

## Why

You can modify parameter values in a custom parameter group, but you can't change the parameter values in a default parameter group.

## How To Fix

Create a new parameter group, and change the `parameter_group_name` to that.
65 changes: 65 additions & 0 deletions rules/aws_elasticache_replication_group_default_parameter_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package rules

import (
"fmt"
"regexp"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint-ruleset-aws/project"
)

// AwsElastiCacheReplicationGroupDefaultParameterGroupRule checks whether the cluster use default parameter group
type AwsElastiCacheReplicationGroupDefaultParameterGroupRule struct {
resourceType string
attributeName string
}

// NewAwsElastiCacheReplicationGroupDefaultParameterGroupRule returns new rule with default attributes
func NewAwsElastiCacheReplicationGroupDefaultParameterGroupRule() *AwsElastiCacheReplicationGroupDefaultParameterGroupRule {
return &AwsElastiCacheReplicationGroupDefaultParameterGroupRule{
resourceType: "aws_elasticache_replication_group",
attributeName: "parameter_group_name",
}
}

// Name returns the rule name
func (r *AwsElastiCacheReplicationGroupDefaultParameterGroupRule) Name() string {
return "aws_elasticache_replication_group_default_parameter_group"
}

// Enabled returns whether the rule is enabled by default
func (r *AwsElastiCacheReplicationGroupDefaultParameterGroupRule) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AwsElastiCacheReplicationGroupDefaultParameterGroupRule) Severity() string {
return tflint.NOTICE
}

// Link returns the rule reference link
func (r *AwsElastiCacheReplicationGroupDefaultParameterGroupRule) Link() string {
return project.ReferenceLink(r.Name())
}

var defaultElastiCacheParameterGroupRegexp = regexp.MustCompile("^default")

// Check checks the parameter group name starts with `default`
func (r *AwsElastiCacheReplicationGroupDefaultParameterGroupRule) Check(runner tflint.Runner) error {
return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error {
var parameterGroup string
err := runner.EvaluateExpr(attribute.Expr, &parameterGroup, nil)

return runner.EnsureNoError(err, func() error {
if defaultElastiCacheParameterGroupRegexp.Match([]byte(parameterGroup)) {
runner.EmitIssueOnExpr(
r,
fmt.Sprintf("\"%s\" is default parameter group. You cannot edit it.", parameterGroup),
attribute.Expr,
)
}
return nil
})
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package rules

import (
"testing"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/helper"
)

func Test_AwsElastiCacheReplicationGroupDefaultParameterGroup(t *testing.T) {
cases := []struct {
Name string
Content string
Expected helper.Issues
}{
{
Name: "default.redis3.2 is default parameter group",
Content: `
resource "aws_elasticache_replication_group" "cache" {
parameter_group_name = "default.redis3.2"
}`,
Expected: helper.Issues{
{
Rule: NewAwsElastiCacheReplicationGroupDefaultParameterGroupRule(),
Message: "\"default.redis3.2\" is default parameter group. You cannot edit it.",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 3, Column: 28},
End: hcl.Pos{Line: 3, Column: 46},
},
},
},
},
{
Name: "application3.2 is not default parameter group",
Content: `
resource "aws_elasticache_replication_group" "cache" {
parameter_group_name = "application3.2"
}`,
Expected: helper.Issues{},
},
}

rule := NewAwsElastiCacheReplicationGroupDefaultParameterGroupRule()

for _, tc := range cases {
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})

if err := rule.Check(runner); err != nil {
t.Fatalf("Unexpected error occurred: %s", err)
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
}
}
126 changes: 126 additions & 0 deletions rules/aws_elasticache_replication_group_invalid_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package rules

import (
"fmt"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint-ruleset-aws/project"
)

// AwsElastiCacheReplicationGroupInvalidTypeRule checks whether "aws_elasticache_replication_group" has invalid node type.
type AwsElastiCacheReplicationGroupInvalidTypeRule struct {
resourceType string
attributeName string
nodeTypes map[string]bool
}

// NewAwsElastiCacheReplicationGroupInvalidTypeRule returns new rule with default attributes
func NewAwsElastiCacheReplicationGroupInvalidTypeRule() *AwsElastiCacheReplicationGroupInvalidTypeRule {
return &AwsElastiCacheReplicationGroupInvalidTypeRule{
resourceType: "aws_elasticache_replication_group",
attributeName: "node_type",
nodeTypes: map[string]bool{
"cache.t2.micro": true,
"cache.t2.small": true,
"cache.t2.medium": true,
"cache.t3.micro": true,
"cache.t3.small": true,
"cache.t3.medium": true,
"cache.m3.medium": true,
"cache.m3.large": true,
"cache.m3.xlarge": true,
"cache.m3.2xlarge": true,
"cache.m4.large": true,
"cache.m4.xlarge": true,
"cache.m4.2xlarge": true,
"cache.m4.4xlarge": true,
"cache.m4.10xlarge": true,
"cache.m5.large": true,
"cache.m5.xlarge": true,
"cache.m5.2xlarge": true,
"cache.m5.4xlarge": true,
"cache.m5.12xlarge": true,
"cache.m5.24xlarge": true,
"cache.m6g.large": true,
"cache.m6g.xlarge": true,
"cache.m6g.2xlarge": true,
"cache.m6g.4xlarge": true,
"cache.m6g.8xlarge": true,
"cache.m6g.12xlarge": true,
"cache.m6g.16xlarge": true,
"cache.r3.large": true,
"cache.r3.xlarge": true,
"cache.r3.2xlarge": true,
"cache.r3.4xlarge": true,
"cache.r3.8xlarge": true,
"cache.r4.large": true,
"cache.r4.xlarge": true,
"cache.r4.2xlarge": true,
"cache.r4.4xlarge": true,
"cache.r4.8xlarge": true,
"cache.r4.16xlarge": true,
"cache.r5.large": true,
"cache.r5.xlarge": true,
"cache.r5.2xlarge": true,
"cache.r5.4xlarge": true,
"cache.r5.12xlarge": true,
"cache.r5.24xlarge": true,
"cache.r6g.large": true,
"cache.r6g.xlarge": true,
"cache.r6g.2xlarge": true,
"cache.r6g.4xlarge": true,
"cache.r6g.8xlarge": true,
"cache.r6g.12xlarge": true,
"cache.r6g.16xlarge": true,
"cache.m1.small": true,
"cache.m1.medium": true,
"cache.m1.large": true,
"cache.m1.xlarge": true,
"cache.m2.xlarge": true,
"cache.m2.2xlarge": true,
"cache.m2.4xlarge": true,
"cache.c1.xlarge": true,
"cache.t1.micro": true,
},
}
}

// Name returns the rule name
func (r *AwsElastiCacheReplicationGroupInvalidTypeRule) Name() string {
return "aws_elasticache_replication_group_invalid_type"
}

// Enabled returns whether the rule is enabled by default
func (r *AwsElastiCacheReplicationGroupInvalidTypeRule) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AwsElastiCacheReplicationGroupInvalidTypeRule) Severity() string {
return tflint.ERROR
}

// Link returns the rule reference link
func (r *AwsElastiCacheReplicationGroupInvalidTypeRule) Link() string {
return project.ReferenceLink(r.Name())
}

// Check checks whether "aws_elasticache_replication_group" has invalid node type.
func (r *AwsElastiCacheReplicationGroupInvalidTypeRule) Check(runner tflint.Runner) error {
return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error {
var nodeType string
err := runner.EvaluateExpr(attribute.Expr, &nodeType, nil)

return runner.EnsureNoError(err, func() error {
if !r.nodeTypes[nodeType] {
runner.EmitIssueOnExpr(
r,
fmt.Sprintf("\"%s\" is invalid node type.", nodeType),
attribute.Expr,
)
}
return nil
})
})
}
55 changes: 55 additions & 0 deletions rules/aws_elasticache_replication_group_invalid_type_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package rules

import (
"testing"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/helper"
)

func Test_AwsElastiCacheReplicationGroupInvalidType(t *testing.T) {
cases := []struct {
Name string
Content string
Expected helper.Issues
}{
{
Name: "t2.micro is invalid",
Content: `
resource "aws_elasticache_replication_group" "redis" {
node_type = "t2.micro"
}`,
Expected: helper.Issues{
{
Rule: NewAwsElastiCacheReplicationGroupInvalidTypeRule(),
Message: "\"t2.micro\" is invalid node type.",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 3, Column: 17},
End: hcl.Pos{Line: 3, Column: 27},
},
},
},
},
{
Name: "cache.t2.micro is valid",
Content: `
resource "aws_elasticache_replication_group" "redis" {
node_type = "cache.t2.micro"
}`,
Expected: helper.Issues{},
},
}

rule := NewAwsElastiCacheReplicationGroupInvalidTypeRule()

for _, tc := range cases {
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})

if err := rule.Check(runner); err != nil {
t.Fatalf("Unexpected error occurred: %s", err)
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
}
}

0 comments on commit eaa469f

Please sign in to comment.