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