provider/aws: Add JSON validation to the aws_cloudwatch_event_rule resource. (#8897)

* Add JSON validation to the aws_cloudwatch_event_rule resource.

This commit adds support for new helper function which is used to
normalise and validate JSON string. Also adds new validation function
to wrap around the aforementioned helper.

Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>

* Re-factor validation function.

This commit changes the logic of the function so that it would check length of
the normalised JSON string over the given string, plus short-circuit early
should JSON would not be valid.

Signed-off-by: Krzysztof Wilczynski <krzysztof.wilczynski@linux.com>
This commit is contained in:
Krzysztof Wilczynski 2016-09-19 23:47:17 +01:00 committed by Radek Simko
parent e58c6cf7da
commit 9ef9956ee2
2 changed files with 89 additions and 4 deletions

View File

@ -39,8 +39,11 @@ func resourceAwsCloudWatchEventRule() *schema.Resource {
"event_pattern": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateMaxLength(2048),
StateFunc: normalizeJson,
ValidateFunc: validateEventPatternValue(2048),
StateFunc: func(v interface{}) string {
json, _ := normalizeJsonString(v)
return json
},
},
"description": &schema.Schema{
Type: schema.TypeString,
@ -123,7 +126,8 @@ func resourceAwsCloudWatchEventRuleRead(d *schema.ResourceData, meta interface{}
d.Set("arn", out.Arn)
d.Set("description", out.Description)
if out.EventPattern != nil {
d.Set("event_pattern", normalizeJson(*out.EventPattern))
pattern, _ := normalizeJsonString(*out.EventPattern)
d.Set("event_pattern", pattern)
}
d.Set("name", out.Name)
d.Set("role_arn", out.RoleArn)
@ -214,7 +218,8 @@ func buildPutRuleInputStruct(d *schema.ResourceData) *events.PutRuleInput {
input.Description = aws.String(v.(string))
}
if v, ok := d.GetOk("event_pattern"); ok {
input.EventPattern = aws.String(normalizeJson(v.(string)))
pattern, _ := normalizeJsonString(v.(string))
input.EventPattern = aws.String(pattern)
}
if v, ok := d.GetOk("role_arn"); ok {
input.RoleArn = aws.String(v.(string))
@ -247,3 +252,24 @@ func getStringStateFromBoolean(isEnabled bool) string {
}
return "DISABLED"
}
func validateEventPatternValue(length int) schema.SchemaValidateFunc {
return func(v interface{}, k string) (ws []string, errors []error) {
json, err := normalizeJsonString(v)
if err != nil {
errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err))
// Invalid JSON? Return immediately,
// there is no need to collect other
// errors.
return
}
// Check whether the normalized JSON is within the given length.
if len(json) > length {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than %d characters: %q", k, length, json))
}
return
}
}

View File

@ -6,6 +6,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
events "github.com/aws/aws-sdk-go/service/cloudwatchevents"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
@ -165,6 +166,64 @@ func testAccCheckAWSCloudWatchEventRuleDestroy(s *terraform.State) error {
return nil
}
func TestResourceAWSCloudWatchEventRule_validateEventPatternValue(t *testing.T) {
type testCases struct {
Length int
Value string
ErrCount int
}
invalidCases := []testCases{
{
Length: 8,
Value: acctest.RandString(16),
ErrCount: 1,
},
{
Length: 123,
Value: `{"abc":}`,
ErrCount: 1,
},
{
Length: 1,
Value: `{"abc":["1","2"]}`,
ErrCount: 1,
},
}
for _, tc := range invalidCases {
_, errors := validateEventPatternValue(tc.Length)(tc.Value, "event_pattern")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected %q to trigger a validation error.", tc.Value)
}
}
validCases := []testCases{
{
Length: 0,
Value: ``,
ErrCount: 0,
},
{
Length: 2,
Value: `{}`,
ErrCount: 0,
},
{
Length: 18,
Value: `{"abc":["1","2"]}`,
ErrCount: 0,
},
}
for _, tc := range validCases {
_, errors := validateEventPatternValue(tc.Length)(tc.Value, "event_pattern")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected %q not to trigger a validation error.", tc.Value)
}
}
}
var testAccAWSCloudWatchEventRuleConfig = `
resource "aws_cloudwatch_event_rule" "foo" {
name = "tf-acc-cw-event-rule"