github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_sqs_queue.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "net/url" 7 "strconv" 8 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "strings" 12 13 "github.com/aws/aws-sdk-go/aws" 14 "github.com/aws/aws-sdk-go/aws/awserr" 15 "github.com/aws/aws-sdk-go/service/sqs" 16 ) 17 18 var AttributeMap = map[string]string{ 19 "delay_seconds": "DelaySeconds", 20 "max_message_size": "MaximumMessageSize", 21 "message_retention_seconds": "MessageRetentionPeriod", 22 "receive_wait_time_seconds": "ReceiveMessageWaitTimeSeconds", 23 "visibility_timeout_seconds": "VisibilityTimeout", 24 "policy": "Policy", 25 "redrive_policy": "RedrivePolicy", 26 "arn": "QueueArn", 27 "fifo_queue": "FifoQueue", 28 "content_based_deduplication": "ContentBasedDeduplication", 29 } 30 31 // A number of these are marked as computed because if you don't 32 // provide a value, SQS will provide you with defaults (which are the 33 // default values specified below) 34 func resourceAwsSqsQueue() *schema.Resource { 35 return &schema.Resource{ 36 Create: resourceAwsSqsQueueCreate, 37 Read: resourceAwsSqsQueueRead, 38 Update: resourceAwsSqsQueueUpdate, 39 Delete: resourceAwsSqsQueueDelete, 40 Importer: &schema.ResourceImporter{ 41 State: schema.ImportStatePassthrough, 42 }, 43 44 Schema: map[string]*schema.Schema{ 45 "name": { 46 Type: schema.TypeString, 47 Required: true, 48 ForceNew: true, 49 }, 50 "delay_seconds": { 51 Type: schema.TypeInt, 52 Optional: true, 53 Default: 0, 54 }, 55 "max_message_size": { 56 Type: schema.TypeInt, 57 Optional: true, 58 Default: 262144, 59 }, 60 "message_retention_seconds": { 61 Type: schema.TypeInt, 62 Optional: true, 63 Default: 345600, 64 }, 65 "receive_wait_time_seconds": { 66 Type: schema.TypeInt, 67 Optional: true, 68 Default: 0, 69 }, 70 "visibility_timeout_seconds": { 71 Type: schema.TypeInt, 72 Optional: true, 73 Default: 30, 74 }, 75 "policy": { 76 Type: schema.TypeString, 77 Optional: true, 78 Computed: true, 79 ValidateFunc: validateJsonString, 80 DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs, 81 }, 82 "redrive_policy": { 83 Type: schema.TypeString, 84 Optional: true, 85 ValidateFunc: validateJsonString, 86 StateFunc: func(v interface{}) string { 87 json, _ := normalizeJsonString(v) 88 return json 89 }, 90 }, 91 "arn": { 92 Type: schema.TypeString, 93 Computed: true, 94 }, 95 "fifo_queue": { 96 Type: schema.TypeBool, 97 Default: false, 98 ForceNew: true, 99 Optional: true, 100 }, 101 "content_based_deduplication": { 102 Type: schema.TypeBool, 103 Default: false, 104 Optional: true, 105 }, 106 }, 107 } 108 } 109 110 func resourceAwsSqsQueueCreate(d *schema.ResourceData, meta interface{}) error { 111 sqsconn := meta.(*AWSClient).sqsconn 112 113 name := d.Get("name").(string) 114 fq := d.Get("fifo_queue").(bool) 115 cbd := d.Get("content_based_deduplication").(bool) 116 117 if fq { 118 if errors := validateSQSFifoQueueName(name, "name"); len(errors) > 0 { 119 return fmt.Errorf("Error validating the FIFO queue name: %v", errors) 120 } 121 } else { 122 if errors := validateSQSQueueName(name, "name"); len(errors) > 0 { 123 return fmt.Errorf("Error validating SQS queue name: %v", errors) 124 } 125 } 126 127 if !fq && cbd { 128 return fmt.Errorf("Content based deduplication can only be set with FIFO queues") 129 } 130 131 log.Printf("[DEBUG] SQS queue create: %s", name) 132 133 req := &sqs.CreateQueueInput{ 134 QueueName: aws.String(name), 135 } 136 137 attributes := make(map[string]*string) 138 139 resource := *resourceAwsSqsQueue() 140 141 for k, s := range resource.Schema { 142 if attrKey, ok := AttributeMap[k]; ok { 143 if value, ok := d.GetOk(k); ok { 144 switch s.Type { 145 case schema.TypeInt: 146 attributes[attrKey] = aws.String(strconv.Itoa(value.(int))) 147 case schema.TypeBool: 148 attributes[attrKey] = aws.String(strconv.FormatBool(value.(bool))) 149 default: 150 attributes[attrKey] = aws.String(value.(string)) 151 } 152 } 153 154 } 155 } 156 157 if len(attributes) > 0 { 158 req.Attributes = attributes 159 } 160 161 output, err := sqsconn.CreateQueue(req) 162 if err != nil { 163 return fmt.Errorf("Error creating SQS queue: %s", err) 164 } 165 166 d.SetId(*output.QueueUrl) 167 168 return resourceAwsSqsQueueUpdate(d, meta) 169 } 170 171 func resourceAwsSqsQueueUpdate(d *schema.ResourceData, meta interface{}) error { 172 sqsconn := meta.(*AWSClient).sqsconn 173 attributes := make(map[string]*string) 174 175 resource := *resourceAwsSqsQueue() 176 177 for k, s := range resource.Schema { 178 if attrKey, ok := AttributeMap[k]; ok { 179 if d.HasChange(k) { 180 log.Printf("[DEBUG] Updating %s", attrKey) 181 _, n := d.GetChange(k) 182 switch s.Type { 183 case schema.TypeInt: 184 attributes[attrKey] = aws.String(strconv.Itoa(n.(int))) 185 case schema.TypeBool: 186 attributes[attrKey] = aws.String(strconv.FormatBool(n.(bool))) 187 default: 188 attributes[attrKey] = aws.String(n.(string)) 189 } 190 } 191 } 192 } 193 194 if len(attributes) > 0 { 195 req := &sqs.SetQueueAttributesInput{ 196 QueueUrl: aws.String(d.Id()), 197 Attributes: attributes, 198 } 199 if _, err := sqsconn.SetQueueAttributes(req); err != nil { 200 return fmt.Errorf("[ERR] Error updating SQS attributes: %s", err) 201 } 202 } 203 204 return resourceAwsSqsQueueRead(d, meta) 205 } 206 207 func resourceAwsSqsQueueRead(d *schema.ResourceData, meta interface{}) error { 208 sqsconn := meta.(*AWSClient).sqsconn 209 210 attributeOutput, err := sqsconn.GetQueueAttributes(&sqs.GetQueueAttributesInput{ 211 QueueUrl: aws.String(d.Id()), 212 AttributeNames: []*string{aws.String("All")}, 213 }) 214 215 if err != nil { 216 if awsErr, ok := err.(awserr.Error); ok { 217 log.Printf("ERROR Found %s", awsErr.Code()) 218 if "AWS.SimpleQueueService.NonExistentQueue" == awsErr.Code() { 219 d.SetId("") 220 log.Printf("[DEBUG] SQS Queue (%s) not found", d.Get("name").(string)) 221 return nil 222 } 223 } 224 return err 225 } 226 227 name, err := extractNameFromSqsQueueUrl(d.Id()) 228 if err != nil { 229 return err 230 } 231 d.Set("name", name) 232 233 if attributeOutput.Attributes != nil && len(attributeOutput.Attributes) > 0 { 234 attrmap := attributeOutput.Attributes 235 resource := *resourceAwsSqsQueue() 236 // iKey = internal struct key, oKey = AWS Attribute Map key 237 for iKey, oKey := range AttributeMap { 238 if attrmap[oKey] != nil { 239 switch resource.Schema[iKey].Type { 240 case schema.TypeInt: 241 value, err := strconv.Atoi(*attrmap[oKey]) 242 if err != nil { 243 return err 244 } 245 d.Set(iKey, value) 246 log.Printf("[DEBUG] Reading %s => %s -> %d", iKey, oKey, value) 247 case schema.TypeBool: 248 value, err := strconv.ParseBool(*attrmap[oKey]) 249 if err != nil { 250 return err 251 } 252 d.Set(iKey, value) 253 log.Printf("[DEBUG] Reading %s => %s -> %t", iKey, oKey, value) 254 default: 255 log.Printf("[DEBUG] Reading %s => %s -> %s", iKey, oKey, *attrmap[oKey]) 256 d.Set(iKey, *attrmap[oKey]) 257 } 258 } 259 } 260 } 261 262 // Since AWS does not send the FifoQueue attribute back when the queue 263 // is a standard one (even to false), this enforces the queue to be set 264 // to the correct value. 265 d.Set("fifo_queue", d.Get("fifo_queue").(bool)) 266 d.Set("content_based_deduplication", d.Get("content_based_deduplication").(bool)) 267 268 return nil 269 } 270 271 func resourceAwsSqsQueueDelete(d *schema.ResourceData, meta interface{}) error { 272 sqsconn := meta.(*AWSClient).sqsconn 273 274 log.Printf("[DEBUG] SQS Delete Queue: %s", d.Id()) 275 _, err := sqsconn.DeleteQueue(&sqs.DeleteQueueInput{ 276 QueueUrl: aws.String(d.Id()), 277 }) 278 if err != nil { 279 return err 280 } 281 return nil 282 } 283 284 func extractNameFromSqsQueueUrl(queue string) (string, error) { 285 //http://sqs.us-west-2.amazonaws.com/123456789012/queueName 286 u, err := url.Parse(queue) 287 if err != nil { 288 return "", err 289 } 290 segments := strings.Split(u.Path, "/") 291 if len(segments) != 3 { 292 return "", fmt.Errorf("SQS Url not parsed correctly") 293 } 294 295 return segments[2], nil 296 297 }