github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/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 }