From f72070e2855cf243d4b97e07034c60f4590da813 Mon Sep 17 00:00:00 2001 From: wata_mac Date: Mon, 13 May 2019 00:02:28 +0900 Subject: [PATCH] Auto generate rules from AWS API models --- .gitmodules | 3 + Gopkg.toml | 1 + Makefile | 5 +- rules/awsrules/models/aws-sdk-go | 1 + ...cm_certificate_invalid_certificate_body.go | 87 ++++++++ ...rtificate_invalid_certificate_body_test.go | 124 +++++++++++ ...m_certificate_invalid_certificate_chain.go | 87 ++++++++ ...tificate_invalid_certificate_chain_test.go | 142 +++++++++++++ ...aws_acm_certificate_invalid_private_key.go | 87 ++++++++ ...cm_certificate_invalid_private_key_test.go | 135 ++++++++++++ ...mpca_certificate_authority_invalid_type.go | 76 +++++++ ...certificate_authority_invalid_type_test.go | 87 ++++++++ ...aws_api_gateway_authorizer_invalid_type.go | 78 +++++++ ...pi_gateway_authorizer_invalid_type_test.go | 87 ++++++++ ..._gateway_response_invalid_response_type.go | 95 +++++++++ ...way_response_invalid_response_type_test.go | 87 ++++++++ ...ay_gateway_response_invalid_status_code.go | 69 +++++++ ...teway_response_invalid_status_code_test.go | 87 ++++++++ ...way_integration_invalid_connection_type.go | 77 +++++++ ...ntegration_invalid_connection_type_test.go | 87 ++++++++ ...ay_integration_invalid_content_handling.go | 77 +++++++ ...tegration_invalid_content_handling_test.go | 87 ++++++++ ...ws_api_gateway_integration_invalid_type.go | 80 ++++++++ ...i_gateway_integration_invalid_type_test.go | 87 ++++++++ ...ation_response_invalid_content_handling.go | 77 +++++++ ..._response_invalid_content_handling_test.go | 87 ++++++++ ...ntegration_response_invalid_status_code.go | 69 +++++++ ...ation_response_invalid_status_code_test.go | 87 ++++++++ ...way_method_response_invalid_status_code.go | 69 +++++++ ...ethod_response_invalid_status_code_test.go | 87 ++++++++ ...gateway_rest_api_invalid_api_key_source.go | 77 +++++++ ...ay_rest_api_invalid_api_key_source_test.go | 87 ++++++++ ...ateway_stage_invalid_cache_cluster_size.go | 83 ++++++++ ...y_stage_invalid_cache_cluster_size_test.go | 87 ++++++++ ...pautoscaling_policy_invalid_policy_type.go | 77 +++++++ ...scaling_policy_invalid_policy_type_test.go | 87 ++++++++ ...aling_policy_invalid_scalable_dimension.go | 86 ++++++++ ..._policy_invalid_scalable_dimension_test.go | 87 ++++++++ ...caling_policy_invalid_service_namespace.go | 83 ++++++++ ...g_policy_invalid_service_namespace_test.go | 87 ++++++++ ...duled_action_invalid_scalable_dimension.go | 86 ++++++++ ..._action_invalid_scalable_dimension_test.go | 87 ++++++++ ...eduled_action_invalid_service_namespace.go | 83 ++++++++ ...d_action_invalid_service_namespace_test.go | 87 ++++++++ ...aling_target_invalid_scalable_dimension.go | 86 ++++++++ ..._target_invalid_scalable_dimension_test.go | 87 ++++++++ ...caling_target_invalid_service_namespace.go | 83 ++++++++ ...g_target_invalid_service_namespace_test.go | 87 ++++++++ .../models/aws_appmesh_mesh_invalid_name.go | 77 +++++++ .../aws_appmesh_route_invalid_mesh_name.go | 77 +++++++ .../models/aws_appmesh_route_invalid_name.go | 77 +++++++ ...pmesh_route_invalid_virtual_router_name.go | 77 +++++++ ..._appmesh_virtual_node_invalid_mesh_name.go | 77 +++++++ .../aws_appmesh_virtual_node_invalid_name.go | 77 +++++++ ...ppmesh_virtual_router_invalid_mesh_name.go | 77 +++++++ ...aws_appmesh_virtual_router_invalid_name.go | 77 +++++++ ...pmesh_virtual_service_invalid_mesh_name.go | 77 +++++++ ...ws_appmesh_virtual_service_invalid_name.go | 77 +++++++ .../aws_appsync_datasource_invalid_name.go | 69 +++++++ ...ws_appsync_datasource_invalid_name_test.go | 87 ++++++++ .../aws_appsync_datasource_invalid_type.go | 81 ++++++++ ...ws_appsync_datasource_invalid_type_test.go | 87 ++++++++ ...graphql_api_invalid_authentication_type.go | 79 +++++++ ...ql_api_invalid_authentication_type_test.go | 87 ++++++++ ...ws_appsync_resolver_invalid_data_source.go | 69 +++++++ ...psync_resolver_invalid_data_source_test.go | 87 ++++++++ .../aws_appsync_resolver_invalid_field.go | 69 +++++++ ...aws_appsync_resolver_invalid_field_test.go | 87 ++++++++ ...psync_resolver_invalid_request_template.go | 77 +++++++ ...sync_resolver_invalid_response_template.go | 77 +++++++ .../aws_appsync_resolver_invalid_type.go | 69 +++++++ .../aws_appsync_resolver_invalid_type_test.go | 87 ++++++++ .../aws_athena_database_invalid_name.go | 77 +++++++ ...aws_athena_named_query_invalid_database.go | 77 +++++++ ..._athena_named_query_invalid_description.go | 77 +++++++ .../aws_athena_named_query_invalid_name.go | 77 +++++++ .../aws_athena_named_query_invalid_query.go | 77 +++++++ .../aws_launch_template_invalid_name.go | 87 ++++++++ .../aws_launch_template_invalid_name_test.go | 87 ++++++++ rules/awsrules/models/mappings/acm-pca.hcl | 14 ++ rules/awsrules/models/mappings/acm.hcl | 193 ++++++++++++++++++ rules/awsrules/models/mappings/apigateway.hcl | 164 +++++++++++++++ .../mappings/application-autoscaling.hcl | 104 ++++++++++ rules/awsrules/models/mappings/appmesh.hcl | 109 ++++++++++ rules/awsrules/models/mappings/appsync.hcl | 111 ++++++++++ rules/awsrules/models/mappings/athena.hcl | 54 +++++ rules/awsrules/models/mappings/ec2.hcl | 14 ++ rules/awsrules/models/models_test.go | 109 ++++++++++ rules/awsrules/models/pattern_rule.go.tmpl | 135 ++++++++++++ .../awsrules/models/pattern_rule_test.go.tmpl | 92 +++++++++ rules/provider.go | 4 +- rules/provider_model.go | 54 +++++ rules/provider_model.go.tmpl | 11 + tools/model-rule-gen/main.go | 79 +++++++ tools/model-rule-gen/provider.go | 25 +++ tools/model-rule-gen/rule.go | 85 ++++++++ tools/rule_generator.go | 42 +--- tools/utils/main.go | 51 +++++ 98 files changed, 7687 insertions(+), 40 deletions(-) create mode 100644 .gitmodules create mode 160000 rules/awsrules/models/aws-sdk-go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_certificate_body.go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_certificate_body_test.go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_certificate_chain.go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_certificate_chain_test.go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_private_key.go create mode 100644 rules/awsrules/models/aws_acm_certificate_invalid_private_key_test.go create mode 100644 rules/awsrules/models/aws_acmpca_certificate_authority_invalid_type.go create mode 100644 rules/awsrules/models/aws_acmpca_certificate_authority_invalid_type_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_authorizer_invalid_type.go create mode 100644 rules/awsrules/models/aws_api_gateway_authorizer_invalid_type_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_gateway_response_invalid_response_type.go create mode 100644 rules/awsrules/models/aws_api_gateway_gateway_response_invalid_response_type_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_gateway_response_invalid_status_code.go create mode 100644 rules/awsrules/models/aws_api_gateway_gateway_response_invalid_status_code_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_connection_type.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_connection_type_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_content_handling.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_content_handling_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_type.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_invalid_type_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_response_invalid_content_handling.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_response_invalid_content_handling_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_response_invalid_status_code.go create mode 100644 rules/awsrules/models/aws_api_gateway_integration_response_invalid_status_code_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_method_response_invalid_status_code.go create mode 100644 rules/awsrules/models/aws_api_gateway_method_response_invalid_status_code_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_rest_api_invalid_api_key_source.go create mode 100644 rules/awsrules/models/aws_api_gateway_rest_api_invalid_api_key_source_test.go create mode 100644 rules/awsrules/models/aws_api_gateway_stage_invalid_cache_cluster_size.go create mode 100644 rules/awsrules/models/aws_api_gateway_stage_invalid_cache_cluster_size_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_policy_type.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_policy_type_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_scalable_dimension.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_scalable_dimension_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_service_namespace.go create mode 100644 rules/awsrules/models/aws_appautoscaling_policy_invalid_service_namespace_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_scheduled_action_invalid_scalable_dimension.go create mode 100644 rules/awsrules/models/aws_appautoscaling_scheduled_action_invalid_scalable_dimension_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_scheduled_action_invalid_service_namespace.go create mode 100644 rules/awsrules/models/aws_appautoscaling_scheduled_action_invalid_service_namespace_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_target_invalid_scalable_dimension.go create mode 100644 rules/awsrules/models/aws_appautoscaling_target_invalid_scalable_dimension_test.go create mode 100644 rules/awsrules/models/aws_appautoscaling_target_invalid_service_namespace.go create mode 100644 rules/awsrules/models/aws_appautoscaling_target_invalid_service_namespace_test.go create mode 100644 rules/awsrules/models/aws_appmesh_mesh_invalid_name.go create mode 100644 rules/awsrules/models/aws_appmesh_route_invalid_mesh_name.go create mode 100644 rules/awsrules/models/aws_appmesh_route_invalid_name.go create mode 100644 rules/awsrules/models/aws_appmesh_route_invalid_virtual_router_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_node_invalid_mesh_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_node_invalid_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_router_invalid_mesh_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_router_invalid_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_service_invalid_mesh_name.go create mode 100644 rules/awsrules/models/aws_appmesh_virtual_service_invalid_name.go create mode 100644 rules/awsrules/models/aws_appsync_datasource_invalid_name.go create mode 100644 rules/awsrules/models/aws_appsync_datasource_invalid_name_test.go create mode 100644 rules/awsrules/models/aws_appsync_datasource_invalid_type.go create mode 100644 rules/awsrules/models/aws_appsync_datasource_invalid_type_test.go create mode 100644 rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type.go create mode 100644 rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type_test.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_data_source.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_data_source_test.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_field.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_field_test.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_request_template.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_response_template.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_type.go create mode 100644 rules/awsrules/models/aws_appsync_resolver_invalid_type_test.go create mode 100644 rules/awsrules/models/aws_athena_database_invalid_name.go create mode 100644 rules/awsrules/models/aws_athena_named_query_invalid_database.go create mode 100644 rules/awsrules/models/aws_athena_named_query_invalid_description.go create mode 100644 rules/awsrules/models/aws_athena_named_query_invalid_name.go create mode 100644 rules/awsrules/models/aws_athena_named_query_invalid_query.go create mode 100644 rules/awsrules/models/aws_launch_template_invalid_name.go create mode 100644 rules/awsrules/models/aws_launch_template_invalid_name_test.go create mode 100644 rules/awsrules/models/mappings/acm-pca.hcl create mode 100644 rules/awsrules/models/mappings/acm.hcl create mode 100644 rules/awsrules/models/mappings/apigateway.hcl create mode 100644 rules/awsrules/models/mappings/application-autoscaling.hcl create mode 100644 rules/awsrules/models/mappings/appmesh.hcl create mode 100644 rules/awsrules/models/mappings/appsync.hcl create mode 100644 rules/awsrules/models/mappings/athena.hcl create mode 100644 rules/awsrules/models/mappings/ec2.hcl create mode 100644 rules/awsrules/models/models_test.go create mode 100644 rules/awsrules/models/pattern_rule.go.tmpl create mode 100644 rules/awsrules/models/pattern_rule_test.go.tmpl create mode 100644 rules/provider_model.go create mode 100644 rules/provider_model.go.tmpl create mode 100644 tools/model-rule-gen/main.go create mode 100644 tools/model-rule-gen/provider.go create mode 100644 tools/model-rule-gen/rule.go create mode 100644 tools/utils/main.go diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..0a48921af --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rules/awsrules/models/aws-sdk-go"] + path = rules/awsrules/models/aws-sdk-go + url = https://github.com/aws/aws-sdk-go.git diff --git a/Gopkg.toml b/Gopkg.toml index 2147e3bca..c35c0075b 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -24,6 +24,7 @@ # go-tests = true # unused-packages = true +ignored = ["github.com/wata727/tflint/rules/awsrules/models/aws-sdk-go/*"] [[constraint]] name = "github.com/aws/aws-sdk-go" diff --git a/Makefile b/Makefile index 0a760609d..8228debb1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ prepare: dep ensure test: prepare - go test $$(go list ./... | grep -v vendor | grep -v mock) + go test $$(go list ./... | grep -v vendor | grep -v mock | grep -v aws-sdk-go) build: test go build -v @@ -57,4 +57,7 @@ image: rule: go run tools/rule_generator.go +model_rules: + go run github.com/wata727/tflint/tools/model-rule-gen + .PHONY: default prepare test build install release clean mock image rule diff --git a/rules/awsrules/models/aws-sdk-go b/rules/awsrules/models/aws-sdk-go new file mode 160000 index 000000000..594c848f3 --- /dev/null +++ b/rules/awsrules/models/aws-sdk-go @@ -0,0 +1 @@ +Subproject commit 594c848f324de48d7b9fa434b213db7283a859e3 diff --git a/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body.go b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body.go new file mode 100644 index 000000000..5c4fa01cf --- /dev/null +++ b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAcmCertificateInvalidCertificateBodyRule checks the pattern is valid +type AwsAcmCertificateInvalidCertificateBodyRule struct { + resourceType string + attributeName string + max int + min int + pattern *regexp.Regexp +} + +// NewAwsAcmCertificateInvalidCertificateBodyRule returns new rule with default attributes +func NewAwsAcmCertificateInvalidCertificateBodyRule() *AwsAcmCertificateInvalidCertificateBodyRule { + return &AwsAcmCertificateInvalidCertificateBodyRule{ + resourceType: "aws_acm_certificate", + attributeName: "certificate_body", + max: 32768, + min: 1, + pattern: regexp.MustCompile(`^-{5}BEGIN CERTIFICATE-{5}\x{000D}?\x{000A}([A-Za-z0-9/+]{64}\x{000D}?\x{000A})*[A-Za-z0-9/+]{1,64}={0,2}\x{000D}?\x{000A}-{5}END CERTIFICATE-{5}(\x{000D}?\x{000A})?$`), + } +} + +// Name returns the rule name +func (r *AwsAcmCertificateInvalidCertificateBodyRule) Name() string { + return "aws_acm_certificate_invalid_certificate_body" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAcmCertificateInvalidCertificateBodyRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAcmCertificateInvalidCertificateBodyRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAcmCertificateInvalidCertificateBodyRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAcmCertificateInvalidCertificateBodyRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "certificate_body must be 32768 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "certificate_body must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `certificate_body does not match valid pattern ^-{5}BEGIN CERTIFICATE-{5}\x{000D}?\x{000A}([A-Za-z0-9/+]{64}\x{000D}?\x{000A})*[A-Za-z0-9/+]{1,64}={0,2}\x{000D}?\x{000A}-{5}END CERTIFICATE-{5}(\x{000D}?\x{000A})?$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body_test.go b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body_test.go new file mode 100644 index 000000000..1e8a419c9 --- /dev/null +++ b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_body_test.go @@ -0,0 +1,124 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAcmCertificateInvalidCertificateBodyRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_acm_certificate" "foo" { + certificate_body = < r.max { + runner.EmitIssue( + r, + "certificate_chain must be 2097152 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "certificate_chain must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `certificate_chain does not match valid pattern ^(-{5}BEGIN CERTIFICATE-{5}\x{000D}?\x{000A}([A-Za-z0-9/+]{64}\x{000D}?\x{000A})*[A-Za-z0-9/+]{1,64}={0,2}\x{000D}?\x{000A}-{5}END CERTIFICATE-{5}\x{000D}?\x{000A})*-{5}BEGIN CERTIFICATE-{5}\x{000D}?\x{000A}([A-Za-z0-9/+]{64}\x{000D}?\x{000A})*[A-Za-z0-9/+]{1,64}={0,2}\x{000D}?\x{000A}-{5}END CERTIFICATE-{5}(\x{000D}?\x{000A})?$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_acm_certificate_invalid_certificate_chain_test.go b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_chain_test.go new file mode 100644 index 000000000..d2df067c4 --- /dev/null +++ b/rules/awsrules/models/aws_acm_certificate_invalid_certificate_chain_test.go @@ -0,0 +1,142 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAcmCertificateInvalidCertificateChainRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_acm_certificate" "foo" { + certificate_chain = < r.max { + runner.EmitIssue( + r, + "private_key must be 524288 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "private_key must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `private_key does not match valid pattern ^-{5}BEGIN PRIVATE KEY-{5}\x{000D}?\x{000A}([A-Za-z0-9/+]{64}\x{000D}?\x{000A})*[A-Za-z0-9/+]{1,64}={0,2}\x{000D}?\x{000A}-{5}END PRIVATE KEY-{5}(\x{000D}?\x{000A})?$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_acm_certificate_invalid_private_key_test.go b/rules/awsrules/models/aws_acm_certificate_invalid_private_key_test.go new file mode 100644 index 000000000..0d85c5b5c --- /dev/null +++ b/rules/awsrules/models/aws_acm_certificate_invalid_private_key_test.go @@ -0,0 +1,135 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAcmCertificateInvalidPrivateKeyRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_acm_certificate" "foo" { + private_key = < r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_route_invalid_mesh_name.go b/rules/awsrules/models/aws_appmesh_route_invalid_mesh_name.go new file mode 100644 index 000000000..a52bee078 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_route_invalid_mesh_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshRouteInvalidMeshNameRule checks the pattern is valid +type AwsAppmeshRouteInvalidMeshNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshRouteInvalidMeshNameRule returns new rule with default attributes +func NewAwsAppmeshRouteInvalidMeshNameRule() *AwsAppmeshRouteInvalidMeshNameRule { + return &AwsAppmeshRouteInvalidMeshNameRule{ + resourceType: "aws_appmesh_route", + attributeName: "mesh_name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshRouteInvalidMeshNameRule) Name() string { + return "aws_appmesh_route_invalid_mesh_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshRouteInvalidMeshNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshRouteInvalidMeshNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshRouteInvalidMeshNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshRouteInvalidMeshNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "mesh_name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "mesh_name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_route_invalid_name.go b/rules/awsrules/models/aws_appmesh_route_invalid_name.go new file mode 100644 index 000000000..8d0965c37 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_route_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshRouteInvalidNameRule checks the pattern is valid +type AwsAppmeshRouteInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshRouteInvalidNameRule returns new rule with default attributes +func NewAwsAppmeshRouteInvalidNameRule() *AwsAppmeshRouteInvalidNameRule { + return &AwsAppmeshRouteInvalidNameRule{ + resourceType: "aws_appmesh_route", + attributeName: "name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshRouteInvalidNameRule) Name() string { + return "aws_appmesh_route_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshRouteInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshRouteInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshRouteInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshRouteInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_route_invalid_virtual_router_name.go b/rules/awsrules/models/aws_appmesh_route_invalid_virtual_router_name.go new file mode 100644 index 000000000..3595f6f22 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_route_invalid_virtual_router_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshRouteInvalidVirtualRouterNameRule checks the pattern is valid +type AwsAppmeshRouteInvalidVirtualRouterNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshRouteInvalidVirtualRouterNameRule returns new rule with default attributes +func NewAwsAppmeshRouteInvalidVirtualRouterNameRule() *AwsAppmeshRouteInvalidVirtualRouterNameRule { + return &AwsAppmeshRouteInvalidVirtualRouterNameRule{ + resourceType: "aws_appmesh_route", + attributeName: "virtual_router_name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshRouteInvalidVirtualRouterNameRule) Name() string { + return "aws_appmesh_route_invalid_virtual_router_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshRouteInvalidVirtualRouterNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshRouteInvalidVirtualRouterNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshRouteInvalidVirtualRouterNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshRouteInvalidVirtualRouterNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "virtual_router_name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "virtual_router_name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_node_invalid_mesh_name.go b/rules/awsrules/models/aws_appmesh_virtual_node_invalid_mesh_name.go new file mode 100644 index 000000000..039d235af --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_node_invalid_mesh_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualNodeInvalidMeshNameRule checks the pattern is valid +type AwsAppmeshVirtualNodeInvalidMeshNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualNodeInvalidMeshNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualNodeInvalidMeshNameRule() *AwsAppmeshVirtualNodeInvalidMeshNameRule { + return &AwsAppmeshVirtualNodeInvalidMeshNameRule{ + resourceType: "aws_appmesh_virtual_node", + attributeName: "mesh_name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualNodeInvalidMeshNameRule) Name() string { + return "aws_appmesh_virtual_node_invalid_mesh_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualNodeInvalidMeshNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualNodeInvalidMeshNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualNodeInvalidMeshNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualNodeInvalidMeshNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "mesh_name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "mesh_name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_node_invalid_name.go b/rules/awsrules/models/aws_appmesh_virtual_node_invalid_name.go new file mode 100644 index 000000000..c7e3aa8b3 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_node_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualNodeInvalidNameRule checks the pattern is valid +type AwsAppmeshVirtualNodeInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualNodeInvalidNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualNodeInvalidNameRule() *AwsAppmeshVirtualNodeInvalidNameRule { + return &AwsAppmeshVirtualNodeInvalidNameRule{ + resourceType: "aws_appmesh_virtual_node", + attributeName: "name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualNodeInvalidNameRule) Name() string { + return "aws_appmesh_virtual_node_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualNodeInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualNodeInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualNodeInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualNodeInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_router_invalid_mesh_name.go b/rules/awsrules/models/aws_appmesh_virtual_router_invalid_mesh_name.go new file mode 100644 index 000000000..3c92b32dd --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_router_invalid_mesh_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualRouterInvalidMeshNameRule checks the pattern is valid +type AwsAppmeshVirtualRouterInvalidMeshNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualRouterInvalidMeshNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualRouterInvalidMeshNameRule() *AwsAppmeshVirtualRouterInvalidMeshNameRule { + return &AwsAppmeshVirtualRouterInvalidMeshNameRule{ + resourceType: "aws_appmesh_virtual_router", + attributeName: "mesh_name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualRouterInvalidMeshNameRule) Name() string { + return "aws_appmesh_virtual_router_invalid_mesh_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualRouterInvalidMeshNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualRouterInvalidMeshNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualRouterInvalidMeshNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualRouterInvalidMeshNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "mesh_name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "mesh_name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_router_invalid_name.go b/rules/awsrules/models/aws_appmesh_virtual_router_invalid_name.go new file mode 100644 index 000000000..f45ed15c4 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_router_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualRouterInvalidNameRule checks the pattern is valid +type AwsAppmeshVirtualRouterInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualRouterInvalidNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualRouterInvalidNameRule() *AwsAppmeshVirtualRouterInvalidNameRule { + return &AwsAppmeshVirtualRouterInvalidNameRule{ + resourceType: "aws_appmesh_virtual_router", + attributeName: "name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualRouterInvalidNameRule) Name() string { + return "aws_appmesh_virtual_router_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualRouterInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualRouterInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualRouterInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualRouterInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_service_invalid_mesh_name.go b/rules/awsrules/models/aws_appmesh_virtual_service_invalid_mesh_name.go new file mode 100644 index 000000000..d92ba3744 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_service_invalid_mesh_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualServiceInvalidMeshNameRule checks the pattern is valid +type AwsAppmeshVirtualServiceInvalidMeshNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualServiceInvalidMeshNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualServiceInvalidMeshNameRule() *AwsAppmeshVirtualServiceInvalidMeshNameRule { + return &AwsAppmeshVirtualServiceInvalidMeshNameRule{ + resourceType: "aws_appmesh_virtual_service", + attributeName: "mesh_name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualServiceInvalidMeshNameRule) Name() string { + return "aws_appmesh_virtual_service_invalid_mesh_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualServiceInvalidMeshNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualServiceInvalidMeshNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualServiceInvalidMeshNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualServiceInvalidMeshNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "mesh_name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "mesh_name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appmesh_virtual_service_invalid_name.go b/rules/awsrules/models/aws_appmesh_virtual_service_invalid_name.go new file mode 100644 index 000000000..1cc14e1d0 --- /dev/null +++ b/rules/awsrules/models/aws_appmesh_virtual_service_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppmeshVirtualServiceInvalidNameRule checks the pattern is valid +type AwsAppmeshVirtualServiceInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppmeshVirtualServiceInvalidNameRule returns new rule with default attributes +func NewAwsAppmeshVirtualServiceInvalidNameRule() *AwsAppmeshVirtualServiceInvalidNameRule { + return &AwsAppmeshVirtualServiceInvalidNameRule{ + resourceType: "aws_appmesh_virtual_service", + attributeName: "name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppmeshVirtualServiceInvalidNameRule) Name() string { + return "aws_appmesh_virtual_service_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppmeshVirtualServiceInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppmeshVirtualServiceInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppmeshVirtualServiceInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppmeshVirtualServiceInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_datasource_invalid_name.go b/rules/awsrules/models/aws_appsync_datasource_invalid_name.go new file mode 100644 index 000000000..1dae6ffea --- /dev/null +++ b/rules/awsrules/models/aws_appsync_datasource_invalid_name.go @@ -0,0 +1,69 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncDatasourceInvalidNameRule checks the pattern is valid +type AwsAppsyncDatasourceInvalidNameRule struct { + resourceType string + attributeName string + pattern *regexp.Regexp +} + +// NewAwsAppsyncDatasourceInvalidNameRule returns new rule with default attributes +func NewAwsAppsyncDatasourceInvalidNameRule() *AwsAppsyncDatasourceInvalidNameRule { + return &AwsAppsyncDatasourceInvalidNameRule{ + resourceType: "aws_appsync_datasource", + attributeName: "name", + pattern: regexp.MustCompile(`^[_A-Za-z][_0-9A-Za-z]*$`), + } +} + +// Name returns the rule name +func (r *AwsAppsyncDatasourceInvalidNameRule) Name() string { + return "aws_appsync_datasource_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncDatasourceInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncDatasourceInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncDatasourceInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncDatasourceInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `name does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_datasource_invalid_name_test.go b/rules/awsrules/models/aws_appsync_datasource_invalid_name_test.go new file mode 100644 index 000000000..dea2c342b --- /dev/null +++ b/rules/awsrules/models/aws_appsync_datasource_invalid_name_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncDatasourceInvalidNameRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_datasource" "foo" { + name = "01_tf_example" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_datasource_invalid_name", + Type: "ERROR", + Message: `name does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_datasource" "foo" { + name = "tf_appsync_example" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncDatasourceInvalidNameRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncDatasourceInvalidNameRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_appsync_datasource_invalid_type.go b/rules/awsrules/models/aws_appsync_datasource_invalid_type.go new file mode 100644 index 000000000..6282dee2e --- /dev/null +++ b/rules/awsrules/models/aws_appsync_datasource_invalid_type.go @@ -0,0 +1,81 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncDatasourceInvalidTypeRule checks the pattern is valid +type AwsAppsyncDatasourceInvalidTypeRule struct { + resourceType string + attributeName string + enum []string +} + +// NewAwsAppsyncDatasourceInvalidTypeRule returns new rule with default attributes +func NewAwsAppsyncDatasourceInvalidTypeRule() *AwsAppsyncDatasourceInvalidTypeRule { + return &AwsAppsyncDatasourceInvalidTypeRule{ + resourceType: "aws_appsync_datasource", + attributeName: "type", + enum: []string{ + "AWS_LAMBDA", + "AMAZON_DYNAMODB", + "AMAZON_ELASTICSEARCH", + "NONE", + "HTTP", + "RELATIONAL_DATABASE", + }, + } +} + +// Name returns the rule name +func (r *AwsAppsyncDatasourceInvalidTypeRule) Name() string { + return "aws_appsync_datasource_invalid_type" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncDatasourceInvalidTypeRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncDatasourceInvalidTypeRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncDatasourceInvalidTypeRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncDatasourceInvalidTypeRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + found := false + for _, item := range r.enum { + if item == val { + found = true + } + } + if !found { + runner.EmitIssue( + r, + `type is not a valid value`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_datasource_invalid_type_test.go b/rules/awsrules/models/aws_appsync_datasource_invalid_type_test.go new file mode 100644 index 000000000..537510e6e --- /dev/null +++ b/rules/awsrules/models/aws_appsync_datasource_invalid_type_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncDatasourceInvalidTypeRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_datasource" "foo" { + type = "AMAZON_SIMPLEDB" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_datasource_invalid_type", + Type: "ERROR", + Message: `type is not a valid value`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_datasource" "foo" { + type = "AWS_LAMBDA" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncDatasourceInvalidTypeRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncDatasourceInvalidTypeRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type.go b/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type.go new file mode 100644 index 000000000..01022dad8 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type.go @@ -0,0 +1,79 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule checks the pattern is valid +type AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule struct { + resourceType string + attributeName string + enum []string +} + +// NewAwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule returns new rule with default attributes +func NewAwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule() *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule { + return &AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule{ + resourceType: "aws_appsync_graphql_api", + attributeName: "authentication_type", + enum: []string{ + "API_KEY", + "AWS_IAM", + "AMAZON_COGNITO_USER_POOLS", + "OPENID_CONNECT", + }, + } +} + +// Name returns the rule name +func (r *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule) Name() string { + return "aws_appsync_graphql_api_invalid_authentication_type" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + found := false + for _, item := range r.enum { + if item == val { + found = true + } + } + if !found { + runner.EmitIssue( + r, + `authentication_type is not a valid value`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type_test.go b/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type_test.go new file mode 100644 index 000000000..2f6fba238 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_graphql_api_invalid_authentication_type_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_graphql_api" "foo" { + authentication_type = "AWS_KEY" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_graphql_api_invalid_authentication_type", + Type: "ERROR", + Message: `authentication_type is not a valid value`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_graphql_api" "foo" { + authentication_type = "API_KEY" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_data_source.go b/rules/awsrules/models/aws_appsync_resolver_invalid_data_source.go new file mode 100644 index 000000000..e4183f0dc --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_data_source.go @@ -0,0 +1,69 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncResolverInvalidDataSourceRule checks the pattern is valid +type AwsAppsyncResolverInvalidDataSourceRule struct { + resourceType string + attributeName string + pattern *regexp.Regexp +} + +// NewAwsAppsyncResolverInvalidDataSourceRule returns new rule with default attributes +func NewAwsAppsyncResolverInvalidDataSourceRule() *AwsAppsyncResolverInvalidDataSourceRule { + return &AwsAppsyncResolverInvalidDataSourceRule{ + resourceType: "aws_appsync_resolver", + attributeName: "data_source", + pattern: regexp.MustCompile(`^[_A-Za-z][_0-9A-Za-z]*$`), + } +} + +// Name returns the rule name +func (r *AwsAppsyncResolverInvalidDataSourceRule) Name() string { + return "aws_appsync_resolver_invalid_data_source" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncResolverInvalidDataSourceRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncResolverInvalidDataSourceRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncResolverInvalidDataSourceRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncResolverInvalidDataSourceRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `data_source does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_data_source_test.go b/rules/awsrules/models/aws_appsync_resolver_invalid_data_source_test.go new file mode 100644 index 000000000..036cc1c8c --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_data_source_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncResolverInvalidDataSourceRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_resolver" "foo" { + data_source = "tf-example" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_resolver_invalid_data_source", + Type: "ERROR", + Message: `data_source does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_resolver" "foo" { + data_source = "tfexample" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncResolverInvalidDataSourceRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncResolverInvalidDataSourceRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_field.go b/rules/awsrules/models/aws_appsync_resolver_invalid_field.go new file mode 100644 index 000000000..6809cfc12 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_field.go @@ -0,0 +1,69 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncResolverInvalidFieldRule checks the pattern is valid +type AwsAppsyncResolverInvalidFieldRule struct { + resourceType string + attributeName string + pattern *regexp.Regexp +} + +// NewAwsAppsyncResolverInvalidFieldRule returns new rule with default attributes +func NewAwsAppsyncResolverInvalidFieldRule() *AwsAppsyncResolverInvalidFieldRule { + return &AwsAppsyncResolverInvalidFieldRule{ + resourceType: "aws_appsync_resolver", + attributeName: "field", + pattern: regexp.MustCompile(`^[_A-Za-z][_0-9A-Za-z]*$`), + } +} + +// Name returns the rule name +func (r *AwsAppsyncResolverInvalidFieldRule) Name() string { + return "aws_appsync_resolver_invalid_field" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncResolverInvalidFieldRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncResolverInvalidFieldRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncResolverInvalidFieldRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncResolverInvalidFieldRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `field does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_field_test.go b/rules/awsrules/models/aws_appsync_resolver_invalid_field_test.go new file mode 100644 index 000000000..e4ea0e151 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_field_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncResolverInvalidFieldRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_resolver" "foo" { + field = "single-post" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_resolver_invalid_field", + Type: "ERROR", + Message: `field does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_resolver" "foo" { + field = "singlePost" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncResolverInvalidFieldRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncResolverInvalidFieldRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_request_template.go b/rules/awsrules/models/aws_appsync_resolver_invalid_request_template.go new file mode 100644 index 000000000..5dc31c7f5 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_request_template.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncResolverInvalidRequestTemplateRule checks the pattern is valid +type AwsAppsyncResolverInvalidRequestTemplateRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppsyncResolverInvalidRequestTemplateRule returns new rule with default attributes +func NewAwsAppsyncResolverInvalidRequestTemplateRule() *AwsAppsyncResolverInvalidRequestTemplateRule { + return &AwsAppsyncResolverInvalidRequestTemplateRule{ + resourceType: "aws_appsync_resolver", + attributeName: "request_template", + max: 65536, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppsyncResolverInvalidRequestTemplateRule) Name() string { + return "aws_appsync_resolver_invalid_request_template" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncResolverInvalidRequestTemplateRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncResolverInvalidRequestTemplateRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncResolverInvalidRequestTemplateRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncResolverInvalidRequestTemplateRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "request_template must be 65536 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "request_template must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_response_template.go b/rules/awsrules/models/aws_appsync_resolver_invalid_response_template.go new file mode 100644 index 000000000..5f7529be4 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_response_template.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncResolverInvalidResponseTemplateRule checks the pattern is valid +type AwsAppsyncResolverInvalidResponseTemplateRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAppsyncResolverInvalidResponseTemplateRule returns new rule with default attributes +func NewAwsAppsyncResolverInvalidResponseTemplateRule() *AwsAppsyncResolverInvalidResponseTemplateRule { + return &AwsAppsyncResolverInvalidResponseTemplateRule{ + resourceType: "aws_appsync_resolver", + attributeName: "response_template", + max: 65536, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAppsyncResolverInvalidResponseTemplateRule) Name() string { + return "aws_appsync_resolver_invalid_response_template" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncResolverInvalidResponseTemplateRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncResolverInvalidResponseTemplateRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncResolverInvalidResponseTemplateRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncResolverInvalidResponseTemplateRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "response_template must be 65536 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "response_template must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_type.go b/rules/awsrules/models/aws_appsync_resolver_invalid_type.go new file mode 100644 index 000000000..c6684dcd7 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_type.go @@ -0,0 +1,69 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAppsyncResolverInvalidTypeRule checks the pattern is valid +type AwsAppsyncResolverInvalidTypeRule struct { + resourceType string + attributeName string + pattern *regexp.Regexp +} + +// NewAwsAppsyncResolverInvalidTypeRule returns new rule with default attributes +func NewAwsAppsyncResolverInvalidTypeRule() *AwsAppsyncResolverInvalidTypeRule { + return &AwsAppsyncResolverInvalidTypeRule{ + resourceType: "aws_appsync_resolver", + attributeName: "type", + pattern: regexp.MustCompile(`^[_A-Za-z][_0-9A-Za-z]*$`), + } +} + +// Name returns the rule name +func (r *AwsAppsyncResolverInvalidTypeRule) Name() string { + return "aws_appsync_resolver_invalid_type" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAppsyncResolverInvalidTypeRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAppsyncResolverInvalidTypeRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAppsyncResolverInvalidTypeRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAppsyncResolverInvalidTypeRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `type does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_appsync_resolver_invalid_type_test.go b/rules/awsrules/models/aws_appsync_resolver_invalid_type_test.go new file mode 100644 index 000000000..6fc853fd4 --- /dev/null +++ b/rules/awsrules/models/aws_appsync_resolver_invalid_type_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsAppsyncResolverInvalidTypeRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_appsync_resolver" "foo" { + type = "User-Config" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_appsync_resolver_invalid_type", + Type: "ERROR", + Message: `type does not match valid pattern ^[_A-Za-z][_0-9A-Za-z]*$`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_appsync_resolver" "foo" { + type = "Query" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsAppsyncResolverInvalidTypeRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsAppsyncResolverInvalidTypeRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/aws_athena_database_invalid_name.go b/rules/awsrules/models/aws_athena_database_invalid_name.go new file mode 100644 index 000000000..214ea5851 --- /dev/null +++ b/rules/awsrules/models/aws_athena_database_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAthenaDatabaseInvalidNameRule checks the pattern is valid +type AwsAthenaDatabaseInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAthenaDatabaseInvalidNameRule returns new rule with default attributes +func NewAwsAthenaDatabaseInvalidNameRule() *AwsAthenaDatabaseInvalidNameRule { + return &AwsAthenaDatabaseInvalidNameRule{ + resourceType: "aws_athena_database", + attributeName: "name", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAthenaDatabaseInvalidNameRule) Name() string { + return "aws_athena_database_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAthenaDatabaseInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAthenaDatabaseInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAthenaDatabaseInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAthenaDatabaseInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_athena_named_query_invalid_database.go b/rules/awsrules/models/aws_athena_named_query_invalid_database.go new file mode 100644 index 000000000..d5dedfac5 --- /dev/null +++ b/rules/awsrules/models/aws_athena_named_query_invalid_database.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAthenaNamedQueryInvalidDatabaseRule checks the pattern is valid +type AwsAthenaNamedQueryInvalidDatabaseRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAthenaNamedQueryInvalidDatabaseRule returns new rule with default attributes +func NewAwsAthenaNamedQueryInvalidDatabaseRule() *AwsAthenaNamedQueryInvalidDatabaseRule { + return &AwsAthenaNamedQueryInvalidDatabaseRule{ + resourceType: "aws_athena_named_query", + attributeName: "database", + max: 255, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAthenaNamedQueryInvalidDatabaseRule) Name() string { + return "aws_athena_named_query_invalid_database" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAthenaNamedQueryInvalidDatabaseRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAthenaNamedQueryInvalidDatabaseRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAthenaNamedQueryInvalidDatabaseRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAthenaNamedQueryInvalidDatabaseRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "database must be 255 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "database must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_athena_named_query_invalid_description.go b/rules/awsrules/models/aws_athena_named_query_invalid_description.go new file mode 100644 index 000000000..2990e5bcc --- /dev/null +++ b/rules/awsrules/models/aws_athena_named_query_invalid_description.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAthenaNamedQueryInvalidDescriptionRule checks the pattern is valid +type AwsAthenaNamedQueryInvalidDescriptionRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAthenaNamedQueryInvalidDescriptionRule returns new rule with default attributes +func NewAwsAthenaNamedQueryInvalidDescriptionRule() *AwsAthenaNamedQueryInvalidDescriptionRule { + return &AwsAthenaNamedQueryInvalidDescriptionRule{ + resourceType: "aws_athena_named_query", + attributeName: "description", + max: 1024, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAthenaNamedQueryInvalidDescriptionRule) Name() string { + return "aws_athena_named_query_invalid_description" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAthenaNamedQueryInvalidDescriptionRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAthenaNamedQueryInvalidDescriptionRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAthenaNamedQueryInvalidDescriptionRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAthenaNamedQueryInvalidDescriptionRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "description must be 1024 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "description must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_athena_named_query_invalid_name.go b/rules/awsrules/models/aws_athena_named_query_invalid_name.go new file mode 100644 index 000000000..7311e4531 --- /dev/null +++ b/rules/awsrules/models/aws_athena_named_query_invalid_name.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAthenaNamedQueryInvalidNameRule checks the pattern is valid +type AwsAthenaNamedQueryInvalidNameRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAthenaNamedQueryInvalidNameRule returns new rule with default attributes +func NewAwsAthenaNamedQueryInvalidNameRule() *AwsAthenaNamedQueryInvalidNameRule { + return &AwsAthenaNamedQueryInvalidNameRule{ + resourceType: "aws_athena_named_query", + attributeName: "name", + max: 128, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAthenaNamedQueryInvalidNameRule) Name() string { + return "aws_athena_named_query_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAthenaNamedQueryInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAthenaNamedQueryInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAthenaNamedQueryInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAthenaNamedQueryInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 128 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_athena_named_query_invalid_query.go b/rules/awsrules/models/aws_athena_named_query_invalid_query.go new file mode 100644 index 000000000..8563a096c --- /dev/null +++ b/rules/awsrules/models/aws_athena_named_query_invalid_query.go @@ -0,0 +1,77 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsAthenaNamedQueryInvalidQueryRule checks the pattern is valid +type AwsAthenaNamedQueryInvalidQueryRule struct { + resourceType string + attributeName string + max int + min int +} + +// NewAwsAthenaNamedQueryInvalidQueryRule returns new rule with default attributes +func NewAwsAthenaNamedQueryInvalidQueryRule() *AwsAthenaNamedQueryInvalidQueryRule { + return &AwsAthenaNamedQueryInvalidQueryRule{ + resourceType: "aws_athena_named_query", + attributeName: "query", + max: 262144, + min: 1, + } +} + +// Name returns the rule name +func (r *AwsAthenaNamedQueryInvalidQueryRule) Name() string { + return "aws_athena_named_query_invalid_query" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsAthenaNamedQueryInvalidQueryRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsAthenaNamedQueryInvalidQueryRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsAthenaNamedQueryInvalidQueryRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsAthenaNamedQueryInvalidQueryRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "query must be 262144 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "query must be 1 characters or higher", + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_launch_template_invalid_name.go b/rules/awsrules/models/aws_launch_template_invalid_name.go new file mode 100644 index 000000000..23630524b --- /dev/null +++ b/rules/awsrules/models/aws_launch_template_invalid_name.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "log" + "regexp" + + "github.com/hashicorp/hcl2/hcl" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +// AwsLaunchTemplateInvalidNameRule checks the pattern is valid +type AwsLaunchTemplateInvalidNameRule struct { + resourceType string + attributeName string + max int + min int + pattern *regexp.Regexp +} + +// NewAwsLaunchTemplateInvalidNameRule returns new rule with default attributes +func NewAwsLaunchTemplateInvalidNameRule() *AwsLaunchTemplateInvalidNameRule { + return &AwsLaunchTemplateInvalidNameRule{ + resourceType: "aws_launch_template", + attributeName: "name", + max: 128, + min: 3, + pattern: regexp.MustCompile(`^[a-zA-Z0-9\(\)\.\-/_]+$`), + } +} + +// Name returns the rule name +func (r *AwsLaunchTemplateInvalidNameRule) Name() string { + return "aws_launch_template_invalid_name" +} + +// Enabled returns whether the rule is enabled by default +func (r *AwsLaunchTemplateInvalidNameRule) Enabled() bool { + return true +} + +// Type returns the rule severity +func (r *AwsLaunchTemplateInvalidNameRule) Type() string { + return issue.ERROR +} + +// Link returns the rule reference link +func (r *AwsLaunchTemplateInvalidNameRule) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AwsLaunchTemplateInvalidNameRule) Check(runner *tflint.Runner) error { + log.Printf("[INFO] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath()) + + return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error { + var val string + err := runner.EvaluateExpr(attribute.Expr, &val) + + return runner.EnsureNoError(err, func() error { + if len(val) > r.max { + runner.EmitIssue( + r, + "name must be 128 characters or less", + attribute.Expr.Range(), + ) + } + if len(val) < r.min { + runner.EmitIssue( + r, + "name must be 3 characters or higher", + attribute.Expr.Range(), + ) + } + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `name does not match valid pattern ^[a-zA-Z0-9\(\)\.\-/_]+$`, + attribute.Expr.Range(), + ) + } + return nil + }) + }) +} diff --git a/rules/awsrules/models/aws_launch_template_invalid_name_test.go b/rules/awsrules/models/aws_launch_template_invalid_name_test.go new file mode 100644 index 000000000..024fe3f21 --- /dev/null +++ b/rules/awsrules/models/aws_launch_template_invalid_name_test.go @@ -0,0 +1,87 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_AwsLaunchTemplateInvalidNameRule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "aws_launch_template" "foo" { + name = "foo[bar]" +}`, + Expected: []*issue.Issue{ + { + Detector: "aws_launch_template_invalid_name", + Type: "ERROR", + Message: `name does not match valid pattern ^[a-zA-Z0-9\(\)\.\-/_]+$`, + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "aws_launch_template" "foo" { + name = "foo" +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "AwsLaunchTemplateInvalidNameRule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := NewAwsLaunchTemplateInvalidNameRule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/awsrules/models/mappings/acm-pca.hcl b/rules/awsrules/models/mappings/acm-pca.hcl new file mode 100644 index 000000000..8ca1b3358 --- /dev/null +++ b/rules/awsrules/models/mappings/acm-pca.hcl @@ -0,0 +1,14 @@ +mapping { + resource { + type = "aws_acmpca_certificate_authority" + attribute = "type" + } + model { + path = "aws-sdk-go/models/apis/acm-pca/2017-08-22/api-2.json" + shape = "CertificateAuthorityType" + } + test { + ok = "SUBORDINATE" + ng = "ORDINATE" + } +} diff --git a/rules/awsrules/models/mappings/acm.hcl b/rules/awsrules/models/mappings/acm.hcl new file mode 100644 index 000000000..10d233e76 --- /dev/null +++ b/rules/awsrules/models/mappings/acm.hcl @@ -0,0 +1,193 @@ +mapping { + resource { + type = "aws_acm_certificate" + attribute = "certificate_body" + } + + model { + path = "aws-sdk-go/models/apis/acm/2015-12-08/api-2.json" + shape = "CertificateBody" + } + + test { + ok = < r.max { + runner.EmitIssue( + r, + "{{ .AttributeName }} must be {{ .Max }} characters or less", + attribute.Expr.Range(), + ) + } +{{- end }} + +{{- if ne .Min 0 }} + if len(val) < r.min { + runner.EmitIssue( + r, + "{{ .AttributeName }} must be {{ .Min }} characters or higher", + attribute.Expr.Range(), + ) + } +{{- end }} + +{{- if ne .Pattern "" }} + if !r.pattern.MatchString(val) { + runner.EmitIssue( + r, + `{{ .AttributeName }} does not match valid pattern ^{{ .Pattern }}$`, + attribute.Expr.Range(), + ) + } +{{- end }} + +{{- if ne (len .Enum) 0 }} + found := false + for _, item := range r.enum { + if item == val { + found = true + } + } + if !found { + runner.EmitIssue( + r, + `{{ .AttributeName }} is not a valid value`, + attribute.Expr.Range(), + ) + } +{{- end }} + return nil + }) + }) +} diff --git a/rules/awsrules/models/pattern_rule_test.go.tmpl b/rules/awsrules/models/pattern_rule_test.go.tmpl new file mode 100644 index 000000000..2a891f302 --- /dev/null +++ b/rules/awsrules/models/pattern_rule_test.go.tmpl @@ -0,0 +1,92 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package models + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configload" + "github.com/hashicorp/terraform/terraform" + "github.com/wata727/tflint/issue" + "github.com/wata727/tflint/tflint" +) + +func Test_{{ .RuleNameCC }}Rule(t *testing.T) { + cases := []struct { + Name string + Content string + Expected issue.Issues + }{ + { + Name: "It includes invalid characters", + Content: ` +resource "{{ .ResourceType }}" "foo" { + {{ .AttributeName }} = {{ .TestNG }} +}`, + Expected: []*issue.Issue{ + { + Detector: "{{ .RuleName }}", + Type: "ERROR", +{{- if ne .Pattern "" }} + Message: `{{ .AttributeName }} does not match valid pattern ^{{ .Pattern }}$`, +{{- end }} +{{- if ne (len .Enum) 0 }} + Message: `{{ .AttributeName }} is not a valid value`, +{{- end }} + Line: 3, + File: "resource.tf", + }, + }, + }, + { + Name: "It is valid", + Content: ` +resource "{{ .ResourceType }}" "foo" { + {{ .AttributeName }} = {{ .TestOK }} +}`, + Expected: []*issue.Issue{}, + }, + } + + dir, err := ioutil.TempDir("", "{{ .RuleNameCC }}Rule") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for _, tc := range cases { + loader, err := configload.NewLoader(&configload.Config{}) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(dir+"/resource.tf", []byte(tc.Content), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + mod, diags := loader.Parser().LoadConfigDir(dir) + if diags.HasErrors() { + t.Fatal(diags) + } + cfg, tfdiags := configs.BuildConfig(mod, configs.DisabledModuleWalker) + if tfdiags.HasErrors() { + t.Fatal(tfdiags) + } + + runner := tflint.NewRunner(tflint.EmptyConfig(), cfg, map[string]*terraform.InputValue{}) + rule := New{{ .RuleNameCC }}Rule() + + if err = rule.Check(runner); err != nil { + t.Fatalf("Unexpected error occurred: %s", err) + } + + if !cmp.Equal(tc.Expected, runner.Issues) { + t.Fatalf("Expected issues are not matched:\n %s\n", cmp.Diff(tc.Expected, runner.Issues)) + } + } +} diff --git a/rules/provider.go b/rules/provider.go index c5c2c7497..fe79cd857 100644 --- a/rules/provider.go +++ b/rules/provider.go @@ -16,7 +16,9 @@ type Rule interface { } // DefaultRules is rules by default -var DefaultRules = []Rule{ +var DefaultRules = append(manualRules, modelRules...) + +var manualRules = []Rule{ awsrules.NewAwsCloudwatchMetricAlarmInvalidUnitRule(), awsrules.NewAwsDBInstanceDefaultParameterGroupRule(), awsrules.NewAwsDBInstanceInvalidTypeRule(), diff --git a/rules/provider_model.go b/rules/provider_model.go new file mode 100644 index 000000000..78d5350fb --- /dev/null +++ b/rules/provider_model.go @@ -0,0 +1,54 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package rules + +import awsmodelrules "github.com/wata727/tflint/rules/awsrules/models" + +var modelRules = []Rule{ + awsmodelrules.NewAwsAcmpcaCertificateAuthorityInvalidTypeRule(), + awsmodelrules.NewAwsAcmCertificateInvalidCertificateBodyRule(), + awsmodelrules.NewAwsAcmCertificateInvalidCertificateChainRule(), + awsmodelrules.NewAwsAcmCertificateInvalidPrivateKeyRule(), + awsmodelrules.NewAwsAPIGatewayGatewayResponseInvalidStatusCodeRule(), + awsmodelrules.NewAwsAPIGatewayIntegrationResponseInvalidStatusCodeRule(), + awsmodelrules.NewAwsAPIGatewayMethodResponseInvalidStatusCodeRule(), + awsmodelrules.NewAwsAPIGatewayAuthorizerInvalidTypeRule(), + awsmodelrules.NewAwsAPIGatewayGatewayResponseInvalidResponseTypeRule(), + awsmodelrules.NewAwsAPIGatewayIntegrationInvalidTypeRule(), + awsmodelrules.NewAwsAPIGatewayIntegrationInvalidConnectionTypeRule(), + awsmodelrules.NewAwsAPIGatewayIntegrationInvalidContentHandlingRule(), + awsmodelrules.NewAwsAPIGatewayIntegrationResponseInvalidContentHandlingRule(), + awsmodelrules.NewAwsAPIGatewayRestAPIInvalidAPIKeySourceRule(), + awsmodelrules.NewAwsAPIGatewayStageInvalidCacheClusterSizeRule(), + awsmodelrules.NewAwsAppautoscalingPolicyInvalidPolicyTypeRule(), + awsmodelrules.NewAwsAppautoscalingPolicyInvalidScalableDimensionRule(), + awsmodelrules.NewAwsAppautoscalingScheduledActionInvalidScalableDimensionRule(), + awsmodelrules.NewAwsAppautoscalingTargetInvalidScalableDimensionRule(), + awsmodelrules.NewAwsAppautoscalingPolicyInvalidServiceNamespaceRule(), + awsmodelrules.NewAwsAppautoscalingScheduledActionInvalidServiceNamespaceRule(), + awsmodelrules.NewAwsAppautoscalingTargetInvalidServiceNamespaceRule(), + awsmodelrules.NewAwsAppmeshMeshInvalidNameRule(), + awsmodelrules.NewAwsAppmeshRouteInvalidNameRule(), + awsmodelrules.NewAwsAppmeshRouteInvalidMeshNameRule(), + awsmodelrules.NewAwsAppmeshRouteInvalidVirtualRouterNameRule(), + awsmodelrules.NewAwsAppmeshVirtualNodeInvalidNameRule(), + awsmodelrules.NewAwsAppmeshVirtualNodeInvalidMeshNameRule(), + awsmodelrules.NewAwsAppmeshVirtualRouterInvalidNameRule(), + awsmodelrules.NewAwsAppmeshVirtualRouterInvalidMeshNameRule(), + awsmodelrules.NewAwsAppmeshVirtualServiceInvalidNameRule(), + awsmodelrules.NewAwsAppmeshVirtualServiceInvalidMeshNameRule(), + awsmodelrules.NewAwsAppsyncDatasourceInvalidNameRule(), + awsmodelrules.NewAwsAppsyncDatasourceInvalidTypeRule(), + awsmodelrules.NewAwsAppsyncGraphqlAPIInvalidAuthenticationTypeRule(), + awsmodelrules.NewAwsAppsyncResolverInvalidTypeRule(), + awsmodelrules.NewAwsAppsyncResolverInvalidFieldRule(), + awsmodelrules.NewAwsAppsyncResolverInvalidDataSourceRule(), + awsmodelrules.NewAwsAppsyncResolverInvalidRequestTemplateRule(), + awsmodelrules.NewAwsAppsyncResolverInvalidResponseTemplateRule(), + awsmodelrules.NewAwsAthenaDatabaseInvalidNameRule(), + awsmodelrules.NewAwsAthenaNamedQueryInvalidNameRule(), + awsmodelrules.NewAwsAthenaNamedQueryInvalidDatabaseRule(), + awsmodelrules.NewAwsAthenaNamedQueryInvalidQueryRule(), + awsmodelrules.NewAwsAthenaNamedQueryInvalidDescriptionRule(), + awsmodelrules.NewAwsLaunchTemplateInvalidNameRule(), +} diff --git a/rules/provider_model.go.tmpl b/rules/provider_model.go.tmpl new file mode 100644 index 000000000..223d02601 --- /dev/null +++ b/rules/provider_model.go.tmpl @@ -0,0 +1,11 @@ +// This file generated by `tools/model-rule-gen/main.go`. DO NOT EDIT + +package rules + +import awsmodelrules "github.com/wata727/tflint/rules/awsrules/models" + +var modelRules = []Rule{ + {{- range $v := .RuleNameCCList }} + awsmodelrules.New{{ $v }}Rule(), + {{- end }} +} diff --git a/tools/model-rule-gen/main.go b/tools/model-rule-gen/main.go new file mode 100644 index 000000000..39ea6627e --- /dev/null +++ b/tools/model-rule-gen/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "path/filepath" + + "github.com/hashicorp/hcl2/gohcl" + "github.com/hashicorp/hcl2/hclparse" +) + +type mappingFile struct { + Mappings []mapping `hcl:"mapping,block"` +} + +type mapping struct { + Resource resource `hcl:"resource,block"` + Model model `hcl:"model,block"` + Test *test `hcl:"test,block"` +} + +type mappings []mapping + +type resource struct { + Type string `hcl:"type"` + Attribute string `hcl:"attribute"` +} + +type model struct { + Path string `hcl:"path"` + Shape string `hcl:"shape"` +} + +type test struct { + OK string `hcl:"ok"` + NG string `hcl:"ng"` +} + +func main() { + files, err := filepath.Glob("rules/awsrules/models/mappings/*.hcl") + if err != nil { + panic(err) + } + + mappings := mappings{} + for _, file := range files { + parser := hclparse.NewParser() + f, diags := parser.ParseHCLFile(file) + if diags.HasErrors() { + panic(diags) + } + + var mf mappingFile + diags = gohcl.DecodeBody(f.Body, nil, &mf) + if diags.HasErrors() { + panic(diags) + } + mappings = append(mappings, mf.Mappings...) + } + + for _, mapping := range mappings { + raw, err := ioutil.ReadFile(fmt.Sprintf("rules/awsrules/models/%s", mapping.Model.Path)) + if err != nil { + panic(err) + } + + var api map[string]interface{} + err = json.Unmarshal(raw, &api) + if err != nil { + panic(err) + } + shapes := api["shapes"].(map[string]interface{}) + + generateRuleFile(mapping, shapes) + } + + generateProviderFile(mappings) +} diff --git a/tools/model-rule-gen/provider.go b/tools/model-rule-gen/provider.go new file mode 100644 index 000000000..80ff24c93 --- /dev/null +++ b/tools/model-rule-gen/provider.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + + "github.com/wata727/tflint/tools/utils" +) + +type providerMeta struct { + RuleNameCCList []string +} + +func generateProviderFile(mappings mappings) { + meta := &providerMeta{} + + for _, mapping := range mappings { + resource := mapping.Resource.Type + attribute := mapping.Resource.Attribute + ruleName := fmt.Sprintf("%s_invalid_%s", resource, attribute) + + meta.RuleNameCCList = append(meta.RuleNameCCList, utils.ToCamel(ruleName)) + } + + utils.GenerateFile("rules/provider_model.go", "rules/provider_model.go.tmpl", meta) +} diff --git a/tools/model-rule-gen/rule.go b/tools/model-rule-gen/rule.go new file mode 100644 index 000000000..ed482c644 --- /dev/null +++ b/tools/model-rule-gen/rule.go @@ -0,0 +1,85 @@ +package main + +import ( + "fmt" + "regexp" + "strings" + + "github.com/wata727/tflint/tools/utils" +) + +type ruleMeta struct { + RuleName string + RuleNameCC string + ResourceType string + AttributeName string + Max int + Min int + Pattern string + Enum []string + TestOK string + TestNG string +} + +func generateRuleFile(mapping mapping, shapes map[string]interface{}) { + resource := mapping.Resource.Type + attribute := mapping.Resource.Attribute + ruleName := fmt.Sprintf("%s_invalid_%s", resource, attribute) + model := shapes[mapping.Model.Shape].(map[string]interface{}) + + meta := &ruleMeta{ + RuleName: ruleName, + RuleNameCC: utils.ToCamel(ruleName), + ResourceType: resource, + AttributeName: attribute, + Max: fetchNumber(model, "max"), + Min: fetchNumber(model, "min"), + Pattern: replacePattern(fetchString(model, "pattern")), + Enum: fetchStrings(model, "enum"), + } + + utils.GenerateFile(fmt.Sprintf("rules/awsrules/models/%s.go", ruleName), "rules/awsrules/models/pattern_rule.go.tmpl", meta) + if mapping.Test != nil { + meta.TestOK = formatTest(mapping.Test.OK) + meta.TestNG = formatTest(mapping.Test.NG) + utils.GenerateFile(fmt.Sprintf("rules/awsrules/models/%s_test.go", ruleName), "rules/awsrules/models/pattern_rule_test.go.tmpl", meta) + } +} + +func fetchNumber(model map[string]interface{}, key string) int { + if v, ok := model[key]; ok { + return int(v.(float64)) + } + return 0 +} + +func fetchStrings(model map[string]interface{}, key string) []string { + if raw, ok := model[key]; ok { + list := raw.([]interface{}) + ret := make([]string, len(list)) + for i, v := range list { + ret[i] = v.(string) + } + return ret + } + return []string{} +} + +func fetchString(model map[string]interface{}, key string) string { + if v, ok := model[key]; ok { + return v.(string) + } + return "" +} + +func replacePattern(pattern string) string { + reg := regexp.MustCompile(`\\u([0-9A-F]{4})`) + return reg.ReplaceAllString(pattern, `\x{$1}`) +} + +func formatTest(body string) string { + if strings.Contains(body, "\n") { + return fmt.Sprintf("<