Skip to content

Commit

Permalink
Merge pull request #4431 from TimeIncOSS/f-aws-validators
Browse files Browse the repository at this point in the history
provider/aws: Add validation for ECR repository name
  • Loading branch information
radeksimko committed Jan 6, 2016
2 parents 265910c + d853d2c commit 2edc25e
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 110 deletions.
11 changes: 0 additions & 11 deletions builtin/providers/aws/resource_aws_autoscaling_schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,3 @@ func resourceAwsASGScheduledActionRetrieve(d *schema.ResourceData, meta interfac

return actions.ScheduledUpdateGroupActions[0], nil
}

func validateASGScheduleTimestamp(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
_, err := time.Parse(awsAutoscalingScheduleTimeLayout, value)
if err != nil {
errors = append(errors, fmt.Errorf(
"%q cannot be parsed as iso8601 Timestamp Format", value))
}

return
}
11 changes: 0 additions & 11 deletions builtin/providers/aws/resource_aws_codedeploy_deployment_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,17 +344,6 @@ func onPremisesTagFiltersToMap(list []*codedeploy.TagFilter) []map[string]string
return result
}

// validateTagFilters confirms the "value" component of a tag filter is one of
// AWS's three allowed types.
func validateTagFilters(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if value != "KEY_ONLY" && value != "VALUE_ONLY" && value != "KEY_AND_VALUE" {
errors = append(errors, fmt.Errorf(
"%q must be one of \"KEY_ONLY\", \"VALUE_ONLY\", or \"KEY_AND_VALUE\"", k))
}
return
}

func resourceAwsCodeDeployTagFilterHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
Expand Down
27 changes: 0 additions & 27 deletions builtin/providers/aws/resource_aws_db_parameter_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"log"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -285,29 +284,3 @@ func buildRDSPGARN(d *schema.ResourceData, meta interface{}) (string, error) {
arn := fmt.Sprintf("arn:aws:rds:%s:%s:pg:%s", region, accountID, d.Id())
return arn, nil
}

func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only lowercase alphanumeric characters and hyphens allowed in %q", k))
}
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"first character of %q must be a letter", k))
}
if regexp.MustCompile(`--`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot contain two consecutive hyphens", k))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen", k))
}
if len(value) > 255 {
errors = append(errors, fmt.Errorf(
"%q cannot be greater than 255 characters", k))
}
return

}
15 changes: 0 additions & 15 deletions builtin/providers/aws/resource_aws_dynamodb_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -833,18 +833,3 @@ func waitForTableToBeActive(tableName string, meta interface{}) error {
return nil

}

func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
viewTypes := map[string]bool{
"KEYS_ONLY": true,
"NEW_IMAGE": true,
"OLD_IMAGE": true,
"NEW_AND_OLD_IMAGES": true,
}

if !viewTypes[value] {
errors = append(errors, fmt.Errorf("%q be a valid DynamoDB StreamViewType", k))
}
return
}
24 changes: 0 additions & 24 deletions builtin/providers/aws/resource_aws_elb.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"log"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -673,29 +672,6 @@ func isLoadBalancerNotFound(err error) bool {
return ok && elberr.Code() == "LoadBalancerNotFound"
}

func validateElbName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only alphanumeric characters and hyphens allowed in %q: %q",
k, value))
}
if len(value) > 32 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 32 characters: %q", k, value))
}
if regexp.MustCompile(`^-`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot begin with a hyphen: %q", k, value))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen: %q", k, value))
}
return

}

func sourceSGIdByName(meta interface{}, sg, vpcId string) (string, error) {
conn := meta.(*AWSClient).ec2conn
var filters []*ec2.Filter
Expand Down
22 changes: 0 additions & 22 deletions builtin/providers/aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"regexp"
"sort"
"strings"

Expand Down Expand Up @@ -516,27 +515,6 @@ func expandResourceRecords(recs []interface{}, typeStr string) []*route53.Resour
return records
}

func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only lowercase alphanumeric characters and hyphens allowed in %q", k))
}
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"first character of %q must be a letter", k))
}
if regexp.MustCompile(`--`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot contain two consecutive hyphens", k))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen", k))
}
return
}

