github.com/ottenhoff/terraform@v0.7.0-rc1.0.20160607213102-ac2d195cc560/builtin/providers/aws/resource_aws_redshift_parameter_group.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"regexp"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/aws/aws-sdk-go/aws"
    12  	"github.com/aws/aws-sdk-go/aws/awserr"
    13  	"github.com/aws/aws-sdk-go/service/redshift"
    14  	"github.com/hashicorp/terraform/helper/hashcode"
    15  	"github.com/hashicorp/terraform/helper/resource"
    16  	"github.com/hashicorp/terraform/helper/schema"
    17  )
    18  
    19  func resourceAwsRedshiftParameterGroup() *schema.Resource {
    20  	return &schema.Resource{
    21  		Create: resourceAwsRedshiftParameterGroupCreate,
    22  		Read:   resourceAwsRedshiftParameterGroupRead,
    23  		Update: resourceAwsRedshiftParameterGroupUpdate,
    24  		Delete: resourceAwsRedshiftParameterGroupDelete,
    25  
    26  		Schema: map[string]*schema.Schema{
    27  			"name": &schema.Schema{
    28  				Type:         schema.TypeString,
    29  				ForceNew:     true,
    30  				Required:     true,
    31  				ValidateFunc: validateRedshiftParamGroupName,
    32  			},
    33  
    34  			"family": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ForceNew: true,
    38  			},
    39  
    40  			"description": &schema.Schema{
    41  				Type:     schema.TypeString,
    42  				Optional: true,
    43  				ForceNew: true,
    44  				Default:  "Managed by Terraform",
    45  			},
    46  
    47  			"parameter": &schema.Schema{
    48  				Type:     schema.TypeSet,
    49  				Optional: true,
    50  				ForceNew: false,
    51  				Elem: &schema.Resource{
    52  					Schema: map[string]*schema.Schema{
    53  						"name": &schema.Schema{
    54  							Type:     schema.TypeString,
    55  							Required: true,
    56  						},
    57  						"value": &schema.Schema{
    58  							Type:     schema.TypeString,
    59  							Required: true,
    60  						},
    61  					},
    62  				},
    63  				Set: resourceAwsRedshiftParameterHash,
    64  			},
    65  		},
    66  	}
    67  }
    68  
    69  func resourceAwsRedshiftParameterGroupCreate(d *schema.ResourceData, meta interface{}) error {
    70  	conn := meta.(*AWSClient).redshiftconn
    71  
    72  	createOpts := redshift.CreateClusterParameterGroupInput{
    73  		ParameterGroupName:   aws.String(d.Get("name").(string)),
    74  		ParameterGroupFamily: aws.String(d.Get("family").(string)),
    75  		Description:          aws.String(d.Get("description").(string)),
    76  	}
    77  
    78  	log.Printf("[DEBUG] Create Redshift Parameter Group: %#v", createOpts)
    79  	_, err := conn.CreateClusterParameterGroup(&createOpts)
    80  	if err != nil {
    81  		return fmt.Errorf("Error creating Redshift Parameter Group: %s", err)
    82  	}
    83  
    84  	d.SetId(*createOpts.ParameterGroupName)
    85  	log.Printf("[INFO] Redshift Parameter Group ID: %s", d.Id())
    86  
    87  	return resourceAwsRedshiftParameterGroupUpdate(d, meta)
    88  }
    89  
    90  func resourceAwsRedshiftParameterGroupRead(d *schema.ResourceData, meta interface{}) error {
    91  	conn := meta.(*AWSClient).redshiftconn
    92  
    93  	describeOpts := redshift.DescribeClusterParameterGroupsInput{
    94  		ParameterGroupName: aws.String(d.Id()),
    95  	}
    96  
    97  	describeResp, err := conn.DescribeClusterParameterGroups(&describeOpts)
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	if len(describeResp.ParameterGroups) != 1 ||
   103  		*describeResp.ParameterGroups[0].ParameterGroupName != d.Id() {
   104  		d.SetId("")
   105  		return fmt.Errorf("Unable to find Parameter Group: %#v", describeResp.ParameterGroups)
   106  	}
   107  
   108  	d.Set("name", describeResp.ParameterGroups[0].ParameterGroupName)
   109  	d.Set("family", describeResp.ParameterGroups[0].ParameterGroupFamily)
   110  	d.Set("description", describeResp.ParameterGroups[0].Description)
   111  
   112  	describeParametersOpts := redshift.DescribeClusterParametersInput{
   113  		ParameterGroupName: aws.String(d.Id()),
   114  		Source:             aws.String("user"),
   115  	}
   116  
   117  	describeParametersResp, err := conn.DescribeClusterParameters(&describeParametersOpts)
   118  	if err != nil {
   119  		return err
   120  	}
   121  
   122  	d.Set("parameter", flattenRedshiftParameters(describeParametersResp.Parameters))
   123  	return nil
   124  }
   125  
   126  func resourceAwsRedshiftParameterGroupUpdate(d *schema.ResourceData, meta interface{}) error {
   127  	conn := meta.(*AWSClient).redshiftconn
   128  
   129  	d.Partial(true)
   130  
   131  	if d.HasChange("parameter") {
   132  		o, n := d.GetChange("parameter")
   133  		if o == nil {
   134  			o = new(schema.Set)
   135  		}
   136  		if n == nil {
   137  			n = new(schema.Set)
   138  		}
   139  
   140  		os := o.(*schema.Set)
   141  		ns := n.(*schema.Set)
   142  
   143  		// Expand the "parameter" set to aws-sdk-go compat []redshift.Parameter
   144  		parameters, err := expandRedshiftParameters(ns.Difference(os).List())
   145  		if err != nil {
   146  			return err
   147  		}
   148  
   149  		if len(parameters) > 0 {
   150  			modifyOpts := redshift.ModifyClusterParameterGroupInput{
   151  				ParameterGroupName: aws.String(d.Get("name").(string)),
   152  				Parameters:         parameters,
   153  			}
   154  
   155  			log.Printf("[DEBUG] Modify Redshift Parameter Group: %s", modifyOpts)
   156  			_, err = conn.ModifyClusterParameterGroup(&modifyOpts)
   157  			if err != nil {
   158  				return fmt.Errorf("Error modifying Redshift Parameter Group: %s", err)
   159  			}
   160  		}
   161  		d.SetPartial("parameter")
   162  	}
   163  
   164  	d.Partial(false)
   165  	return resourceAwsRedshiftParameterGroupRead(d, meta)
   166  }
   167  
   168  func resourceAwsRedshiftParameterGroupDelete(d *schema.ResourceData, meta interface{}) error {
   169  	stateConf := &resource.StateChangeConf{
   170  		Pending:    []string{"pending"},
   171  		Target:     []string{"destroyed"},
   172  		Refresh:    resourceAwsRedshiftParameterGroupDeleteRefreshFunc(d, meta),
   173  		Timeout:    3 * time.Minute,
   174  		MinTimeout: 1 * time.Second,
   175  	}
   176  	_, err := stateConf.WaitForState()
   177  	return err
   178  }
   179  
   180  func resourceAwsRedshiftParameterGroupDeleteRefreshFunc(
   181  	d *schema.ResourceData,
   182  	meta interface{}) resource.StateRefreshFunc {
   183  	conn := meta.(*AWSClient).redshiftconn
   184  
   185  	return func() (interface{}, string, error) {
   186  
   187  		deleteOpts := redshift.DeleteClusterParameterGroupInput{
   188  			ParameterGroupName: aws.String(d.Id()),
   189  		}
   190  
   191  		if _, err := conn.DeleteClusterParameterGroup(&deleteOpts); err != nil {
   192  			redshiftErr, ok := err.(awserr.Error)
   193  			if !ok {
   194  				return d, "error", err
   195  			}
   196  
   197  			if redshiftErr.Code() != "RedshiftParameterGroupNotFoundFault" {
   198  				return d, "error", err
   199  			}
   200  		}
   201  
   202  		return d, "destroyed", nil
   203  	}
   204  }
   205  
   206  func resourceAwsRedshiftParameterHash(v interface{}) int {
   207  	var buf bytes.Buffer
   208  	m := v.(map[string]interface{})
   209  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   210  	// Store the value as a lower case string, to match how we store them in flattenParameters
   211  	buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["value"].(string))))
   212  
   213  	return hashcode.String(buf.String())
   214  }
   215  
   216  func validateRedshiftParamGroupName(v interface{}, k string) (ws []string, errors []error) {
   217  	value := v.(string)
   218  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
   219  		errors = append(errors, fmt.Errorf(
   220  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
   221  	}
   222  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
   223  		errors = append(errors, fmt.Errorf(
   224  			"first character of %q must be a letter", k))
   225  	}
   226  	if regexp.MustCompile(`--`).MatchString(value) {
   227  		errors = append(errors, fmt.Errorf(
   228  			"%q cannot contain two consecutive hyphens", k))
   229  	}
   230  	if regexp.MustCompile(`-$`).MatchString(value) {
   231  		errors = append(errors, fmt.Errorf(
   232  			"%q cannot end with a hyphen", k))
   233  	}
   234  	if len(value) > 255 {
   235  		errors = append(errors, fmt.Errorf(
   236  			"%q cannot be greater than 255 characters", k))
   237  	}
   238  	return
   239  }