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  }