Add `name_prefix` to RDS resources (#13232)
Adds `name_prefix` (or, in some cases, `identifier_prefix`) support to all AWS RDS resources.
This commit is contained in:
parent
e7c3e8df68
commit
d25c310468
|
@ -101,11 +101,19 @@ func resourceAwsDbInstance() *schema.Resource {
|
|||
},
|
||||
|
||||
"identifier": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"identifier_prefix"},
|
||||
ValidateFunc: validateRdsIdentifier,
|
||||
},
|
||||
"identifier_prefix": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateRdsId,
|
||||
ValidateFunc: validateRdsIdentifierPrefix,
|
||||
},
|
||||
|
||||
"instance_class": {
|
||||
|
@ -336,10 +344,16 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
|
|||
conn := meta.(*AWSClient).rdsconn
|
||||
tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
|
||||
|
||||
identifier := d.Get("identifier").(string)
|
||||
// Generate a unique ID for the user
|
||||
if identifier == "" {
|
||||
identifier = resource.PrefixedUniqueId("tf-")
|
||||
var identifier string
|
||||
if v, ok := d.GetOk("identifier"); ok {
|
||||
identifier = v.(string)
|
||||
} else {
|
||||
if v, ok := d.GetOk("identifier_prefix"); ok {
|
||||
identifier = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
identifier = resource.UniqueId()
|
||||
}
|
||||
|
||||
// SQL Server identifier size is max 15 chars, so truncate
|
||||
if engine := d.Get("engine").(string); engine != "" {
|
||||
if strings.Contains(strings.ToLower(engine), "sqlserver") {
|
||||
|
|
|
@ -53,6 +53,46 @@ func TestAccAWSDBInstance_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBInstance_namePrefix(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSDBInstanceConfig_namePrefix,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBInstanceExists("aws_db_instance.test", &v),
|
||||
testAccCheckAWSDBInstanceAttributes(&v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_db_instance.test", "identifier", regexp.MustCompile("^tf-test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBInstance_generatedName(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSDBInstanceConfig_generatedName,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBInstanceExists("aws_db_instance.test", &v),
|
||||
testAccCheckAWSDBInstanceAttributes(&v),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBInstance_kmsKey(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
keyRegex := regexp.MustCompile("^arn:aws:kms:")
|
||||
|
@ -613,8 +653,8 @@ resource "aws_db_instance" "bar" {
|
|||
username = "foo"
|
||||
|
||||
|
||||
# Maintenance Window is stored in lower case in the API, though not strictly
|
||||
# documented. Terraform will downcase this to match (as opposed to throw a
|
||||
# Maintenance Window is stored in lower case in the API, though not strictly
|
||||
# documented. Terraform will downcase this to match (as opposed to throw a
|
||||
# validation error).
|
||||
maintenance_window = "Fri:09:00-Fri:09:30"
|
||||
skip_final_snapshot = true
|
||||
|
@ -628,6 +668,39 @@ resource "aws_db_instance" "bar" {
|
|||
}
|
||||
}`
|
||||
|
||||
const testAccAWSDBInstanceConfig_namePrefix = `
|
||||
resource "aws_db_instance" "test" {
|
||||
allocated_storage = 10
|
||||
engine = "MySQL"
|
||||
identifier_prefix = "tf-test-"
|
||||
instance_class = "db.t1.micro"
|
||||
password = "password"
|
||||
username = "root"
|
||||
security_group_names = ["default"]
|
||||
publicly_accessible = true
|
||||
skip_final_snapshot = true
|
||||
|
||||
timeouts {
|
||||
create = "30m"
|
||||
}
|
||||
}`
|
||||
|
||||
const testAccAWSDBInstanceConfig_generatedName = `
|
||||
resource "aws_db_instance" "test" {
|
||||
allocated_storage = 10
|
||||
engine = "MySQL"
|
||||
instance_class = "db.t1.micro"
|
||||
password = "password"
|
||||
username = "root"
|
||||
security_group_names = ["default"]
|
||||
publicly_accessible = true
|
||||
skip_final_snapshot = true
|
||||
|
||||
timeouts {
|
||||
create = "30m"
|
||||
}
|
||||
}`
|
||||
|
||||
var testAccAWSDBInstanceConfigKmsKeyId = `
|
||||
resource "aws_kms_key" "foo" {
|
||||
description = "Terraform acc test %s"
|
||||
|
@ -720,7 +793,7 @@ func testAccReplicaInstanceConfig(val int) string {
|
|||
|
||||
parameter_group_name = "default.mysql5.6"
|
||||
}
|
||||
|
||||
|
||||
resource "aws_db_instance" "replica" {
|
||||
identifier = "tf-replica-db-%d"
|
||||
backup_retention_period = 0
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
@ -31,10 +30,19 @@ func resourceAwsDbOptionGroup() *schema.Resource {
|
|||
Computed: true,
|
||||
},
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"name_prefix"},
|
||||
ValidateFunc: validateDbOptionGroupName,
|
||||
},
|
||||
"name_prefix": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
ValidateFunc: validateDbOptionGroupName,
|
||||
ValidateFunc: validateDbOptionGroupNamePrefix,
|
||||
},
|
||||
"engine_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
|
@ -48,8 +56,9 @@ func resourceAwsDbOptionGroup() *schema.Resource {
|
|||
},
|
||||
"option_group_description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: "Managed by Terraform",
|
||||
},
|
||||
|
||||
"option": &schema.Schema{
|
||||
|
@ -107,11 +116,20 @@ func resourceAwsDbOptionGroupCreate(d *schema.ResourceData, meta interface{}) er
|
|||
rdsconn := meta.(*AWSClient).rdsconn
|
||||
tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
|
||||
|
||||
var groupName string
|
||||
if v, ok := d.GetOk("name"); ok {
|
||||
groupName = v.(string)
|
||||
} else if v, ok := d.GetOk("name_prefix"); ok {
|
||||
groupName = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
groupName = resource.UniqueId()
|
||||
}
|
||||
|
||||
createOpts := &rds.CreateOptionGroupInput{
|
||||
EngineName: aws.String(d.Get("engine_name").(string)),
|
||||
MajorEngineVersion: aws.String(d.Get("major_engine_version").(string)),
|
||||
OptionGroupDescription: aws.String(d.Get("option_group_description").(string)),
|
||||
OptionGroupName: aws.String(d.Get("name").(string)),
|
||||
OptionGroupName: aws.String(groupName),
|
||||
Tags: tags,
|
||||
}
|
||||
|
||||
|
@ -121,7 +139,7 @@ func resourceAwsDbOptionGroupCreate(d *schema.ResourceData, meta interface{}) er
|
|||
return fmt.Errorf("Error creating DB Option Group: %s", err)
|
||||
}
|
||||
|
||||
d.SetId(d.Get("name").(string))
|
||||
d.SetId(groupName)
|
||||
log.Printf("[INFO] DB Option Group ID: %s", d.Id())
|
||||
|
||||
return resourceAwsDbOptionGroupUpdate(d, meta)
|
||||
|
@ -343,28 +361,3 @@ func buildRDSOptionGroupARN(identifier, partition, accountid, region string) (st
|
|||
arn := fmt.Sprintf("arn:%s:rds:%s:%s:og:%s", partition, region, accountid, identifier)
|
||||
return arn, nil
|
||||
}
|
||||
|
||||
func validateDbOptionGroupName(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"first character of %q must be a letter", k))
|
||||
}
|
||||
if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"only alphanumeric characters and hyphens allowed in %q", 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
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package aws
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
@ -34,6 +35,66 @@ func TestAccAWSDBOptionGroup_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBOptionGroup_namePrefix(t *testing.T) {
|
||||
var v rds.OptionGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBOptionGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSDBOptionGroup_namePrefix,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBOptionGroupExists("aws_db_option_group.test", &v),
|
||||
testAccCheckAWSDBOptionGroupAttributes(&v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_db_option_group.test", "name", regexp.MustCompile("^tf-test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBOptionGroup_generatedName(t *testing.T) {
|
||||
var v rds.OptionGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBOptionGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSDBOptionGroup_generatedName,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBOptionGroupExists("aws_db_option_group.test", &v),
|
||||
testAccCheckAWSDBOptionGroupAttributes(&v),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBOptionGroup_defaultDescription(t *testing.T) {
|
||||
var v rds.OptionGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBOptionGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSDBOptionGroup_defaultDescription(acctest.RandInt()),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBOptionGroupExists("aws_db_option_group.test", &v),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_db_option_group.test", "option_group_description", "Managed by Terraform"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBOptionGroup_basicDestroyWithInstance(t *testing.T) {
|
||||
rName := fmt.Sprintf("option-group-test-terraform-%s", acctest.RandString(5))
|
||||
|
||||
|
@ -160,42 +221,6 @@ func testAccCheckAWSDBOptionGroupAttributes(v *rds.OptionGroup) resource.TestChe
|
|||
}
|
||||
}
|
||||
|
||||
func TestResourceAWSDBOptionGroupName_validation(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "testing123!",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "1testing123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing--123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing123-",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(256),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateDbOptionGroupName(tc.Value, "aws_db_option_group_name")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Option Group Name to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSDBOptionGroupExists(n string, v *rds.OptionGroup) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
|
@ -387,3 +412,30 @@ resource "aws_db_option_group" "bar" {
|
|||
}
|
||||
`, r)
|
||||
}
|
||||
|
||||
const testAccAWSDBOptionGroup_namePrefix = `
|
||||
resource "aws_db_option_group" "test" {
|
||||
name_prefix = "tf-test-"
|
||||
option_group_description = "Test option group for terraform"
|
||||
engine_name = "mysql"
|
||||
major_engine_version = "5.6"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccAWSDBOptionGroup_generatedName = `
|
||||
resource "aws_db_option_group" "test" {
|
||||
option_group_description = "Test option group for terraform"
|
||||
engine_name = "mysql"
|
||||
major_engine_version = "5.6"
|
||||
}
|
||||
`
|
||||
|
||||
func testAccAWSDBOptionGroup_defaultDescription(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_db_option_group" "test" {
|
||||
name = "tf-test-%d"
|
||||
engine_name = "mysql"
|
||||
major_engine_version = "5.6"
|
||||
}
|
||||
`, n)
|
||||
}
|
||||
|
|
|
@ -32,10 +32,19 @@ func resourceAwsDbParameterGroup() *schema.Resource {
|
|||
Computed: true,
|
||||
},
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"name_prefix"},
|
||||
ValidateFunc: validateDbParamGroupName,
|
||||
},
|
||||
"name_prefix": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
ValidateFunc: validateDbParamGroupName,
|
||||
ValidateFunc: validateDbParamGroupNamePrefix,
|
||||
},
|
||||
"family": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
|
@ -81,8 +90,17 @@ func resourceAwsDbParameterGroupCreate(d *schema.ResourceData, meta interface{})
|
|||
rdsconn := meta.(*AWSClient).rdsconn
|
||||
tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
|
||||
|
||||
var groupName string
|
||||
if v, ok := d.GetOk("name"); ok {
|
||||
groupName = v.(string)
|
||||
} else if v, ok := d.GetOk("name_prefix"); ok {
|
||||
groupName = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
groupName = resource.UniqueId()
|
||||
}
|
||||
|
||||
createOpts := rds.CreateDBParameterGroupInput{
|
||||
DBParameterGroupName: aws.String(d.Get("name").(string)),
|
||||
DBParameterGroupName: aws.String(groupName),
|
||||
DBParameterGroupFamily: aws.String(d.Get("family").(string)),
|
||||
Description: aws.String(d.Get("description").(string)),
|
||||
Tags: tags,
|
||||
|
|
|
@ -3,6 +3,7 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -290,6 +291,44 @@ func TestAccAWSDBParameterGroup_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBParameterGroup_namePrefix(t *testing.T) {
|
||||
var v rds.DBParameterGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBParameterGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBParameterGroupConfig_namePrefix,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBParameterGroupExists("aws_db_parameter_group.test", &v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_db_parameter_group.test", "name", regexp.MustCompile("^tf-test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBParameterGroup_generatedName(t *testing.T) {
|
||||
var v rds.DBParameterGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBParameterGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBParameterGroupConfig_generatedName,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBParameterGroupExists("aws_db_parameter_group.test", &v),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBParameterGroup_withApplyMethod(t *testing.T) {
|
||||
var v rds.DBParameterGroup
|
||||
|
||||
|
@ -671,3 +710,16 @@ resource "aws_db_parameter_group" "large" {
|
|||
parameter { name = "tx_isolation" value = "REPEATABLE-READ" }
|
||||
}`, n)
|
||||
}
|
||||
|
||||
const testAccDBParameterGroupConfig_namePrefix = `
|
||||
resource "aws_db_parameter_group" "test" {
|
||||
name_prefix = "tf-test-"
|
||||
family = "mysql5.6"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBParameterGroupConfig_generatedName = `
|
||||
resource "aws_db_parameter_group" "test" {
|
||||
family = "mysql5.6"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -3,7 +3,6 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -31,10 +30,19 @@ func resourceAwsDbSubnetGroup() *schema.Resource {
|
|||
},
|
||||
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"name_prefix"},
|
||||
ValidateFunc: validateDbSubnetGroupName,
|
||||
},
|
||||
"name_prefix": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
ValidateFunc: validateSubnetGroupName,
|
||||
ValidateFunc: validateDbSubnetGroupNamePrefix,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
|
@ -65,8 +73,17 @@ func resourceAwsDbSubnetGroupCreate(d *schema.ResourceData, meta interface{}) er
|
|||
subnetIds[i] = aws.String(subnetId.(string))
|
||||
}
|
||||
|
||||
var groupName string
|
||||
if v, ok := d.GetOk("name"); ok {
|
||||
groupName = v.(string)
|
||||
} else if v, ok := d.GetOk("name_prefix"); ok {
|
||||
groupName = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
groupName = resource.UniqueId()
|
||||
}
|
||||
|
||||
createOpts := rds.CreateDBSubnetGroupInput{
|
||||
DBSubnetGroupName: aws.String(d.Get("name").(string)),
|
||||
DBSubnetGroupName: aws.String(groupName),
|
||||
DBSubnetGroupDescription: aws.String(d.Get("description").(string)),
|
||||
SubnetIds: subnetIds,
|
||||
Tags: tags,
|
||||
|
@ -238,20 +255,3 @@ func buildRDSsubgrpARN(identifier, partition, accountid, region string) (string,
|
|||
return arn, nil
|
||||
|
||||
}
|
||||
|
||||
func validateSubnetGroupName(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, hyphens, underscores, periods, and spaces allowed in %q", k))
|
||||
}
|
||||
if len(value) > 255 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be longer than 255 characters", k))
|
||||
}
|
||||
if regexp.MustCompile(`(?i)^default$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q is not allowed as %q", "Default", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package aws
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
|
@ -43,6 +44,46 @@ func TestAccAWSDBSubnetGroup_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBSubnetGroup_namePrefix(t *testing.T) {
|
||||
var v rds.DBSubnetGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBSubnetGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBSubnetGroupConfig_namePrefix,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBSubnetGroupExists(
|
||||
"aws_db_subnet_group.test", &v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_db_subnet_group.test", "name", regexp.MustCompile("^tf_test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBSubnetGroup_generatedName(t *testing.T) {
|
||||
var v rds.DBSubnetGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBSubnetGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBSubnetGroupConfig_generatedName,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBSubnetGroupExists(
|
||||
"aws_db_subnet_group.test", &v),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/hashicorp/terraform/issues/2603 and
|
||||
// https://github.com/hashicorp/terraform/issues/2664
|
||||
func TestAccAWSDBSubnetGroup_withUndocumentedCharacters(t *testing.T) {
|
||||
|
@ -105,38 +146,6 @@ func TestAccAWSDBSubnetGroup_updateDescription(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestResourceAWSDBSubnetGroupNameValidation(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "tEsting",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing?",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "default",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(300),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateSubnetGroupName(tc.Value, "aws_db_subnet_group")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Subnet Group name to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckDBSubnetGroupDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).rdsconn
|
||||
|
||||
|
@ -263,6 +272,49 @@ resource "aws_db_subnet_group" "foo" {
|
|||
}`, rName)
|
||||
}
|
||||
|
||||
const testAccDBSubnetGroupConfig_namePrefix = `
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
name_prefix = "tf_test-"
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}`
|
||||
|
||||
const testAccDBSubnetGroupConfig_generatedName = `
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.1.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.1.2.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}`
|
||||
|
||||
const testAccDBSubnetGroupConfig_withUnderscoresAndPeriodsAndSpaces = `
|
||||
resource "aws_vpc" "main" {
|
||||
cidr_block = "192.168.0.0/16"
|
||||
|
|
|
@ -36,10 +36,19 @@ func resourceAwsRDSCluster() *schema.Resource {
|
|||
},
|
||||
|
||||
"cluster_identifier": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"cluster_identifier_prefix"},
|
||||
ValidateFunc: validateRdsIdentifier,
|
||||
},
|
||||
"cluster_identifier_prefix": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateRdsId,
|
||||
ValidateFunc: validateRdsIdentifierPrefix,
|
||||
},
|
||||
|
||||
"cluster_members": {
|
||||
|
@ -225,6 +234,19 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error
|
|||
conn := meta.(*AWSClient).rdsconn
|
||||
tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
|
||||
|
||||
var identifier string
|
||||
if v, ok := d.GetOk("cluster_identifier"); ok {
|
||||
identifier = v.(string)
|
||||
} else {
|
||||
if v, ok := d.GetOk("cluster_identifier_prefix"); ok {
|
||||
identifier = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
identifier = resource.PrefixedUniqueId("tf-")
|
||||
}
|
||||
|
||||
d.Set("cluster_identifier", identifier)
|
||||
}
|
||||
|
||||
if _, ok := d.GetOk("snapshot_identifier"); ok {
|
||||
opts := rds.RestoreDBClusterFromSnapshotInput{
|
||||
DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)),
|
||||
|
|
|
@ -24,10 +24,19 @@ func resourceAwsRDSClusterInstance() *schema.Resource {
|
|||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"identifier": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"identifier_prefix"},
|
||||
ValidateFunc: validateRdsIdentifier,
|
||||
},
|
||||
"identifier_prefix": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateRdsId,
|
||||
ValidateFunc: validateRdsIdentifierPrefix,
|
||||
},
|
||||
|
||||
"db_subnet_group_name": {
|
||||
|
@ -162,10 +171,14 @@ func resourceAwsRDSClusterInstanceCreate(d *schema.ResourceData, meta interface{
|
|||
createOpts.DBParameterGroupName = aws.String(attr.(string))
|
||||
}
|
||||
|
||||
if v := d.Get("identifier").(string); v != "" {
|
||||
createOpts.DBInstanceIdentifier = aws.String(v)
|
||||
if v, ok := d.GetOk("identifier"); ok {
|
||||
createOpts.DBInstanceIdentifier = aws.String(v.(string))
|
||||
} else {
|
||||
createOpts.DBInstanceIdentifier = aws.String(resource.UniqueId())
|
||||
if v, ok := d.GetOk("identifier_prefix"); ok {
|
||||
createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId(v.(string)))
|
||||
} else {
|
||||
createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId("tf-"))
|
||||
}
|
||||
}
|
||||
|
||||
if attr, ok := d.GetOk("db_subnet_group_name"); ok {
|
||||
|
|
|
@ -46,6 +46,48 @@ func TestAccAWSRDSClusterInstance_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSClusterInstance_namePrefix(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSClusterDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSClusterInstanceConfig_namePrefix(acctest.RandInt()),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSClusterInstanceExists("aws_rds_cluster_instance.test", &v),
|
||||
testAccCheckAWSDBClusterInstanceAttributes(&v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_rds_cluster_instance.test", "identifier", regexp.MustCompile("^tf-cluster-instance-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSClusterInstance_generatedName(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSClusterDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSClusterInstanceConfig_generatedName(acctest.RandInt()),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSClusterInstanceExists("aws_rds_cluster_instance.test", &v),
|
||||
testAccCheckAWSDBClusterInstanceAttributes(&v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_rds_cluster_instance.test", "identifier", regexp.MustCompile("^tf-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSClusterInstance_kmsKey(t *testing.T) {
|
||||
var v rds.DBInstance
|
||||
keyRegex := regexp.MustCompile("^arn:aws:kms:")
|
||||
|
@ -256,6 +298,83 @@ resource "aws_db_parameter_group" "bar" {
|
|||
`, n, n, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterInstanceConfig_namePrefix(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_rds_cluster_instance" "test" {
|
||||
identifier_prefix = "tf-cluster-instance-"
|
||||
cluster_identifier = "${aws_rds_cluster.test.id}"
|
||||
instance_class = "db.r3.large"
|
||||
}
|
||||
|
||||
resource "aws_rds_cluster" "test" {
|
||||
cluster_identifier = "tf-aurora-cluster-%d"
|
||||
master_username = "root"
|
||||
master_password = "password"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.test.name}"
|
||||
skip_final_snapshot = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.0.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.1.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
name = "tf-test-%d"
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}
|
||||
`, n, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterInstanceConfig_generatedName(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_rds_cluster_instance" "test" {
|
||||
cluster_identifier = "${aws_rds_cluster.test.id}"
|
||||
instance_class = "db.r3.large"
|
||||
}
|
||||
|
||||
resource "aws_rds_cluster" "test" {
|
||||
cluster_identifier = "tf-aurora-cluster-%d"
|
||||
master_username = "root"
|
||||
master_password = "password"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.test.name}"
|
||||
skip_final_snapshot = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.0.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.1.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
name = "tf-test-%d"
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}
|
||||
`, n, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterInstanceConfigKmsKey(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
|
||||
|
|
|
@ -29,10 +29,19 @@ func resourceAwsRDSClusterParameterGroup() *schema.Resource {
|
|||
Computed: true,
|
||||
},
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ConflictsWith: []string{"name_prefix"},
|
||||
ValidateFunc: validateDbParamGroupName,
|
||||
},
|
||||
"name_prefix": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
ValidateFunc: validateDbParamGroupName,
|
||||
ValidateFunc: validateDbParamGroupNamePrefix,
|
||||
},
|
||||
"family": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
|
@ -86,8 +95,17 @@ func resourceAwsRDSClusterParameterGroupCreate(d *schema.ResourceData, meta inte
|
|||
rdsconn := meta.(*AWSClient).rdsconn
|
||||
tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))
|
||||
|
||||
var groupName string
|
||||
if v, ok := d.GetOk("name"); ok {
|
||||
groupName = v.(string)
|
||||
} else if v, ok := d.GetOk("name_prefix"); ok {
|
||||
groupName = resource.PrefixedUniqueId(v.(string))
|
||||
} else {
|
||||
groupName = resource.UniqueId()
|
||||
}
|
||||
|
||||
createOpts := rds.CreateDBClusterParameterGroupInput{
|
||||
DBClusterParameterGroupName: aws.String(d.Get("name").(string)),
|
||||
DBClusterParameterGroupName: aws.String(groupName),
|
||||
DBParameterGroupFamily: aws.String(d.Get("family").(string)),
|
||||
Description: aws.String(d.Get("description").(string)),
|
||||
Tags: tags,
|
||||
|
|
|
@ -3,6 +3,7 @@ package aws
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -90,6 +91,44 @@ func TestAccAWSDBClusterParameterGroup_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBClusterParameterGroup_namePrefix(t *testing.T) {
|
||||
var v rds.DBClusterParameterGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBClusterParameterGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSDBClusterParameterGroupConfig_namePrefix,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.test", &v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_rds_cluster_parameter_group.test", "name", regexp.MustCompile("^tf-test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBClusterParameterGroup_generatedName(t *testing.T) {
|
||||
var v rds.DBClusterParameterGroup
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSDBClusterParameterGroupDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSDBClusterParameterGroupConfig_generatedName,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.test", &v),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSDBClusterParameterGroup_disappears(t *testing.T) {
|
||||
var v rds.DBClusterParameterGroup
|
||||
|
||||
|
@ -365,3 +404,15 @@ func testAccAWSDBClusterParameterGroupOnlyConfig(name string) string {
|
|||
family = "aurora5.6"
|
||||
}`, name)
|
||||
}
|
||||
|
||||
const testAccAWSDBClusterParameterGroupConfig_namePrefix = `
|
||||
resource "aws_rds_cluster_parameter_group" "test" {
|
||||
name_prefix = "tf-test-"
|
||||
family = "aurora5.6"
|
||||
}
|
||||
`
|
||||
const testAccAWSDBClusterParameterGroupConfig_generatedName = `
|
||||
resource "aws_rds_cluster_parameter_group" "test" {
|
||||
family = "aurora5.6"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -40,6 +40,46 @@ func TestAccAWSRDSCluster_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSCluster_namePrefix(t *testing.T) {
|
||||
var v rds.DBCluster
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSClusterDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSClusterConfig_namePrefix(acctest.RandInt()),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSClusterExists("aws_rds_cluster.test", &v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-test-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSCluster_generatedName(t *testing.T) {
|
||||
var v rds.DBCluster
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSClusterDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSClusterConfig_generatedName(acctest.RandInt()),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSClusterExists("aws_rds_cluster.test", &v),
|
||||
resource.TestMatchResourceAttr(
|
||||
"aws_rds_cluster.test", "cluster_identifier", regexp.MustCompile("^tf-")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSRDSCluster_takeFinalSnapshot(t *testing.T) {
|
||||
var v rds.DBCluster
|
||||
rInt := acctest.RandInt()
|
||||
|
@ -322,6 +362,71 @@ resource "aws_rds_cluster" "default" {
|
|||
}`, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterConfig_namePrefix(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_rds_cluster" "test" {
|
||||
cluster_identifier_prefix = "tf-test-"
|
||||
master_username = "root"
|
||||
master_password = "password"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.test.name}"
|
||||
skip_final_snapshot = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.0.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.1.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
name = "tf-test-%d"
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}
|
||||
`, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterConfig_generatedName(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_rds_cluster" "test" {
|
||||
master_username = "root"
|
||||
master_password = "password"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.test.name}"
|
||||
skip_final_snapshot = true
|
||||
}
|
||||
|
||||
resource "aws_vpc" "test" {
|
||||
cidr_block = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "a" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.0.0/24"
|
||||
availability_zone = "us-west-2a"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "b" {
|
||||
vpc_id = "${aws_vpc.test.id}"
|
||||
cidr_block = "10.0.1.0/24"
|
||||
availability_zone = "us-west-2b"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "test" {
|
||||
name = "tf-test-%d"
|
||||
subnet_ids = ["${aws_subnet.a.id}", "${aws_subnet.b.id}"]
|
||||
}
|
||||
`, n)
|
||||
}
|
||||
|
||||
func testAccAWSClusterConfigWithFinalSnapshot(n int) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_rds_cluster" "default" {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
|
||||
func validateRdsIdentifier(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
|
@ -33,6 +33,23 @@ func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
|
|||
return
|
||||
}
|
||||
|
||||
func validateRdsIdentifierPrefix(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))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateElastiCacheClusterId(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
if (len(value) < 1) || (len(value) > 20) {
|
||||
|
@ -103,7 +120,27 @@ func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []er
|
|||
"%q cannot be greater than 255 characters", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateDbParamGroupNamePrefix(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 len(value) > 255 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be greater than 226 characters", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
@ -1041,3 +1078,79 @@ func validateApiGatewayUsagePlanQuotaSettings(v map[string]interface{}) (errors
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
func validateDbSubnetGroupName(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, hyphens, underscores, periods, and spaces allowed in %q", k))
|
||||
}
|
||||
if len(value) > 255 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be longer than 255 characters", k))
|
||||
}
|
||||
if regexp.MustCompile(`(?i)^default$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q is not allowed as %q", "Default", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateDbSubnetGroupNamePrefix(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, hyphens, underscores, periods, and spaces allowed in %q", k))
|
||||
}
|
||||
if len(value) > 229 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be longer than 229 characters", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateDbOptionGroupName(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"first character of %q must be a letter", k))
|
||||
}
|
||||
if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"only alphanumeric characters and hyphens allowed in %q", 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 validateDbOptionGroupNamePrefix(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"first character of %q must be a letter", k))
|
||||
}
|
||||
if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"only alphanumeric characters and hyphens allowed in %q", k))
|
||||
}
|
||||
if regexp.MustCompile(`--`).MatchString(value) {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot contain two consecutive hyphens", k))
|
||||
}
|
||||
if len(value) > 229 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be greater than 229 characters", k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1785,3 +1785,131 @@ func TestValidateElbNamePrefix(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDbSubnetGroupName(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "tEsting",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing?",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "default",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(300),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateDbSubnetGroupName(tc.Value, "aws_db_subnet_group")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Subnet Group name to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDbSubnetGroupNamePrefix(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "tEsting",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing?",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(230),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateDbSubnetGroupNamePrefix(tc.Value, "aws_db_subnet_group")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Subnet Group name prefix to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDbOptionGroupName(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "testing123!",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "1testing123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing--123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing123-",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(256),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateDbOptionGroupName(tc.Value, "aws_db_option_group_name")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Option Group Name to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDbOptionGroupNamePrefix(t *testing.T) {
|
||||
cases := []struct {
|
||||
Value string
|
||||
ErrCount int
|
||||
}{
|
||||
{
|
||||
Value: "testing123!",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "1testing123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: "testing--123",
|
||||
ErrCount: 1,
|
||||
},
|
||||
{
|
||||
Value: randomString(230),
|
||||
ErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
_, errors := validateDbOptionGroupNamePrefix(tc.Value, "aws_db_option_group_name")
|
||||
|
||||
if len(errors) != tc.ErrCount {
|
||||
t.Fatalf("Expected the DB Option Group name prefix to trigger a validation error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ The following arguments are supported:
|
|||
* `allocated_storage` - (Required unless a `snapshot_identifier` or `replicate_source_db` is provided) The allocated storage in gigabytes.
|
||||
* `engine` - (Required unless a `snapshot_identifier` or `replicate_source_db` is provided) The database engine to use.
|
||||
* `engine_version` - (Optional) The engine version to use.
|
||||
* `identifier` - (Optional) The name of the RDS instance, if omitted, Terraform will assign a random, unique name
|
||||
* `identifier` - (Optional, Forces new resource) The name of the RDS instance, if omitted, Terraform will assign a random, unique identifier.
|
||||
* `identifier_prefix` - (Optional, Forces new resource) Creates a unique identifier beginning with the specified prefix. Conflicts with `identifer`.
|
||||
* `instance_class` - (Required) The instance type of the RDS instance.
|
||||
* `storage_type` - (Optional) One of "standard" (magnetic), "gp2" (general
|
||||
purpose SSD), or "io1" (provisioned IOPS SSD). The default is "io1" if
|
||||
|
@ -156,7 +157,7 @@ On Oracle instances the following is exported additionally:
|
|||
|
||||
- `create` - (Default `40 minutes`) Used for Creating Instances, Replicas, and
|
||||
restoring from Snapshots
|
||||
- `update` - (Default `80 minutes`) Used for Database modifications
|
||||
- `update` - (Default `80 minutes`) Used for Database modifications
|
||||
- `delete` - (Default `40 minutes`) Used for destroying databases. This includes
|
||||
the time required to take snapshots
|
||||
|
||||
|
|
|
@ -38,8 +38,9 @@ resource "aws_db_option_group" "bar" {
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) The name of the Option group to be created.
|
||||
* `option_group_description` - (Required) The description of the option group.
|
||||
* `name` - (Optional, Forces new resource) The name of the option group. If omitted, Terraform will assign a random, unique name.
|
||||
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
|
||||
* `option_group_description` - (Optional) The description of the option group. Defaults to "Managed by Terraform".
|
||||
* `engine_name` - (Required) Specifies the name of the engine that this option group should be associated with..
|
||||
* `major_engine_version` - (Required) Specifies the major version of the engine that this option group should be associated with.
|
||||
* `option` - (Optional) A list of Options to apply.
|
||||
|
@ -70,4 +71,4 @@ DB Option groups can be imported using the `name`, e.g.
|
|||
|
||||
```
|
||||
$ terraform import aws_db_option_group.bar mysql-option-group
|
||||
```
|
||||
```
|
||||
|
|
|
@ -31,7 +31,8 @@ resource "aws_db_parameter_group" "default" {
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) The name of the DB parameter group.
|
||||
* `name` - (Optional, Forces new resource) The name of the DB parameter group. If omitted, Terraform will assign a random, unique name.
|
||||
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
|
||||
* `family` - (Required) The family of the DB parameter group.
|
||||
* `description` - (Optional) The description of the DB parameter group. Defaults to "Managed by Terraform".
|
||||
* `parameter` - (Optional) A list of DB parameters to apply.
|
||||
|
@ -58,4 +59,4 @@ DB Parameter groups can be imported using the `name`, e.g.
|
|||
|
||||
```
|
||||
$ terraform import aws_db_parameter_group.rds_pg rds-pg
|
||||
```
|
||||
```
|
||||
|
|
|
@ -27,7 +27,8 @@ resource "aws_db_subnet_group" "default" {
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) The name of the DB subnet group.
|
||||
* `name` - (Optional, Forces new resource) The name of the DB subnet group. If omitted, Terraform will assign a random, unique name.
|
||||
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
|
||||
* `description` - (Optional) The description of the DB subnet group. Defaults to "Managed by Terraform".
|
||||
* `subnet_ids` - (Required) A list of VPC subnet IDs.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
|
@ -46,4 +47,4 @@ DB Subnet groups can be imported using the `name`, e.g.
|
|||
|
||||
```
|
||||
$ terraform import aws_db_subnet_group.default production-subnet-group
|
||||
```
|
||||
```
|
||||
|
|
|
@ -53,8 +53,8 @@ the [AWS official documentation](https://docs.aws.amazon.com/AmazonRDS/latest/Co
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `cluster_identifier` - (Required) The Cluster Identifier. Must be a lower case
|
||||
string.
|
||||
* `cluster_identifier` - (Optional, Forces new resources) The cluster identifier. If omitted, Terraform will assign a random, unique identifier.
|
||||
* `cluster_identifier_prefix` - (Optional, Forces new resource) Creates a unique cluster identifier beginning with the specified prefix. Conflicts with `cluster_identifer`.
|
||||
* `database_name` - (Optional) The name for your database of up to 8 alpha-numeric
|
||||
characters. If you do not provide a name, Amazon RDS will not create a
|
||||
database in the DB cluster you are creating
|
||||
|
|
|
@ -47,8 +47,8 @@ the [AWS official documentation](https://docs.aws.amazon.com/AmazonRDS/latest/Co
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `identifier` - (Optional) The Instance Identifier. Must be a lower case
|
||||
string. If omitted, a unique identifier will be generated.
|
||||
* `identifier` - (Optional, Forces new resource) The indentifier for the RDS instance, if omitted, Terraform will assign a random, unique identifier.
|
||||
* `identifier_prefix` - (Optional, Forces new resource) Creates a unique identifier beginning with the specified prefix. Conflicts with `identifer`.
|
||||
* `cluster_identifier` - (Required) The identifier of the [`aws_rds_cluster`](/docs/providers/aws/r/rds_cluster.html) in which to launch this instance.
|
||||
* `instance_class` - (Required) The instance class to use. For details on CPU
|
||||
and memory, see [Scaling Aurora DB Instances][4]. Aurora currently
|
||||
|
|
|
@ -32,9 +32,10 @@ resource "aws_rds_cluster_parameter_group" "default" {
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) The name of the DB cluster parameter group.
|
||||
* `name` - (Optional, Forces new resource) The name of the DB cluster parameter group. If omitted, Terraform will assign a random, unique name.
|
||||
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
|
||||
* `family` - (Required) The family of the DB cluster parameter group.
|
||||
* `description` - (Required) The description of the DB cluster parameter group.
|
||||
* `description` - (Optional) The description of the DB cluster parameter group. Defaults to "Managed by Terraform".
|
||||
* `parameter` - (Optional) A list of DB parameters to apply.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
|
||||
|
@ -60,4 +61,4 @@ RDS Cluster Parameter Groups can be imported using the `name`, e.g.
|
|||
|
||||
```
|
||||
$ terraform import aws_rds_cluster_parameter_group.cluster_pg production-pg-1
|
||||
```
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue