github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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 }