terraform/builtin/providers/aws/resource_aws_redshift_param...

243 lines
6.7 KiB
Go

package aws
import (
"bytes"
"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/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsRedshiftParameterGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAwsRedshiftParameterGroupCreate,
Read: resourceAwsRedshiftParameterGroupRead,
Update: resourceAwsRedshiftParameterGroupUpdate,
Delete: resourceAwsRedshiftParameterGroupDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
ValidateFunc: validateRedshiftParamGroupName,
},
"family": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "Managed by Terraform",
},
"parameter": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: false,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"value": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
},
Set: resourceAwsRedshiftParameterHash,
},
},
}
}
func resourceAwsRedshiftParameterGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
createOpts := redshift.CreateClusterParameterGroupInput{
ParameterGroupName: aws.String(d.Get("name").(string)),
ParameterGroupFamily: aws.String(d.Get("family").(string)),
Description: aws.String(d.Get("description").(string)),
}
log.Printf("[DEBUG] Create Redshift Parameter Group: %#v", createOpts)
_, err := conn.CreateClusterParameterGroup(&createOpts)
if err != nil {
return fmt.Errorf("Error creating Redshift Parameter Group: %s", err)
}
d.SetId(*createOpts.ParameterGroupName)
log.Printf("[INFO] Redshift Parameter Group ID: %s", d.Id())
return resourceAwsRedshiftParameterGroupUpdate(d, meta)
}
func resourceAwsRedshiftParameterGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
describeOpts := redshift.DescribeClusterParameterGroupsInput{
ParameterGroupName: aws.String(d.Id()),
}
describeResp, err := conn.DescribeClusterParameterGroups(&describeOpts)
if err != nil {
return err
}
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)
describeParametersOpts := redshift.DescribeClusterParametersInput{
ParameterGroupName: aws.String(d.Id()),
Source: aws.String("user"),
}
describeParametersResp, err := conn.DescribeClusterParameters(&describeParametersOpts)
if err != nil {
return err
}
d.Set("parameter", flattenRedshiftParameters(describeParametersResp.Parameters))
return nil
}
func resourceAwsRedshiftParameterGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).redshiftconn
d.Partial(true)
if d.HasChange("parameter") {
o, n := d.GetChange("parameter")
if o == nil {
o = new(schema.Set)
}
if n == nil {
n = new(schema.Set)
}
os := o.(*schema.Set)
ns := n.(*schema.Set)
// Expand the "parameter" set to aws-sdk-go compat []redshift.Parameter
parameters, err := expandRedshiftParameters(ns.Difference(os).List())
if err != nil {
return err
}
if len(parameters) > 0 {
modifyOpts := redshift.ModifyClusterParameterGroupInput{
ParameterGroupName: aws.String(d.Get("name").(string)),
Parameters: parameters,
}
log.Printf("[DEBUG] Modify Redshift Parameter Group: %s", modifyOpts)
_, err = conn.ModifyClusterParameterGroup(&modifyOpts)
if err != nil {
return fmt.Errorf("Error modifying Redshift Parameter Group: %s", err)
}
}
d.SetPartial("parameter")
}
d.Partial(false)
return resourceAwsRedshiftParameterGroupRead(d, meta)
}
func resourceAwsRedshiftParameterGroupDelete(d *schema.ResourceData, meta interface{}) error {
stateConf := &resource.StateChangeConf{
Pending: []string{"pending"},
Target: []string{"destroyed"},
Refresh: resourceAwsRedshiftParameterGroupDeleteRefreshFunc(d, meta),
Timeout: 3 * time.Minute,
MinTimeout: 1 * time.Second,
}
_, err := stateConf.WaitForState()
return err
}
func resourceAwsRedshiftParameterGroupDeleteRefreshFunc(
d *schema.ResourceData,
meta interface{}) resource.StateRefreshFunc {
conn := meta.(*AWSClient).redshiftconn
return func() (interface{}, string, error) {
deleteOpts := redshift.DeleteClusterParameterGroupInput{
ParameterGroupName: aws.String(d.Id()),
}
if _, err := conn.DeleteClusterParameterGroup(&deleteOpts); err != nil {
redshiftErr, ok := err.(awserr.Error)
if !ok {
return d, "error", err
}
if redshiftErr.Code() != "RedshiftParameterGroupNotFoundFault" {
return d, "error", err
}
}
return d, "destroyed", nil
}
}
func resourceAwsRedshiftParameterHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
// Store the value as a lower case string, to match how we store them in flattenParameters
buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["value"].(string))))
return hashcode.String(buf.String())
}
func validateRedshiftParamGroupName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only lowercase alphanumeric characters and hyphens allowed in %q", k))
}
if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"first character of %q must be a letter", k))
}
if regexp.MustCompile(`--`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot contain two consecutive hyphens", k))
}
if regexp.MustCompile(`-$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q cannot end with a hyphen", k))
}
if len(value) > 255 {
errors = append(errors, fmt.Errorf(
"%q cannot be greater than 255 characters", k))
}
return
}