Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add invalid option group detector for RDS #25

Merged
merged 1 commit into from
Dec 18, 2016
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
60 changes: 60 additions & 0 deletions detector/aws_db_instance_invalid_option_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package detector

import (
"fmt"

"github.com/aws/aws-sdk-go/service/rds"
"github.com/wata727/tflint/issue"
)

type AwsDBInstanceInvalidOptionGroupDetector struct {
*Detector
}

func (d *Detector) CreateAwsDBInstanceInvalidOptionGroupDetector() *AwsDBInstanceInvalidOptionGroupDetector {
return &AwsDBInstanceInvalidOptionGroupDetector{d}
}

func (d *AwsDBInstanceInvalidOptionGroupDetector) Detect(issues *[]*issue.Issue) {
if !d.isDeepCheck("resource", "aws_db_instance") {
return
}

validOptionGroups := map[string]bool{}
if d.ResponseCache.DescribeOptionGroupsOutput == nil {
resp, err := d.AwsClient.Rds.DescribeOptionGroups(&rds.DescribeOptionGroupsInput{})
if err != nil {
d.Logger.Error(err)
d.Error = true
}
d.ResponseCache.DescribeOptionGroupsOutput = resp
}
for _, optionGroup := range d.ResponseCache.DescribeOptionGroupsOutput.OptionGroupsList {
validOptionGroups[*optionGroup.OptionGroupName] = true
}

for filename, list := range d.ListMap {
for _, item := range list.Filter("resource", "aws_db_instance").Items {
optionGroupToken, err := hclLiteralToken(item, "option_group_name")
if err != nil {
d.Logger.Error(err)
continue
}
optionGroup, err := d.evalToString(optionGroupToken.Text)
if err != nil {
d.Logger.Error(err)
continue
}

if !validOptionGroups[optionGroup] {
issue := &issue.Issue{
Type: "ERROR",
Message: fmt.Sprintf("\"%s\" is invalid option group name.", optionGroup),
Line: optionGroupToken.Pos.Line,
File: filename,
}
*issues = append(*issues, issue)
}
}
}
}
92 changes: 92 additions & 0 deletions detector/aws_db_instance_invalid_option_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package detector

import (
"reflect"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/golang/mock/gomock"
"github.com/wata727/tflint/awsmock"
"github.com/wata727/tflint/config"
"github.com/wata727/tflint/issue"
)

func TestDetectAwsDBInstanceInvalidOptionGroup(t *testing.T) {
cases := []struct {
Name string
Src string
Response []*rds.OptionGroup
Issues []*issue.Issue
}{
{
Name: "option_group is invalid",
Src: `
resource "aws_db_instance" "mysql" {
option_group_name = "app-server"
}`,
Response: []*rds.OptionGroup{
&rds.OptionGroup{
OptionGroupName: aws.String("app-server1"),
},
&rds.OptionGroup{
OptionGroupName: aws.String("app-server2"),
},
},
Issues: []*issue.Issue{
&issue.Issue{
Type: "ERROR",
Message: "\"app-server\" is invalid option group name.",
Line: 3,
File: "test.tf",
},
},
},
{
Name: "option_group is valid",
Src: `
resource "aws_db_instance" "mysql" {
option_group_name = "app-server"
}`,
Response: []*rds.OptionGroup{
&rds.OptionGroup{
OptionGroupName: aws.String("app-server1"),
},
&rds.OptionGroup{
OptionGroupName: aws.String("app-server2"),
},
&rds.OptionGroup{
OptionGroupName: aws.String("app-server"),
},
},
Issues: []*issue.Issue{},
},
}

for _, tc := range cases {
c := config.Init()
c.DeepCheck = true

awsClient := c.NewAwsClient()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
rdsmock := awsmock.NewMockRDSAPI(ctrl)
rdsmock.EXPECT().DescribeOptionGroups(&rds.DescribeOptionGroupsInput{}).Return(&rds.DescribeOptionGroupsOutput{
OptionGroupsList: tc.Response,
}, nil)
awsClient.Rds = rdsmock

var issues = []*issue.Issue{}
TestDetectByCreatorName(
"CreateAwsDBInstanceInvalidOptionGroupDetector",
tc.Src,
c,
awsClient,
&issues,
)

if !reflect.DeepEqual(issues, tc.Issues) {
t.Fatalf("Bad: %s\nExpected: %s\n\ntestcase: %s", issues, tc.Issues, tc.Name)
}
}
}
1 change: 1 addition & 0 deletions detector/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var detectors = map[string]string{
"aws_db_instance_invalid_vpc_security_group": "CreateAwsDBInstanceInvalidVPCSecurityGroupDetector",
"aws_db_instance_invalid_db_subnet_group": "CreateAwsDBInstanceInvalidDBSubnetGroupDetector",
"aws_db_instance_invalid_parameter_group": "CreateAwsDBInstanceInvalidParameterGroupDetector",
"aws_db_instance_invalid_option_group": "CreateAwsDBInstanceInvalidOptionGroupDetector",
"aws_elasticache_cluster_default_parameter_group": "CreateAwsElastiCacheClusterDefaultParameterGroupDetector",
"aws_instance_invalid_iam_profile": "CreateAwsInstanceInvalidIAMProfileDetector",
"aws_instance_invalid_ami": "CreateAwsInstanceInvalidAMIDetector",
Expand Down
1 change: 1 addition & 0 deletions detector/response_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ type ResponseCache struct {
DescribeInstancesOutput *ec2.DescribeInstancesOutput
DescribeDBSubnetGroupsOutput *rds.DescribeDBSubnetGroupsOutput
DescribeDBParameterGroupsOutput *rds.DescribeDBParameterGroupsOutput
DescribeOptionGroupsOutput *rds.DescribeOptionGroupsOutput
}
38 changes: 38 additions & 0 deletions docs/AWS_DB_Instance_Invalid_Option_Group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# AWS DB Instance Invalid Option Group
Report this issue if you have specified the invalid option group name. This issue type is ERROR. This issue is enable only with deep check.

## Example
```
resource "aws_db_instance" "mysql" {
identifier = "app"
allocated_storage = 50
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7.11"
instance_class = "db.m4.large"
name = "app_db"
port = 3306
publicly_accessible = false
vpc_security_group_ids = ["sg-12345678"]
db_subnet_group_name = "app-subnet-group"
parameter_group_name = "default.mysql5.7"
option_group_name = "invalid_option"
multi_az = true
}
```

The following is the execution result of TFLint:

```
$ tflint --deep
template.tf
ERROR:14 "invalid_option" is invalid option group name.

Result: 1 issues (1 errors , 0 warnings , 0 notices)
```

## Why
If an invalid option group name is specified, an error will occur at `terraform apply`.

## How to fix
Check your option groups and select a valid name again.
2 changes: 1 addition & 1 deletion docs/AWS_DB_Instance_Invalid_Parameter_Group.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# AWS DB Instance Invalid Parameter Group
Report this issue if you have specified the invalid DB subnet group name. This issue type is ERROR. This issue is enable only with deep check.
Report this issue if you have specified the invalid parameter name. This issue type is ERROR. This issue is enable only with deep check.

## Example
```
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ Issues are classified into the following three types.
- [Invalid VPC Security Group](AWS_DB_Instance_Invalid_VPC_Security_Group.md)
- [Invalid DB Subnet Group](AWS_DB_Instance_Invalid_DB_Subnet_Group.md)
- [Invalid Parameter Group](AWS_DB_Instance_Invalid_Parameter_Group.md)
- [Invalid Option Group](AWS_DB_Instance_Invalid_Option_Group.md)
- AWS Elasticache Cluster
- [Default Parameter Group](AWS_Elasticache_Cluster_Default_Parameter_Group.md)