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