func expandESClusterConfig(m map[string]interface{}) *elasticsearch.ElasticsearchClusterConfig {
config := elasticsearch.ElasticsearchClusterConfig{}

Expand Down
136 changes: 136 additions & 0 deletions builtin/providers/aws/validators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package aws

import (
"fmt"
"regexp"
"time"
)

func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only lowercase alphanumeric characters and hyphens allowed in %q", k))
}
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"first character of %q must be a letter", k))
}
if regexp.MustCompile(`--`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot contain two consecutive hyphens", k))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen", k))
}
return
}

func validateASGScheduleTimestamp(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
_, err := time.Parse(awsAutoscalingScheduleTimeLayout, value)
if err != nil {
errors = append(errors, fmt.Errorf(
"%q cannot be parsed as iso8601 Timestamp Format", value))
}

return
}

// validateTagFilters confirms the "value" component of a tag filter is one of
// AWS's three allowed types.
func validateTagFilters(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if value != "KEY_ONLY" && value != "VALUE_ONLY" && value != "KEY_AND_VALUE" {
errors = append(errors, fmt.Errorf(
"%q must be one of \"KEY_ONLY\", \"VALUE_ONLY\", or \"KEY_AND_VALUE\"", k))
}
return
}

func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only lowercase alphanumeric characters and hyphens allowed in %q", k))
}
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"first character of %q must be a letter", k))
}
if regexp.MustCompile(`--`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot contain two consecutive hyphens", k))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen", k))
}
if len(value) > 255 {
errors = append(errors, fmt.Errorf(
"%q cannot be greater than 255 characters", k))
}
return

}

func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
viewTypes := map[string]bool{
"KEYS_ONLY": true,
"NEW_IMAGE": true,
"OLD_IMAGE": true,
"NEW_AND_OLD_IMAGES": true,
}

if !viewTypes[value] {
errors = append(errors, fmt.Errorf("%q be a valid DynamoDB StreamViewType", k))
}
return
}

func validateElbName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only alphanumeric characters and hyphens allowed in %q: %q",
k, value))
}
if len(value) > 32 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 32 characters: %q", k, value))
}
if regexp.MustCompile(`^-`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot begin with a hyphen: %q", k, value))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen: %q", k, value))
}
return

}

func validateEcrRepositoryName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if len(value) < 2 {
errors = append(errors, fmt.Errorf(
"%q must be at least 2 characters long: %q", k, value))
}
if len(value) > 256 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 256 characters: %q", k, value))
}

// http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_CreateRepository.html
pattern := `^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$`
if !regexp.MustCompile(pattern).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q doesn't comply with restrictions (%q): %q",
k, pattern, value))
}

return
}
45 changes: 45 additions & 0 deletions builtin/providers/aws/validators_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package aws

import (
"testing"
)

func TestValidateEcrRepositoryName(t *testing.T) {
validNames := []string{
"nginx-web-app",
"project-a/nginx-web-app",
"domain.ltd/nginx-web-app",
"3chosome-thing.com/01different-pattern",
"0123456789/999999999",
"double/forward/slash",
"000000000000000",
}
for _, v := range validNames {
_, errors := validateEcrRepositoryName(v, "name")
if len(errors) != 0 {
t.Fatalf("%q should be a valid ECR repository name: %q", v, errors)
}
}

invalidNames := []string{
// length > 256
"3cho_some-thing.com/01different.-_pattern01different.-_pattern01diff" +
"erent.-_pattern01different.-_pattern01different.-_pattern01different" +
".-_pattern01different.-_pattern01different.-_pattern01different.-_pa" +
"ttern01different.-_pattern01different.-_pattern234567",
// length < 2
"i",
"special@character",
"different+special=character",
"double//slash",
"double..dot",
"/slash-at-the-beginning",
"slash-at-the-end/",
}
for _, v := range invalidNames {
_, errors := validateEcrRepositoryName(v, "name")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid ECR repository name", v)
}
}
}

0 comments on commit 2edc25e

Please sign in to comment.