Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fixes #2384 aws_cloudwatch_log_metric_filter: default_value is automatically set to 0 #5933

Merged
merged 4 commits into from
Nov 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions aws/resource_aws_cloudwatch_log_metric_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ func resourceAwsCloudWatchLogMetricFilter() *schema.Resource {
ValidateFunc: validation.StringLenBetween(0, 100),
},
"default_value": {
Type: schema.TypeFloat,
Optional: true,
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateTypeStringNullableFloat,
},
},
},
Expand All @@ -92,14 +93,10 @@ func resourceAwsCloudWatchLogMetricFilterUpdate(d *schema.ResourceData, meta int

transformations := d.Get("metric_transformation").([]interface{})
o := transformations[0].(map[string]interface{})
metricsTransformations, err := expandCloudWachLogMetricTransformations(o)
if err != nil {
return err
}
input.MetricTransformations = metricsTransformations
input.MetricTransformations = expandCloudWatchLogMetricTransformations(o)

log.Printf("[DEBUG] Creating/Updating CloudWatch Log Metric Filter: %s", input)
_, err = conn.PutMetricFilter(&input)
_, err := conn.PutMetricFilter(&input)
if err != nil {
return fmt.Errorf("Creating/Updating CloudWatch Log Metric Filter failed: %s", err)
}
Expand Down Expand Up @@ -130,7 +127,7 @@ func resourceAwsCloudWatchLogMetricFilterRead(d *schema.ResourceData, meta inter

d.Set("name", mf.FilterName)
d.Set("pattern", mf.FilterPattern)
d.Set("metric_transformation", flattenCloudWachLogMetricTransformations(mf.MetricTransformations))
d.Set("metric_transformation", flattenCloudWatchLogMetricTransformations(mf.MetricTransformations))

return nil
}
Expand Down
9 changes: 9 additions & 0 deletions aws/resource_aws_cloudwatch_log_metric_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func TestAccAWSCloudWatchLogMetricFilter_basic(t *testing.T) {
MetricName: aws.String("AccessDeniedCount"),
MetricNamespace: aws.String("MyNamespace"),
MetricValue: aws.String("2"),
DefaultValue: aws.Float64(1),
}),
),
},
Expand Down Expand Up @@ -109,6 +110,14 @@ func testAccCheckCloudWatchLogMetricFilterTransformation(mf *cloudwatchlogs.Metr
*expected.MetricValue, *given.MetricValue)
}

if (given.DefaultValue != nil) != (expected.DefaultValue != nil) {
return fmt.Errorf("Expected default value to be present: %t, received: %t",
expected.DefaultValue != nil, given.DefaultValue != nil)
} else if (given.DefaultValue != nil) && *given.DefaultValue != *expected.DefaultValue {
return fmt.Errorf("Expected metric value: %g, received: %g",
*expected.DefaultValue, *given.DefaultValue)
}

return nil
}
}
Expand Down
15 changes: 9 additions & 6 deletions aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -1780,29 +1780,32 @@ func expandApiGatewayStageKeyOperations(d *schema.ResourceData) []*apigateway.Pa
return operations
}

func expandCloudWachLogMetricTransformations(m map[string]interface{}) ([]*cloudwatchlogs.MetricTransformation, error) {
func expandCloudWatchLogMetricTransformations(m map[string]interface{}) []*cloudwatchlogs.MetricTransformation {
transformation := cloudwatchlogs.MetricTransformation{
MetricName: aws.String(m["name"].(string)),
MetricNamespace: aws.String(m["namespace"].(string)),
MetricValue: aws.String(m["value"].(string)),
}

if m["default_value"] != "" {
transformation.DefaultValue = aws.Float64(m["default_value"].(float64))
if m["default_value"].(string) != "" {
value, _ := strconv.ParseFloat(m["default_value"].(string), 64)
transformation.DefaultValue = aws.Float64(value)
}

return []*cloudwatchlogs.MetricTransformation{&transformation}, nil
return []*cloudwatchlogs.MetricTransformation{&transformation}
}

func flattenCloudWachLogMetricTransformations(ts []*cloudwatchlogs.MetricTransformation) []interface{} {
func flattenCloudWatchLogMetricTransformations(ts []*cloudwatchlogs.MetricTransformation) []interface{} {
mts := make([]interface{}, 0)
m := make(map[string]interface{}, 0)

m["name"] = *ts[0].MetricName
m["namespace"] = *ts[0].MetricNamespace
m["value"] = *ts[0].MetricValue

if ts[0].DefaultValue != nil {
if ts[0].DefaultValue == nil {
m["default_value"] = ""
} else {
m["default_value"] = *ts[0].DefaultValue
}

Expand Down
20 changes: 20 additions & 0 deletions aws/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ func validateTypeStringNullableBoolean(v interface{}, k string) (ws []string, es
return
}

// validateTypeStringNullableFloat provides custom error messaging for TypeString floats
// Some arguments require a floating point value or an unspecified, empty field.
func validateTypeStringNullableFloat(v interface{}, k string) (ws []string, es []error) {
value, ok := v.(string)
if !ok {
es = append(es, fmt.Errorf("expected type of %s to be string", k))
return
}

if value == "" {
return
}

if _, err := strconv.ParseFloat(value, 64); err != nil {
ahl marked this conversation as resolved.
Show resolved Hide resolved
es = append(es, fmt.Errorf("%s: cannot parse '%s' as float: %s", k, value, err))
}

return
}

func validateRdsIdentifier(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
Expand Down
51 changes: 51 additions & 0 deletions aws/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,57 @@ func TestValidateTypeStringNullableBoolean(t *testing.T) {
}
}

func TestValidateTypeStringNullableFloat(t *testing.T) {
testCases := []struct {
val interface{}
expectedErr *regexp.Regexp
}{
{
val: "",
},
{
val: "0",
},
{
val: "1",
},
{
val: "42.0",
},
{
val: "threeve",
expectedErr: regexp.MustCompile(`cannot parse`),
},
}

matchErr := func(errs []error, r *regexp.Regexp) bool {
// err must match one provided
for _, err := range errs {
if r.MatchString(err.Error()) {
return true
}
}

return false
}

for i, tc := range testCases {
_, errs := validateTypeStringNullableFloat(tc.val, "test_property")

if len(errs) == 0 && tc.expectedErr == nil {
continue
}

if len(errs) != 0 && tc.expectedErr == nil {
t.Fatalf("expected test case %d to produce no errors, got %v", i, errs)
}

if !matchErr(errs, tc.expectedErr) {
t.Fatalf("expected test case %d to produce error matching \"%s\", got %v", i, tc.expectedErr, errs)
}
}
}

func TestValidateCloudWatchDashboardName(t *testing.T) {
validNames := []string{
"HelloWorl_d",
Expand Down