github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_app_cookie_stickiness_policy.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/aws/aws-sdk-go/aws"
    11  	"github.com/aws/aws-sdk-go/aws/awserr"
    12  	"github.com/aws/aws-sdk-go/service/elb"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  func resourceAwsAppCookieStickinessPolicy() *schema.Resource {
    17  	return &schema.Resource{
    18  		// There is no concept of "updating" an App Stickiness policy in
    19  		// the AWS API.
    20  		Create: resourceAwsAppCookieStickinessPolicyCreate,
    21  		Read:   resourceAwsAppCookieStickinessPolicyRead,
    22  		Delete: resourceAwsAppCookieStickinessPolicyDelete,
    23  
    24  		Schema: map[string]*schema.Schema{
    25  			"name": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  				ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
    30  					value := v.(string)
    31  					if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
    32  						es = append(es, fmt.Errorf(
    33  							"only alphanumeric characters and hyphens allowed in %q", k))
    34  					}
    35  					return
    36  				},
    37  			},
    38  
    39  			"load_balancer": &schema.Schema{
    40  				Type:     schema.TypeString,
    41  				Required: true,
    42  				ForceNew: true,
    43  			},
    44  
    45  			"lb_port": &schema.Schema{
    46  				Type:     schema.TypeInt,
    47  				Required: true,
    48  				ForceNew: true,
    49  			},
    50  
    51  			"cookie_name": &schema.Schema{
    52  				Type:     schema.TypeString,
    53  				Required: true,
    54  				ForceNew: true,
    55  			},
    56  		},
    57  	}
    58  }
    59  
    60  func resourceAwsAppCookieStickinessPolicyCreate(d *schema.ResourceData, meta interface{}) error {
    61  	elbconn := meta.(*AWSClient).elbconn
    62  
    63  	// Provision the AppStickinessPolicy
    64  	acspOpts := &elb.CreateAppCookieStickinessPolicyInput{
    65  		CookieName:       aws.String(d.Get("cookie_name").(string)),
    66  		LoadBalancerName: aws.String(d.Get("load_balancer").(string)),
    67  		PolicyName:       aws.String(d.Get("name").(string)),
    68  	}
    69  
    70  	if _, err := elbconn.CreateAppCookieStickinessPolicy(acspOpts); err != nil {
    71  		return fmt.Errorf("Error creating AppCookieStickinessPolicy: %s", err)
    72  	}
    73  
    74  	setLoadBalancerOpts := &elb.SetLoadBalancerPoliciesOfListenerInput{
    75  		LoadBalancerName: aws.String(d.Get("load_balancer").(string)),
    76  		LoadBalancerPort: aws.Int64(int64(d.Get("lb_port").(int))),
    77  		PolicyNames:      []*string{aws.String(d.Get("name").(string))},
    78  	}
    79  
    80  	if _, err := elbconn.SetLoadBalancerPoliciesOfListener(setLoadBalancerOpts); err != nil {
    81  		return fmt.Errorf("Error setting AppCookieStickinessPolicy: %s", err)
    82  	}
    83  
    84  	d.SetId(fmt.Sprintf("%s:%d:%s",
    85  		*acspOpts.LoadBalancerName,
    86  		*setLoadBalancerOpts.LoadBalancerPort,
    87  		*acspOpts.PolicyName))
    88  	return nil
    89  }
    90  
    91  func resourceAwsAppCookieStickinessPolicyRead(d *schema.ResourceData, meta interface{}) error {
    92  	elbconn := meta.(*AWSClient).elbconn
    93  
    94  	lbName, lbPort, policyName := resourceAwsAppCookieStickinessPolicyParseId(d.Id())
    95  
    96  	request := &elb.DescribeLoadBalancerPoliciesInput{
    97  		LoadBalancerName: aws.String(lbName),
    98  		PolicyNames:      []*string{aws.String(policyName)},
    99  	}
   100  
   101  	getResp, err := elbconn.DescribeLoadBalancerPolicies(request)
   102  	if err != nil {
   103  		if ec2err, ok := err.(awserr.Error); ok {
   104  			if ec2err.Code() == "PolicyNotFound" || ec2err.Code() == "LoadBalancerNotFound" {
   105  				d.SetId("")
   106  			}
   107  			return nil
   108  		}
   109  		return fmt.Errorf("Error retrieving policy: %s", err)
   110  	}
   111  	if len(getResp.PolicyDescriptions) != 1 {
   112  		return fmt.Errorf("Unable to find policy %#v", getResp.PolicyDescriptions)
   113  	}
   114  
   115  	// we know the policy exists now, but we have to check if it's assigned to a listener
   116  	assigned, err := resourceAwsELBSticknessPolicyAssigned(policyName, lbName, lbPort, elbconn)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	if !assigned {
   121  		// policy exists, but isn't assigned to a listener
   122  		log.Printf("[DEBUG] policy '%s' exists, but isn't assigned to a listener", policyName)
   123  		d.SetId("")
   124  		return nil
   125  	}
   126  
   127  	// We can get away with this because there's only one attribute, the
   128  	// cookie expiration, in these descriptions.
   129  	policyDesc := getResp.PolicyDescriptions[0]
   130  	cookieAttr := policyDesc.PolicyAttributeDescriptions[0]
   131  	if *cookieAttr.AttributeName != "CookieName" {
   132  		return fmt.Errorf("Unable to find cookie Name.")
   133  	}
   134  	d.Set("cookie_name", cookieAttr.AttributeValue)
   135  
   136  	d.Set("name", policyName)
   137  	d.Set("load_balancer", lbName)
   138  	d.Set("lb_port", lbPort)
   139  
   140  	return nil
   141  }
   142  
   143  // Determine if a particular policy is assigned to an ELB listener
   144  func resourceAwsELBSticknessPolicyAssigned(policyName, lbName, lbPort string, elbconn *elb.ELB) (bool, error) {
   145  	describeElbOpts := &elb.DescribeLoadBalancersInput{
   146  		LoadBalancerNames: []*string{aws.String(lbName)},
   147  	}
   148  	describeResp, err := elbconn.DescribeLoadBalancers(describeElbOpts)
   149  	if err != nil {
   150  		if ec2err, ok := err.(awserr.Error); ok {
   151  			if ec2err.Code() == "LoadBalancerNotFound" {
   152  				return false, nil
   153  			}
   154  		}
   155  		return false, fmt.Errorf("Error retrieving ELB description: %s", err)
   156  	}
   157  
   158  	if len(describeResp.LoadBalancerDescriptions) != 1 {
   159  		return false, fmt.Errorf("Unable to find ELB: %#v", describeResp.LoadBalancerDescriptions)
   160  	}
   161  
   162  	lb := describeResp.LoadBalancerDescriptions[0]
   163  	assigned := false
   164  	for _, listener := range lb.ListenerDescriptions {
   165  		if lbPort != strconv.Itoa(int(*listener.Listener.LoadBalancerPort)) {
   166  			continue
   167  		}
   168  
   169  		for _, name := range listener.PolicyNames {
   170  			if policyName == *name {
   171  				assigned = true
   172  				break
   173  			}
   174  		}
   175  	}
   176  
   177  	return assigned, nil
   178  }
   179  
   180  func resourceAwsAppCookieStickinessPolicyDelete(d *schema.ResourceData, meta interface{}) error {
   181  	elbconn := meta.(*AWSClient).elbconn
   182  
   183  	lbName, _, policyName := resourceAwsAppCookieStickinessPolicyParseId(d.Id())
   184  
   185  	// Perversely, if we Set an empty list of PolicyNames, we detach the
   186  	// policies attached to a listener, which is required to delete the
   187  	// policy itself.
   188  	setLoadBalancerOpts := &elb.SetLoadBalancerPoliciesOfListenerInput{
   189  		LoadBalancerName: aws.String(d.Get("load_balancer").(string)),
   190  		LoadBalancerPort: aws.Int64(int64(d.Get("lb_port").(int))),
   191  		PolicyNames:      []*string{},
   192  	}
   193  
   194  	if _, err := elbconn.SetLoadBalancerPoliciesOfListener(setLoadBalancerOpts); err != nil {
   195  		return fmt.Errorf("Error removing AppCookieStickinessPolicy: %s", err)
   196  	}
   197  
   198  	request := &elb.DeleteLoadBalancerPolicyInput{
   199  		LoadBalancerName: aws.String(lbName),
   200  		PolicyName:       aws.String(policyName),
   201  	}
   202  
   203  	if _, err := elbconn.DeleteLoadBalancerPolicy(request); err != nil {
   204  		return fmt.Errorf("Error deleting App stickiness policy %s: %s", d.Id(), err)
   205  	}
   206  	return nil
   207  }
   208  
   209  // resourceAwsAppCookieStickinessPolicyParseId takes an ID and parses it into
   210  // it's constituent parts. You need three axes (LB name, policy name, and LB
   211  // port) to create or identify a stickiness policy in AWS's API.
   212  func resourceAwsAppCookieStickinessPolicyParseId(id string) (string, string, string) {
   213  	parts := strings.SplitN(id, ":", 3)
   214  	return parts[0], parts[1], parts[2]
   215  }