From f5a8ba149f3518a5dd98fc321d39dcf14753969d Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Sat, 5 Mar 2016 16:37:45 +0000 Subject: [PATCH] provider/aws: Add validation for CW Log Metric Filter --- .../aws/resource_aws_cloudwatch_log_group.go | 7 +- ...source_aws_cloudwatch_log_metric_filter.go | 34 ++++--- builtin/providers/aws/validators.go | 59 +++++++++++ builtin/providers/aws/validators_test.go | 97 +++++++++++++++++++ 4 files changed, 180 insertions(+), 17 deletions(-) diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_group.go b/builtin/providers/aws/resource_aws_cloudwatch_log_group.go index e4f7236b2de7..66416b7df186 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_group.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_group.go @@ -19,9 +19,10 @@ func resourceAwsCloudWatchLogGroup() *schema.Resource { Schema: map[string]*schema.Schema{ "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateLogGroupName, }, "retention_in_days": &schema.Schema{ diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_metric_filter.go b/builtin/providers/aws/resource_aws_cloudwatch_log_metric_filter.go index dfaed7ca0dda..0fca5fc20bb8 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_metric_filter.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_metric_filter.go @@ -21,14 +21,16 @@ func resourceAwsCloudWatchLogMetricFilter() *schema.Resource { Schema: map[string]*schema.Schema{ "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateLogMetricFilterName, }, "pattern": &schema.Schema{ - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateMaxLength(512), StateFunc: func(v interface{}) string { s, ok := v.(string) if !ok { @@ -39,9 +41,10 @@ func resourceAwsCloudWatchLogMetricFilter() *schema.Resource { }, "log_group_name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateLogGroupName, }, "metric_transformation": &schema.Schema{ @@ -51,16 +54,19 @@ func resourceAwsCloudWatchLogMetricFilter() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateLogMetricFilterTransformationName, }, "namespace": &schema.Schema{ - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateLogMetricFilterTransformationName, }, "value": &schema.Schema{ - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateMaxLength(100), }, }, }, diff --git a/builtin/providers/aws/validators.go b/builtin/providers/aws/validators.go index 6ff09a4a3928..6e978b765eb8 100644 --- a/builtin/providers/aws/validators.go +++ b/builtin/providers/aws/validators.go @@ -299,3 +299,62 @@ func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors [] return } + +func validateLogMetricFilterName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 512 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 512 characters: %q", k, value)) + } + + // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutMetricFilter.html + pattern := `^[^:*]+$` + if !regexp.MustCompile(pattern).MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q isn't a valid log metric name (must not contain colon nor asterisk): %q", + k, value)) + } + + return +} + +func validateLogMetricFilterTransformationName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 255 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 255 characters: %q", k, value)) + } + + // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_MetricTransformation.html + pattern := `^[^:*$]*$` + if !regexp.MustCompile(pattern).MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q isn't a valid log metric transformation name (must not contain"+ + " colon, asterisk nor dollar sign): %q", + k, value)) + } + + return +} + +func validateLogGroupName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 512 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 512 characters: %q", k, value)) + } + + // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html + pattern := `^[\.\-_/#A-Za-z0-9]+$` + if !regexp.MustCompile(pattern).MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q isn't a valid log group name (alphanumeric characters, underscores,"+ + " hyphens, slashes, hash signs and dots are allowed): %q", + k, value)) + } + + return +} diff --git a/builtin/providers/aws/validators_test.go b/builtin/providers/aws/validators_test.go index 0cca92c4f9df..bafc5d9416e8 100644 --- a/builtin/providers/aws/validators_test.go +++ b/builtin/providers/aws/validators_test.go @@ -274,3 +274,100 @@ func TestValidateCIDRNetworkAddress(t *testing.T) { } } } + +func TestValidateLogMetricFilterName(t *testing.T) { + validNames := []string{ + "YadaHereAndThere", + "Valid-5Metric_Name", + "This . is also %% valid@!)+(", + "1234", + strings.Repeat("W", 512), + } + for _, v := range validNames { + _, errors := validateLogMetricFilterName(v, "name") + if len(errors) != 0 { + t.Fatalf("%q should be a valid Log Metric Filter Name: %q", v, errors) + } + } + + invalidNames := []string{ + "Here is a name with: colon", + "and here is another * invalid name", + "*", + // length > 512 + strings.Repeat("W", 513), + } + for _, v := range invalidNames { + _, errors := validateLogMetricFilterName(v, "name") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid Log Metric Filter Name", v) + } + } +} + +func TestValidateLogMetricTransformationName(t *testing.T) { + validNames := []string{ + "YadaHereAndThere", + "Valid-5Metric_Name", + "This . is also %% valid@!)+(", + "1234", + "", + strings.Repeat("W", 255), + } + for _, v := range validNames { + _, errors := validateLogMetricFilterTransformationName(v, "name") + if len(errors) != 0 { + t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) + } + } + + invalidNames := []string{ + "Here is a name with: colon", + "and here is another * invalid name", + "also $ invalid", + "*", + // length > 255 + strings.Repeat("W", 256), + } + for _, v := range invalidNames { + _, errors := validateLogMetricFilterTransformationName(v, "name") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) + } + } +} + +func TestValidateLogGroupName(t *testing.T) { + validNames := []string{ + "ValidLogGroupName", + "ValidLogGroup.Name", + "valid/Log-group", + "1234", + "YadaValid#0123", + "Also_valid-name", + strings.Repeat("W", 512), + } + for _, v := range validNames { + _, errors := validateLogGroupName(v, "name") + if len(errors) != 0 { + t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) + } + } + + invalidNames := []string{ + "Here is a name with: colon", + "and here is another * invalid name", + "also $ invalid", + "This . is also %% invalid@!)+(", + "*", + "", + // length > 512 + strings.Repeat("W", 513), + } + for _, v := range invalidNames { + _, errors := validateLogGroupName(v, "name") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) + } + } +}