Adding the documentation for the Redshift Parameter Groups

Changed the aws_redshift_security_group and aws_redshift_parameter_group
to remove the tags from the schema. Tags are a little bit more
complicated than originally though - I will revisit this later

Then added the schema, CRUD functionality and basic acceptance tests for
aws_redshift_subnet_group

Adding an acceptance test for the Update of subnet_ids in AWS Redshift Subnet Group
This commit is contained in:
stack72 2015-11-12 01:10:57 +00:00
parent 249e7df76c
commit 48091e37c7
7 changed files with 469 additions and 13 deletions

View File

@ -172,6 +172,7 @@ func Provider() terraform.ResourceProvider {
"aws_rds_cluster_instance": resourceAwsRDSClusterInstance(),
"aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(),
"aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(),
"aws_redshift_subnet_group": resourceAwsRedshiftSubnetGroup(),
"aws_route53_delegation_set": resourceAwsRoute53DelegationSet(),
"aws_route53_record": resourceAwsRoute53Record(),
"aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(),

View File

@ -61,8 +61,6 @@ func resourceAwsRedshiftParameterGroup() *schema.Resource {
},
Set: resourceAwsRedshiftParameterHash,
},
"tags": tagsSchema(),
},
}
}
@ -74,7 +72,6 @@ func resourceAwsRedshiftParameterGroupCreate(d *schema.ResourceData, meta interf
ParameterGroupName: aws.String(d.Get("name").(string)),
ParameterGroupFamily: aws.String(d.Get("family").(string)),
Description: aws.String(d.Get("description").(string)),
Tags: tagsFromMapRedshift(d.Get("tags").(map[string]interface{})),
}
log.Printf("[DEBUG] Create Redshift Parameter Group: %#v", createOpts)
@ -103,13 +100,13 @@ func resourceAwsRedshiftParameterGroupRead(d *schema.ResourceData, meta interfac
if len(describeResp.ParameterGroups) != 1 ||
*describeResp.ParameterGroups[0].ParameterGroupName != d.Id() {
d.SetId("")
return fmt.Errorf("Unable to find Parameter Group: %#v", describeResp.ParameterGroups)
}
d.Set("name", describeResp.ParameterGroups[0].ParameterGroupName)
d.Set("family", describeResp.ParameterGroups[0].ParameterGroupFamily)
d.Set("description", describeResp.ParameterGroups[0].Description)
d.Set("tags", tagsToMapRedshift(describeResp.ParameterGroups[0].Tags))
describeParametersOpts := redshift.DescribeClusterParametersInput{
ParameterGroupName: aws.String(d.Id()),

View File

@ -62,12 +62,6 @@ func resourceAwsRedshiftSecurityGroup() *schema.Resource {
},
Set: resourceAwsRedshiftSecurityGroupIngressHash,
},
"tags": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
},
}
}
@ -80,11 +74,9 @@ func resourceAwsRedshiftSecurityGroupCreate(d *schema.ResourceData, meta interfa
name := d.Get("name").(string)
desc := d.Get("description").(string)
tags := tagsFromMapRedshift(d.Get("tags").(map[string]interface{}))
sgInput := &redshift.CreateClusterSecurityGroupInput{
ClusterSecurityGroupName: aws.String(name),
Description: aws.String(desc),
Tags: tags,
}
log.Printf("[DEBUG] Redshift security group create: name: %s, description: %s", name, desc)
_, err = conn.CreateClusterSecurityGroup(sgInput)
@ -154,7 +146,6 @@ func resourceAwsRedshiftSecurityGroupRead(d *schema.ResourceData, meta interface
d.Set("ingress", rules)
d.Set("name", *sg.ClusterSecurityGroupName)
d.Set("description", *sg.Description)
d.Set("tags", tagsToMapRedshift(sg.Tags))
return nil
}

View File

@ -0,0 +1,186 @@
package aws
import (
"fmt"
"log"
"regexp"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsRedshiftSubnetGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAwsRedshiftSubnetGroupCreate,
Read: resourceAwsRedshiftSubnetGroupRead,
Update: resourceAwsRedshiftSubnetGroupUpdate,
Delete: resourceAwsRedshiftSubnetGroupDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
ValidateFunc: validateRedshiftSubnetGroupName,
},
"description": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"subnet_ids": &schema.Schema{
Type: schema.TypeSet,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}
func resourceAwsRedshiftSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
subnetIdsSet := d.Get("subnet_ids").(*schema.Set)
subnetIds := make([]*string, subnetIdsSet.Len())
for i, subnetId := range subnetIdsSet.List() {
subnetIds[i] = aws.String(subnetId.(string))
}
createOpts := redshift.CreateClusterSubnetGroupInput{
ClusterSubnetGroupName: aws.String(d.Get("name").(string)),
Description: aws.String(d.Get("description").(string)),
SubnetIds: subnetIds,
}
log.Printf("[DEBUG] Create Redshift Subnet Group: %#v", createOpts)
_, err := conn.CreateClusterSubnetGroup(&createOpts)
if err != nil {
return fmt.Errorf("Error creating Redshift Subnet Group: %s", err)
}
d.SetId(*createOpts.ClusterSubnetGroupName)
log.Printf("[INFO] Redshift Subnet Group ID: %s", d.Id())
return resourceAwsRedshiftSubnetGroupRead(d, meta)
}
func resourceAwsRedshiftSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
describeOpts := redshift.DescribeClusterSubnetGroupsInput{
ClusterSubnetGroupName: aws.String(d.Id()),
}
describeResp, err := conn.DescribeClusterSubnetGroups(&describeOpts)
if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "ClusterSubnetGroupNotFoundFault" {
log.Printf("[INFO] Redshift Subnet Group: %s was not found", d.Id())
d.SetId("")
return nil
}
return err
}
if len(describeResp.ClusterSubnetGroups) == 0 {
return fmt.Errorf("Unable to find Redshift Subnet Group: %#v", describeResp.ClusterSubnetGroups)
}
d.Set("name", d.Id())
d.Set("description", describeResp.ClusterSubnetGroups[0].Description)
d.Set("subnet_ids", subnetIdsToSlice(describeResp.ClusterSubnetGroups[0].Subnets))
return nil
}
func resourceAwsRedshiftSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
if d.HasChange("subnet_ids") {
_, n := d.GetChange("subnet_ids")
if n == nil {
n = new(schema.Set)
}
ns := n.(*schema.Set)
var sIds []*string
for _, s := range ns.List() {
sIds = append(sIds, aws.String(s.(string)))
}
_, err := conn.ModifyClusterSubnetGroup(&redshift.ModifyClusterSubnetGroupInput{
ClusterSubnetGroupName: aws.String(d.Id()),
SubnetIds: sIds,
})
if err != nil {
return err
}
}
return nil
}
func resourceAwsRedshiftSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
stateConf := &resource.StateChangeConf{
Pending: []string{"pending"},
Target: "destroyed",
Refresh: resourceAwsRedshiftSubnetGroupDeleteRefreshFunc(d, meta),
Timeout: 3 * time.Minute,
MinTimeout: 1 * time.Second,
}
_, err := stateConf.WaitForState()
return err
}
func resourceAwsRedshiftSubnetGroupDeleteRefreshFunc(d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
conn := meta.(*AWSClient).redshiftconn
return func() (interface{}, string, error) {
deleteOpts := redshift.DeleteClusterSubnetGroupInput{
ClusterSubnetGroupName: aws.String(d.Id()),
}
if _, err := conn.DeleteClusterSubnetGroup(&deleteOpts); err != nil {
redshiftErr, ok := err.(awserr.Error)
if !ok {
return d, "error", err
}
if redshiftErr.Code() != "ClusterSubnetGroupNotFoundFault" {
return d, "error", err
}
}
return d, "destroyed", nil
}
}
func subnetIdsToSlice(subnetIds []*redshift.Subnet) []string {
subnetsSlice := make([]string, 0, len(subnetIds))
for _, s := range subnetIds {
subnetsSlice = append(subnetsSlice, *s.SubnetIdentifier)
}
return subnetsSlice
}
func validateRedshiftSubnetGroupName(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, and periods 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
}

View File

@ -0,0 +1,220 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSRedshiftSubnetGroup_basic(t *testing.T) {
var v redshift.ClusterSubnetGroup
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRedshiftSubnetGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRedshiftSubnetGroupConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckRedshiftSubnetGroupExists("aws_redshift_subnet_group.foo", &v),
resource.TestCheckResourceAttr(
"aws_redshift_subnet_group.foo", "subnet_ids.#", "2"),
),
},
},
})
}
func TestAccAWSRedshiftSubnetGroup_updateSubnetIds(t *testing.T) {
var v redshift.ClusterSubnetGroup
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRedshiftSubnetGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRedshiftSubnetGroupConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckRedshiftSubnetGroupExists("aws_redshift_subnet_group.foo", &v),
resource.TestCheckResourceAttr(
"aws_redshift_subnet_group.foo", "subnet_ids.#", "2"),
),
},
resource.TestStep{
Config: testAccRedshiftSubnetGroupConfig_updateSubnetIds,
Check: resource.ComposeTestCheckFunc(
testAccCheckRedshiftSubnetGroupExists("aws_redshift_subnet_group.foo", &v),
resource.TestCheckResourceAttr(
"aws_redshift_subnet_group.foo", "subnet_ids.#", "3"),
),
},
},
})
}
func TestResourceAWSRedshiftSubnetGroupName_validation(t *testing.T) {
cases := []struct {
Value string
ErrCount int
}{
{
Value: "default",
ErrCount: 1,
},
{
Value: "testing123%%",
ErrCount: 1,
},
{
Value: "TestingSG",
ErrCount: 1,
},
{
Value: randomString(256),
ErrCount: 1,
},
}
for _, tc := range cases {
_, errors := validateRedshiftSubnetGroupName(tc.Value, "aws_redshift_subnet_group_name")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected the Redshift Subnet Group Name to trigger a validation error")
}
}
}
func testAccCheckRedshiftSubnetGroupDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).redshiftconn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_redshift_subnet_group" {
continue
}
resp, err := conn.DescribeClusterSubnetGroups(
&redshift.DescribeClusterSubnetGroupsInput{
ClusterSubnetGroupName: aws.String(rs.Primary.ID)})
if err == nil {
if len(resp.ClusterSubnetGroups) > 0 {
return fmt.Errorf("still exist.")
}
return nil
}
redshiftErr, ok := err.(awserr.Error)
if !ok {
return err
}
if redshiftErr.Code() != "ClusterSubnetGroupNotFoundFault" {
return err
}
}
return nil
}
func testAccCheckRedshiftSubnetGroupExists(n string, v *redshift.ClusterSubnetGroup) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).redshiftconn
resp, err := conn.DescribeClusterSubnetGroups(
&redshift.DescribeClusterSubnetGroupsInput{ClusterSubnetGroupName: aws.String(rs.Primary.ID)})
if err != nil {
return err
}
if len(resp.ClusterSubnetGroups) == 0 {
return fmt.Errorf("ClusterSubnetGroup not found")
}
*v = *resp.ClusterSubnetGroups[0]
return nil
}
}
const testAccRedshiftSubnetGroupConfig = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
}
resource "aws_subnet" "foo" {
cidr_block = "10.1.1.0/24"
availability_zone = "us-west-2a"
vpc_id = "${aws_vpc.foo.id}"
tags {
Name = "tf-dbsubnet-test-1"
}
}
resource "aws_subnet" "bar" {
cidr_block = "10.1.2.0/24"
availability_zone = "us-west-2b"
vpc_id = "${aws_vpc.foo.id}"
tags {
Name = "tf-dbsubnet-test-2"
}
}
resource "aws_redshift_subnet_group" "foo" {
name = "foo"
description = "foo description"
subnet_ids = ["${aws_subnet.foo.id}", "${aws_subnet.bar.id}"]
}
`
const testAccRedshiftSubnetGroupConfig_updateSubnetIds = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
}
resource "aws_subnet" "foo" {
cidr_block = "10.1.1.0/24"
availability_zone = "us-west-2a"
vpc_id = "${aws_vpc.foo.id}"
tags {
Name = "tf-dbsubnet-test-1"
}
}
resource "aws_subnet" "bar" {
cidr_block = "10.1.2.0/24"
availability_zone = "us-west-2b"
vpc_id = "${aws_vpc.foo.id}"
tags {
Name = "tf-dbsubnet-test-2"
}
}
resource "aws_subnet" "foobar" {
cidr_block = "10.1.3.0/24"
availability_zone = "us-west-2c"
vpc_id = "${aws_vpc.foo.id}"
tags {
Name = "tf-dbsubnet-test-3"
}
}
resource "aws_redshift_subnet_group" "foo" {
name = "foo"
description = "foo description"
subnet_ids = ["${aws_subnet.foo.id}", "${aws_subnet.bar.id}", "${aws_subnet.foobar.id}"]
}
`

View File

@ -0,0 +1,57 @@
---
layout: "aws"
page_title: "AWS: aws_redshift_parameter_group"
sidebar_current: "docs-aws-resource-redshift-parameter-group"
---
# aws\_redshift\_parameter\_group
Provides an Redshift Cluster parameter group resource.
## Example Usage
```
resource "aws_redshift_parameter_group" "bar" {
name = "parameter-group-test-terraform"
family = "redshift-1.0"
description = "Test parameter group for terraform"
parameter {
name = "require_ssl"
value = "true"
}
parameter {
name = "query_group"
value = "example"
}
parameter{
name = "enable_user_activity_logging"
value = "true"
}
tags {
Environment = "test"
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the Redshift parameter group.
* `family` - (Required) The family of the Redshift parameter group.
* `description` - (Required) The description of the Redshift parameter group.
* `parameter` - (Optional) A list of Redshift parameters to apply.
Parameter blocks support the following:
* `name` - (Required) The name of the Redshift parameter.
* `value` - (Required) The value of the Redshift parameter.
You can read more about the parameters that Redshift supports in the [documentation](http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-parameter-groups.html)
## Attributes Reference
The following attributes are exported:
* `id` - The Redshift parameter group name.

View File

@ -437,6 +437,10 @@
<a href="#">Redshift Resources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-aws-resource-redshift-parameter-group") %>>
<a href="/docs/providers/aws/r/redshift_parameter_group.html">aws_redshift_parameter_group</a>
</li>
<li<%= sidebar_current("docs-aws-resource-redshift-security-group") %>>
<a href="/docs/providers/aws/r/redshift_security_group.html">aws_redshift_security_group</a>
</li>