Adding the documentation for the AWS Redshift Subnet Group resource
also removed the notion of tags from the redshift security group and parameter group documentation until that has been implemented Redshift Cluster CRUD and acceptance tests Removing the Acceptance test for the Cluster Updates. You cannot delete a cluster immediately after performing an operation on it. We would need to add a lot of retry logic to the system to get this test to work Adding some schema validation for RedShift cluster Adding the last of the pieces of a first draft of the Redshift work - this is the documentation
This commit is contained in:
parent
48091e37c7
commit
bf03752552
|
@ -170,6 +170,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
|
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
|
||||||
"aws_rds_cluster": resourceAwsRDSCluster(),
|
"aws_rds_cluster": resourceAwsRDSCluster(),
|
||||||
"aws_rds_cluster_instance": resourceAwsRDSClusterInstance(),
|
"aws_rds_cluster_instance": resourceAwsRDSClusterInstance(),
|
||||||
|
"aws_redshift_cluster": resourceAwsRedshiftCluster(),
|
||||||
"aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(),
|
"aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(),
|
||||||
"aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(),
|
"aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(),
|
||||||
"aws_redshift_subnet_group": resourceAwsRedshiftSubnetGroup(),
|
"aws_redshift_subnet_group": resourceAwsRedshiftSubnetGroup(),
|
||||||
|
|
|
@ -0,0 +1,574 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"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 resourceAwsRedshiftCluster() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAwsRedshiftClusterCreate,
|
||||||
|
Read: resourceAwsRedshiftClusterRead,
|
||||||
|
Update: resourceAwsRedshiftClusterUpdate,
|
||||||
|
Delete: resourceAwsRedshiftClusterDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"database_name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ValidateFunc: validateRedshiftClusterDbName,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_identifier": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: validateRedshiftClusterIdentifier,
|
||||||
|
},
|
||||||
|
"cluster_type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"node_type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"master_username": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validateRedshiftClusterMasterUsername,
|
||||||
|
},
|
||||||
|
|
||||||
|
"master_password": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_security_groups": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Set: schema.HashString,
|
||||||
|
},
|
||||||
|
|
||||||
|
"vpc_security_group_ids": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
Set: schema.HashString,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_subnet_group_name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"availability_zone": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"preferred_maintenance_window": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
StateFunc: func(val interface{}) string {
|
||||||
|
if val == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strings.ToLower(val.(string))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_parameter_group_name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"automated_snapshot_retention_period": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 1,
|
||||||
|
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
|
||||||
|
value := v.(int)
|
||||||
|
if value > 35 {
|
||||||
|
es = append(es, fmt.Errorf(
|
||||||
|
"backup retention period cannot be more than 35 days"))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"port": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 5439,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_version": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Default: "1.0",
|
||||||
|
},
|
||||||
|
|
||||||
|
"allow_version_upgrade": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"number_of_nodes": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
Default: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
"publicly_accessible": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"encrypted": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"elastic_ip": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"final_snapshot_identifier": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ValidateFunc: validateRedshiftClusterFinalSnapshotIdentifier,
|
||||||
|
},
|
||||||
|
|
||||||
|
"skip_final_snapshot": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"endpoint": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_public_key": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_revision_number": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsRedshiftClusterCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).redshiftconn
|
||||||
|
|
||||||
|
log.Printf("[INFO] Building Redshift Cluster Options")
|
||||||
|
createOpts := &redshift.CreateClusterInput{
|
||||||
|
ClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)),
|
||||||
|
Port: aws.Int64(int64(d.Get("port").(int))),
|
||||||
|
MasterUserPassword: aws.String(d.Get("master_password").(string)),
|
||||||
|
MasterUsername: aws.String(d.Get("master_username").(string)),
|
||||||
|
ClusterType: aws.String(d.Get("cluster_type").(string)),
|
||||||
|
ClusterVersion: aws.String(d.Get("cluster_version").(string)),
|
||||||
|
NodeType: aws.String(d.Get("node_type").(string)),
|
||||||
|
DBName: aws.String(d.Get("database_name").(string)),
|
||||||
|
AllowVersionUpgrade: aws.Bool(d.Get("allow_version_upgrade").(bool)),
|
||||||
|
}
|
||||||
|
if d.Get("cluster_type") == "multi-node" {
|
||||||
|
createOpts.NumberOfNodes = aws.Int64(int64(d.Get("number_of_nodes").(int)))
|
||||||
|
}
|
||||||
|
if v := d.Get("cluster_security_groups").(*schema.Set); v.Len() > 0 {
|
||||||
|
createOpts.ClusterSecurityGroups = expandStringList(v.List())
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := d.Get("vpc_security_group_ids").(*schema.Set); v.Len() > 0 {
|
||||||
|
createOpts.VpcSecurityGroupIds = expandStringList(v.List())
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("cluster_subnet_group_name"); ok {
|
||||||
|
createOpts.ClusterSubnetGroupName = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("availability_zone"); ok {
|
||||||
|
createOpts.AvailabilityZone = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("preferred_maintenance_window"); ok {
|
||||||
|
createOpts.PreferredMaintenanceWindow = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("cluster_parameter_group_name"); ok {
|
||||||
|
createOpts.ClusterParameterGroupName = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("automated_snapshot_retention_period"); ok {
|
||||||
|
createOpts.AutomatedSnapshotRetentionPeriod = aws.Int64(int64(v.(int)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("publicly_accessible"); ok {
|
||||||
|
createOpts.PubliclyAccessible = aws.Bool(v.(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("encrypted"); ok {
|
||||||
|
createOpts.Encrypted = aws.Bool(v.(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("elastic_ip"); ok {
|
||||||
|
createOpts.ElasticIp = aws.String(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Redshift Cluster create options: %s", createOpts)
|
||||||
|
resp, err := conn.CreateCluster(createOpts)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Error creating Redshift Cluster: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG]: Cluster create response: %s", resp)
|
||||||
|
d.SetId(*resp.Cluster.ClusterIdentifier)
|
||||||
|
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"creating", "backing-up", "modifying"},
|
||||||
|
Target: "available",
|
||||||
|
Refresh: resourceAwsRedshiftClusterStateRefreshFunc(d, meta),
|
||||||
|
Timeout: 5 * time.Minute,
|
||||||
|
MinTimeout: 3 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = stateConf.WaitForState()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[WARN] Error waiting for Redshift Cluster state to be \"available\": %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceAwsRedshiftClusterRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsRedshiftClusterRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).redshiftconn
|
||||||
|
|
||||||
|
log.Printf("[INFO] Reading Redshift Cluster Information: %s", d.Id())
|
||||||
|
resp, err := conn.DescribeClusters(&redshift.DescribeClustersInput{
|
||||||
|
ClusterIdentifier: aws.String(d.Id()),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if awsErr, ok := err.(awserr.Error); ok {
|
||||||
|
if "ClusterNotFound" == awsErr.Code() {
|
||||||
|
d.SetId("")
|
||||||
|
log.Printf("[DEBUG] Redshift Cluster (%s) not found", d.Id())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] Error describing Redshift Cluster (%s)", d.Id())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rsc *redshift.Cluster
|
||||||
|
for _, c := range resp.Clusters {
|
||||||
|
if *c.ClusterIdentifier == d.Id() {
|
||||||
|
rsc = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsc == nil {
|
||||||
|
log.Printf("[WARN] Redshift Cluster (%s) not found", d.Id())
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("database_name", rsc.DBName)
|
||||||
|
d.Set("cluster_subnet_group_name", rsc.ClusterSubnetGroupName)
|
||||||
|
d.Set("availability_zone", rsc.AvailabilityZone)
|
||||||
|
d.Set("encrypted", rsc.Encrypted)
|
||||||
|
d.Set("automated_snapshot_retention_period", rsc.AutomatedSnapshotRetentionPeriod)
|
||||||
|
d.Set("preferred_maintenance_window", rsc.PreferredMaintenanceWindow)
|
||||||
|
d.Set("endpoint", aws.String(fmt.Sprintf("%s:%d", *rsc.Endpoint.Address, *rsc.Endpoint.Port)))
|
||||||
|
d.Set("cluster_parameter_group_name", rsc.ClusterParameterGroups[0].ParameterGroupName)
|
||||||
|
|
||||||
|
var vpcg []string
|
||||||
|
for _, g := range rsc.VpcSecurityGroups {
|
||||||
|
vpcg = append(vpcg, *g.VpcSecurityGroupId)
|
||||||
|
}
|
||||||
|
if err := d.Set("vpc_security_group_ids", vpcg); err != nil {
|
||||||
|
return fmt.Errorf("[DEBUG] Error saving VPC Security Group IDs to state for Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var csg []string
|
||||||
|
for _, g := range rsc.ClusterSecurityGroups {
|
||||||
|
csg = append(csg, *g.ClusterSecurityGroupName)
|
||||||
|
}
|
||||||
|
if err := d.Set("cluster_security_groups", csg); err != nil {
|
||||||
|
return fmt.Errorf("[DEBUG] Error saving Cluster Security Group Names to state for Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("cluster_public_key", rsc.ClusterPublicKey)
|
||||||
|
d.Set("cluster_revision_number", rsc.ClusterRevisionNumber)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsRedshiftClusterUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).redshiftconn
|
||||||
|
|
||||||
|
log.Printf("[INFO] Building Redshift Modify Cluster Options")
|
||||||
|
req := &redshift.ModifyClusterInput{
|
||||||
|
ClusterIdentifier: aws.String(d.Id()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("cluster_type") {
|
||||||
|
req.ClusterType = aws.String(d.Get("cluster_type").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("node_type") {
|
||||||
|
req.NodeType = aws.String(d.Get("node_type").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("number_of_nodes") {
|
||||||
|
log.Printf("[INFO] When changing the NumberOfNodes in a Redshift Cluster, NodeType is required")
|
||||||
|
req.NumberOfNodes = aws.Int64(int64(d.Get("number_of_nodes").(int)))
|
||||||
|
req.NodeType = aws.String(d.Get("node_type").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("cluster_security_groups") {
|
||||||
|
req.ClusterSecurityGroups = expandStringList(d.Get("cluster_security_groups").(*schema.Set).List())
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("vpc_security_group_ips") {
|
||||||
|
req.VpcSecurityGroupIds = expandStringList(d.Get("vpc_security_group_ips").(*schema.Set).List())
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("master_password") {
|
||||||
|
req.MasterUserPassword = aws.String(d.Get("master_password").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("cluster_parameter_group_name") {
|
||||||
|
req.ClusterParameterGroupName = aws.String(d.Get("cluster_parameter_group_name").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("automated_snapshot_retention_period") {
|
||||||
|
req.AutomatedSnapshotRetentionPeriod = aws.Int64(int64(d.Get("automated_snapshot_retention_period").(int)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("preferred_maintenance_window") {
|
||||||
|
req.PreferredMaintenanceWindow = aws.String(d.Get("preferred_maintenance_window").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("cluster_version") {
|
||||||
|
req.ClusterVersion = aws.String(d.Get("cluster_version").(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("allow_version_upgrade") {
|
||||||
|
req.AllowVersionUpgrade = aws.Bool(d.Get("allow_version_upgrade").(bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Modifying Redshift Cluster: %s", d.Id())
|
||||||
|
log.Printf("[DEBUG] Redshift Cluster Modify options: %s", req)
|
||||||
|
_, err := conn.ModifyCluster(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[WARN] Error modifying Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"creating", "deleting", "rebooting", "resizing", "renaming"},
|
||||||
|
Target: "available",
|
||||||
|
Refresh: resourceAwsRedshiftClusterStateRefreshFunc(d, meta),
|
||||||
|
Timeout: 10 * time.Minute,
|
||||||
|
MinTimeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait, catching any errors
|
||||||
|
_, err = stateConf.WaitForState()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[WARN] Error Modifying Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceAwsRedshiftClusterRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsRedshiftClusterDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
conn := meta.(*AWSClient).redshiftconn
|
||||||
|
log.Printf("[DEBUG] Destroying Redshift Cluster (%s)", d.Id())
|
||||||
|
|
||||||
|
deleteOpts := redshift.DeleteClusterInput{
|
||||||
|
ClusterIdentifier: aws.String(d.Id()),
|
||||||
|
}
|
||||||
|
|
||||||
|
skipFinalSnapshot := d.Get("skip_final_snapshot").(bool)
|
||||||
|
deleteOpts.SkipFinalClusterSnapshot = aws.Bool(skipFinalSnapshot)
|
||||||
|
|
||||||
|
if !skipFinalSnapshot {
|
||||||
|
if name, present := d.GetOk("final_snapshot_identifier"); present {
|
||||||
|
deleteOpts.FinalClusterSnapshotIdentifier = aws.String(name.(string))
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Redshift Cluster Instance FinalSnapshotIdentifier is required when a final snapshot is required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Redshift Cluster delete options: %s", deleteOpts)
|
||||||
|
_, err := conn.DeleteCluster(&deleteOpts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERROR] Error deleting Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateConf := &resource.StateChangeConf{
|
||||||
|
Pending: []string{"available", "creating", "deleting", "rebooting", "resizing", "renaming"},
|
||||||
|
Target: "destroyed",
|
||||||
|
Refresh: resourceAwsRedshiftClusterStateRefreshFunc(d, meta),
|
||||||
|
Timeout: 40 * time.Minute,
|
||||||
|
MinTimeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait, catching any errors
|
||||||
|
_, err = stateConf.WaitForState()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("[ERROR] Error deleting Redshift Cluster (%s): %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Redshift Cluster %s successfully deleted", d.Id())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAwsRedshiftClusterStateRefreshFunc(d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
|
||||||
|
return func() (interface{}, string, error) {
|
||||||
|
conn := meta.(*AWSClient).redshiftconn
|
||||||
|
|
||||||
|
log.Printf("[INFO] Reading Redshift Cluster Information: %s", d.Id())
|
||||||
|
resp, err := conn.DescribeClusters(&redshift.DescribeClustersInput{
|
||||||
|
ClusterIdentifier: aws.String(d.Id()),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if awsErr, ok := err.(awserr.Error); ok {
|
||||||
|
if "ClusterNotFound" == awsErr.Code() {
|
||||||
|
return 42, "destroyed", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("[WARN] Error on retrieving Redshift Cluster (%s) when waiting: %s", d.Id(), err)
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rsc *redshift.Cluster
|
||||||
|
|
||||||
|
for _, c := range resp.Clusters {
|
||||||
|
if *c.ClusterIdentifier == d.Id() {
|
||||||
|
rsc = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsc == nil {
|
||||||
|
return 42, "destroyed", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsc.ClusterStatus != nil {
|
||||||
|
log.Printf("[DEBUG] Redshift Cluster status (%s): %s", d.Id(), *rsc.ClusterStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rsc, *rsc.ClusterStatus, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRedshiftClusterIdentifier(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 validateRedshiftClusterDbName(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
value := v.(string)
|
||||||
|
if !regexp.MustCompile(`^[a-z]+$`).MatchString(value) {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"only lowercase letters characters allowed in %q", k))
|
||||||
|
}
|
||||||
|
if len(value) > 64 {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"%q cannot be longer than 64 characters: %q", k, value))
|
||||||
|
}
|
||||||
|
if value == "" {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"%q cannot be an empty string", k))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRedshiftClusterFinalSnapshotIdentifier(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", 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 in a hyphen", k))
|
||||||
|
}
|
||||||
|
if len(value) > 255 {
|
||||||
|
errors = append(errors, fmt.Errorf("%q cannot be more than 255 characters", k))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRedshiftClusterMasterUsername(v interface{}, k string) (ws []string, errors []error) {
|
||||||
|
value := v.(string)
|
||||||
|
if !regexp.MustCompile(`^[A-Za-z0-9]+$`).MatchString(value) {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"only alphanumeric characters in %q", k))
|
||||||
|
}
|
||||||
|
if !regexp.MustCompile(`^[A-Za-z]`).MatchString(value) {
|
||||||
|
errors = append(errors, fmt.Errorf(
|
||||||
|
"first character of %q must be a letter", k))
|
||||||
|
}
|
||||||
|
if len(value) > 128 {
|
||||||
|
errors = append(errors, fmt.Errorf("%q cannot be more than 128 characters", k))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"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/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccAWSRedshiftCluster_basic(t *testing.T) {
|
||||||
|
var v redshift.Cluster
|
||||||
|
|
||||||
|
ri := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
||||||
|
config := fmt.Sprintf(testAccAWSRedshiftClusterConfig_basic, ri)
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: config,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSRedshiftClusterDestroy(s *terraform.State) error {
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "aws_redshift_cluster" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the Group
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).redshiftconn
|
||||||
|
var err error
|
||||||
|
resp, err := conn.DescribeClusters(
|
||||||
|
&redshift.DescribeClustersInput{
|
||||||
|
ClusterIdentifier: aws.String(rs.Primary.ID),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
if len(resp.Clusters) != 0 &&
|
||||||
|
*resp.Clusters[0].ClusterIdentifier == rs.Primary.ID {
|
||||||
|
return fmt.Errorf("Redshift Cluster %s still exists", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return nil if the cluster is already destroyed
|
||||||
|
if awsErr, ok := err.(awserr.Error); ok {
|
||||||
|
if awsErr.Code() == "ClusterNotFound" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckAWSRedshiftClusterExists(n string, v *redshift.Cluster) 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 Redshift Cluster Instance ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := testAccProvider.Meta().(*AWSClient).redshiftconn
|
||||||
|
resp, err := conn.DescribeClusters(&redshift.DescribeClustersInput{
|
||||||
|
ClusterIdentifier: aws.String(rs.Primary.ID),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range resp.Clusters {
|
||||||
|
if *c.ClusterIdentifier == rs.Primary.ID {
|
||||||
|
*v = *c
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Redshift Cluster (%s) not found", rs.Primary.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceAWSRedshiftClusterIdentifierValidation(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Value string
|
||||||
|
ErrCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "tEsting",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "1testing",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing--123",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing!",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing-",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
_, errors := validateRedshiftClusterIdentifier(tc.Value, "aws_redshift_cluster_identifier")
|
||||||
|
|
||||||
|
if len(errors) != tc.ErrCount {
|
||||||
|
t.Fatalf("Expected the Redshift Cluster cluster_identifier to trigger a validation error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceAWSRedshiftClusterDbNameValidation(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Value string
|
||||||
|
ErrCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "tEsting",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing1",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing-",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "",
|
||||||
|
ErrCount: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: randomString(65),
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
_, errors := validateRedshiftClusterDbName(tc.Value, "aws_redshift_cluster_database_name")
|
||||||
|
|
||||||
|
if len(errors) != tc.ErrCount {
|
||||||
|
t.Fatalf("Expected the Redshift Cluster database_name to trigger a validation error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceAWSRedshiftClusterFinalSnapshotIdentifierValidation(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Value string
|
||||||
|
ErrCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "testing--123",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "testing-",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "Testingq123!",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: randomString(256),
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
_, errors := validateRedshiftClusterFinalSnapshotIdentifier(tc.Value, "aws_redshift_cluster_final_snapshot_identifier")
|
||||||
|
|
||||||
|
if len(errors) != tc.ErrCount {
|
||||||
|
t.Fatalf("Expected the Redshift Cluster final_snapshot_identifier to trigger a validation error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourceAWSRedshiftClusterMasterUsernameValidation(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Value string
|
||||||
|
ErrCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "1Testing",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "Testing!!",
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: randomString(129),
|
||||||
|
ErrCount: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
_, errors := validateRedshiftClusterMasterUsername(tc.Value, "aws_redshift_cluster_master_username")
|
||||||
|
|
||||||
|
if len(errors) != tc.ErrCount {
|
||||||
|
t.Fatalf("Expected the Redshift Cluster master_username to trigger a validation error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testAccAWSRedshiftClusterConfig_basic = `
|
||||||
|
provider "aws" {
|
||||||
|
region = "us-west-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_redshift_cluster" "default" {
|
||||||
|
cluster_identifier = "tf-redshift-cluster-%d"
|
||||||
|
availability_zone = "us-west-2a"
|
||||||
|
database_name = "mydb"
|
||||||
|
master_username = "foo"
|
||||||
|
master_password = "Mustbe8characters"
|
||||||
|
node_type = "dc1.large"
|
||||||
|
cluster_type = "single-node"
|
||||||
|
automated_snapshot_retention_period = 7
|
||||||
|
allow_version_upgrade = false
|
||||||
|
}`
|
|
@ -71,7 +71,7 @@ func TestAccAWSRedshiftParameterGroup_withoutParameters(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceAWSRedshiftParameterGroupName_validation(t *testing.T) {
|
func TestResourceAWSRedshiftParameterGroupNameValidation(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Value string
|
Value string
|
||||||
ErrCount int
|
ErrCount int
|
||||||
|
|
|
@ -131,7 +131,7 @@ func testAccCheckAWSRedshiftSecurityGroupDestroy(s *terraform.State) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceAWSRedshiftSecurityGroupName_validation(t *testing.T) {
|
func TestResourceAWSRedshiftSecurityGroupNameValidation(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Value string
|
Value string
|
||||||
ErrCount int
|
ErrCount int
|
||||||
|
|
|
@ -60,7 +60,7 @@ func TestAccAWSRedshiftSubnetGroup_updateSubnetIds(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceAWSRedshiftSubnetGroupName_validation(t *testing.T) {
|
func TestResourceAWSRedshiftSubnetGroupNameValidation(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Value string
|
Value string
|
||||||
ErrCount int
|
ErrCount int
|
||||||
|
|
|
@ -427,9 +427,6 @@ func TestExpandParameters(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
func TestExpandElasticacheParameters(t *testing.T) {
|
|
||||||
=======
|
|
||||||
func TestexpandRedshiftParameters(t *testing.T) {
|
func TestexpandRedshiftParameters(t *testing.T) {
|
||||||
expanded := []interface{}{
|
expanded := []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
|
@ -456,7 +453,6 @@ func TestexpandRedshiftParameters(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestexpandElasticacheParameters(t *testing.T) {
|
func TestexpandElasticacheParameters(t *testing.T) {
|
||||||
>>>>>>> Creation of the schema, CRUD and acceptance tests for Redshift Parameter Group
|
|
||||||
expanded := []interface{}{
|
expanded := []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"name": "activerehashing",
|
"name": "activerehashing",
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_redshift_cluster"
|
||||||
|
sidebar_current: "docs-aws-resource-redshift-cluster"
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_redshift\_cluster
|
||||||
|
|
||||||
|
Provides a Redshift Cluster Resource.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
resource "aws_redshift_cluster" "default" {
|
||||||
|
cluster_identifier = "tf-redshift-cluster"
|
||||||
|
database_name = "mydb"
|
||||||
|
master_username = "foo"
|
||||||
|
master_password = "Mustbe8characters"
|
||||||
|
node_type = "dc1.large"
|
||||||
|
cluster_type = "single-node"
|
||||||
|
}
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
For more detailed documentation about each argument, refer to
|
||||||
|
the [AWS official documentation](http://docs.aws.amazon.com/cli/latest/reference/redshift/index.html#cli-aws-redshift).
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `cluster_identifier` - (Required) The Cluster Identifier. Must be a lower case
|
||||||
|
string.
|
||||||
|
* `database_name` - (Optional) The name of the first database to be created when the cluster is created.
|
||||||
|
If you do not provide a name, Amazon Redshift will create a default database called `dev`.
|
||||||
|
* `cluster_type` - (Required) The type of the cluster. Valid values are `multi-node` and `single-node`
|
||||||
|
* `node_type` - (Required) The node type to be provisioned for the cluster.
|
||||||
|
* `master_password` - (Required) Password for the master DB user. Note that this may
|
||||||
|
show up in logs, and it will be stored in the state file
|
||||||
|
* `master_username` - (Required) Username for the master DB user
|
||||||
|
* `cluster_security_groups` - (Optional) A list of security groups to be associated with this cluster.
|
||||||
|
* `vpc_security_group_ids` - (Optional) A list of Virtual Private Cloud (VPC) security groups to be associated with the cluster.
|
||||||
|
* `cluster_subnet_group_name` - (Optional) The name of a cluster subnet group to be associated with this cluster. If this parameter is not provided the resulting cluster will be deployed outside virtual private cloud (VPC).
|
||||||
|
* `availability_zone` - (Optional) The EC2 Availability Zone (AZ) in which you want Amazon Redshift to provision the cluster. For example, if you have several EC2 instances running in a specific Availability Zone, then you might want the cluster to be provisioned in the same zone in order to decrease network latency.
|
||||||
|
* `preferred_maintenance_window` - (Optional) The weekly time range (in UTC) during which automated cluster maintenance can occur.
|
||||||
|
Format: ddd:hh24:mi-ddd:hh24:mi
|
||||||
|
* `cluster_parameter_group_name` - (Optional) The name of the parameter group to be associated with this cluster.
|
||||||
|
* `automated_snapshot_retention_period` - (Optional) The number of days that automated snapshots are retained. If the value is 0, automated snapshots are disabled. Even if automated snapshots are disabled, you can still create manual snapshots when you want with create-cluster-snapshot.
|
||||||
|
* `port` - (Optional) The port number on which the cluster accepts incoming connections.
|
||||||
|
The cluster is accessible only via the JDBC and ODBC connection strings. Part of the connection string requires the port on which the cluster will listen for incoming connections. Default port is 5439.
|
||||||
|
* `cluster_version` - (Optional) The version of the Amazon Redshift engine software that you want to deploy on the cluster.
|
||||||
|
The version selected runs on all the nodes in the cluster.
|
||||||
|
* `allow_version_upgrade` - (Optional) If true , major version upgrades can be applied during the maintenance window to the Amazon Redshift engine that is running on the cluster. Default is true
|
||||||
|
* `number_of_nodes` - (Optional) The number of compute nodes in the cluster. This parameter is required when the ClusterType parameter is specified as multi-node. Default is 1.
|
||||||
|
* `publicly_accessible` - (Optional) If true , the cluster can be accessed from a public network.
|
||||||
|
* `encrypted` - (Optional) If true , the data in the cluster is encrypted at rest.
|
||||||
|
* `elastic_ip` - (Optional) The Elastic IP (EIP) address for the cluster.
|
||||||
|
* `skip_final_snapshot` - (Optional) Determines whether a final snapshot of the cluster is created before Amazon Redshift deletes the cluster. If true , a final cluster snapshot is not created. If false , a final cluster snapshot is created before the cluster is deleted. Default is false.
|
||||||
|
* `final_snapshot_identifier` - (Optional) The identifier of the final snapshot that is to be created immediately before deleting the cluster. If this parameter is provided, `skip_final_snapshot` must be false.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The Redshift Cluster ID.
|
||||||
|
* `cluster_identifier` - The Cluster Identifier
|
||||||
|
* `cluster_type` - The cluster type
|
||||||
|
* `node_type` - The type of nodes in the cluster
|
||||||
|
* `database_name` - The name of the default database in the Cluster
|
||||||
|
* `availability_zone` - The availability zone of the Cluster
|
||||||
|
* `automated_snapshot_retention_period` - The backup retention period
|
||||||
|
* `preferred_maintenance_window` - The backup window
|
||||||
|
* `endpoint` - The connection endpoint
|
||||||
|
* `encrypted` - Whether the data in the cluster is encrypted
|
||||||
|
* `cluster_security_groups` - The security groups associated with the cluster
|
||||||
|
* `vpc_security_group_ids` - The VPC security group Ids associated with the cluster
|
||||||
|
* `port` - The Port the cluster responds on
|
||||||
|
* `cluster_version` - The version of Redshift engine software
|
||||||
|
* `cluster_parameter_group_name` - The name of the parameter group to be associated with this cluster
|
||||||
|
* `cluster_subnet_group_name` - The name of a cluster subnet group to be associated with this cluster
|
||||||
|
* `cluster_public_key` - The public key for the cluster
|
||||||
|
* `cluster_revision_number` - The specific revision number of the database in the cluster
|
||||||
|
|
|
@ -6,7 +6,7 @@ sidebar_current: "docs-aws-resource-redshift-parameter-group"
|
||||||
|
|
||||||
# aws\_redshift\_parameter\_group
|
# aws\_redshift\_parameter\_group
|
||||||
|
|
||||||
Provides an Redshift Cluster parameter group resource.
|
Provides a Redshift Cluster parameter group resource.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
@ -27,10 +27,6 @@ resource "aws_redshift_parameter_group" "bar" {
|
||||||
name = "enable_user_activity_logging"
|
name = "enable_user_activity_logging"
|
||||||
value = "true"
|
value = "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
tags {
|
|
||||||
Environment = "test"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,6 @@ resource "aws_redshift_security_group" "default" {
|
||||||
ingress {
|
ingress {
|
||||||
cidr = "10.0.0.0/24"
|
cidr = "10.0.0.0/24"
|
||||||
}
|
}
|
||||||
|
|
||||||
tags {
|
|
||||||
Environment = "test"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
layout: "aws"
|
||||||
|
page_title: "AWS: aws_redshift_subnet_group"
|
||||||
|
sidebar_current: "docs-aws-resource-redshift-subnet-group"
|
||||||
|
description: |-
|
||||||
|
Provides a Redshift Subnet Group resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# aws\_redshift\_subnet\_group
|
||||||
|
|
||||||
|
Creates a new Amazon Redshift subnet group. You must provide a list of one or more subnets in your existing Amazon Virtual Private Cloud (Amazon VPC) when creating Amazon Redshift subnet group.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
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}"]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the Redshift Subnet group.
|
||||||
|
* `description` - (Required) The description of the Redshift Subnet group.
|
||||||
|
* `subnet_ids` - (Optional) An array of VPC subnet IDs..
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `id` - The Redshift Subnet group ID.
|
||||||
|
|
|
@ -437,6 +437,10 @@
|
||||||
<a href="#">Redshift Resources</a>
|
<a href="#">Redshift Resources</a>
|
||||||
<ul class="nav nav-visible">
|
<ul class="nav nav-visible">
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-aws-resource-redshift-cluster") %>>
|
||||||
|
<a href="/docs/providers/aws/r/redshift_cluster.html">aws_redshift_cluster</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-aws-resource-redshift-parameter-group") %>>
|
<li<%= sidebar_current("docs-aws-resource-redshift-parameter-group") %>>
|
||||||
<a href="/docs/providers/aws/r/redshift_parameter_group.html">aws_redshift_parameter_group</a>
|
<a href="/docs/providers/aws/r/redshift_parameter_group.html">aws_redshift_parameter_group</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -445,6 +449,10 @@
|
||||||
<a href="/docs/providers/aws/r/redshift_security_group.html">aws_redshift_security_group</a>
|
<a href="/docs/providers/aws/r/redshift_security_group.html">aws_redshift_security_group</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-aws-resource-redshift-subnet-group") %>>
|
||||||
|
<a href="/docs/providers/aws/r/redshift_subnet_group.html">aws_redshift_subnet_group</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue