github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_proxy_protocol_policy.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "strings" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/service/elb" 11 "github.com/hashicorp/terraform/helper/hashcode" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 func resourceAwsProxyProtocolPolicy() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceAwsProxyProtocolPolicyCreate, 18 Read: resourceAwsProxyProtocolPolicyRead, 19 Update: resourceAwsProxyProtocolPolicyUpdate, 20 Delete: resourceAwsProxyProtocolPolicyDelete, 21 22 Schema: map[string]*schema.Schema{ 23 "load_balancer": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 }, 27 28 "instance_ports": &schema.Schema{ 29 Type: schema.TypeSet, 30 Elem: &schema.Schema{Type: schema.TypeString}, 31 Required: true, 32 Set: func(v interface{}) int { 33 return hashcode.String(v.(string)) 34 }, 35 }, 36 }, 37 } 38 } 39 40 func resourceAwsProxyProtocolPolicyCreate(d *schema.ResourceData, meta interface{}) error { 41 elbconn := meta.(*AWSClient).elbconn 42 elbname := aws.String(d.Get("load_balancer").(string)) 43 44 input := &elb.CreateLoadBalancerPolicyInput{ 45 LoadBalancerName: elbname, 46 PolicyAttributes: []*elb.PolicyAttribute{ 47 &elb.PolicyAttribute{ 48 AttributeName: aws.String("ProxyProtocol"), 49 AttributeValue: aws.String("True"), 50 }, 51 }, 52 PolicyName: aws.String("TFEnableProxyProtocol"), 53 PolicyTypeName: aws.String("ProxyProtocolPolicyType"), 54 } 55 56 // Create a policy 57 log.Printf("[DEBUG] ELB create a policy %s from policy type %s", 58 *input.PolicyName, *input.PolicyTypeName) 59 60 if _, err := elbconn.CreateLoadBalancerPolicy(input); err != nil { 61 return fmt.Errorf("Error creating a policy %s: %s", 62 *input.PolicyName, err) 63 } 64 65 // Assign the policy name for use later 66 d.Partial(true) 67 d.SetId(fmt.Sprintf("%s:%s", *elbname, *input.PolicyName)) 68 d.SetPartial("load_balancer") 69 log.Printf("[INFO] ELB PolicyName: %s", *input.PolicyName) 70 71 return resourceAwsProxyProtocolPolicyUpdate(d, meta) 72 } 73 74 func resourceAwsProxyProtocolPolicyRead(d *schema.ResourceData, meta interface{}) error { 75 elbconn := meta.(*AWSClient).elbconn 76 elbname := aws.String(d.Get("load_balancer").(string)) 77 78 // Retrieve the current ELB policies for updating the state 79 req := &elb.DescribeLoadBalancersInput{ 80 LoadBalancerNames: []*string{elbname}, 81 } 82 resp, err := elbconn.DescribeLoadBalancers(req) 83 if err != nil { 84 if isLoadBalancerNotFound(err) { 85 // The ELB is gone now, so just remove it from the state 86 d.SetId("") 87 return nil 88 } 89 return fmt.Errorf("Error retrieving ELB attributes: %s", err) 90 } 91 92 backends := flattenBackendPolicies(resp.LoadBalancerDescriptions[0].BackendServerDescriptions) 93 94 ports := []*string{} 95 for ip := range backends { 96 ipstr := strconv.Itoa(int(ip)) 97 ports = append(ports, &ipstr) 98 } 99 d.Set("instance_ports", ports) 100 d.Set("load_balancer", *elbname) 101 return nil 102 } 103 104 func resourceAwsProxyProtocolPolicyUpdate(d *schema.ResourceData, meta interface{}) error { 105 elbconn := meta.(*AWSClient).elbconn 106 elbname := aws.String(d.Get("load_balancer").(string)) 107 108 // Retrieve the current ELB policies for updating the state 109 req := &elb.DescribeLoadBalancersInput{ 110 LoadBalancerNames: []*string{elbname}, 111 } 112 resp, err := elbconn.DescribeLoadBalancers(req) 113 if err != nil { 114 if isLoadBalancerNotFound(err) { 115 // The ELB is gone now, so just remove it from the state 116 d.SetId("") 117 return nil 118 } 119 return fmt.Errorf("Error retrieving ELB attributes: %s", err) 120 } 121 122 backends := flattenBackendPolicies(resp.LoadBalancerDescriptions[0].BackendServerDescriptions) 123 _, policyName := resourceAwsProxyProtocolPolicyParseId(d.Id()) 124 125 d.Partial(true) 126 if d.HasChange("instance_ports") { 127 o, n := d.GetChange("instance_ports") 128 os := o.(*schema.Set) 129 ns := n.(*schema.Set) 130 remove := os.Difference(ns).List() 131 add := ns.Difference(os).List() 132 133 inputs := []*elb.SetLoadBalancerPoliciesForBackendServerInput{} 134 135 i, err := resourceAwsProxyProtocolPolicyRemove(policyName, remove, backends) 136 if err != nil { 137 return err 138 } 139 inputs = append(inputs, i...) 140 141 i, err = resourceAwsProxyProtocolPolicyAdd(policyName, add, backends) 142 if err != nil { 143 return err 144 } 145 inputs = append(inputs, i...) 146 147 for _, input := range inputs { 148 input.LoadBalancerName = elbname 149 if _, err := elbconn.SetLoadBalancerPoliciesForBackendServer(input); err != nil { 150 return fmt.Errorf("Error setting policy for backend: %s", err) 151 } 152 } 153 154 d.SetPartial("instance_ports") 155 } 156 157 return resourceAwsProxyProtocolPolicyRead(d, meta) 158 } 159 160 func resourceAwsProxyProtocolPolicyDelete(d *schema.ResourceData, meta interface{}) error { 161 elbconn := meta.(*AWSClient).elbconn 162 elbname := aws.String(d.Get("load_balancer").(string)) 163 164 // Retrieve the current ELB policies for updating the state 165 req := &elb.DescribeLoadBalancersInput{ 166 LoadBalancerNames: []*string{elbname}, 167 } 168 var err error 169 resp, err := elbconn.DescribeLoadBalancers(req) 170 if err != nil { 171 if isLoadBalancerNotFound(err) { 172 // The ELB is gone now, so just remove it from the state 173 d.SetId("") 174 return nil 175 } 176 return fmt.Errorf("Error retrieving ELB attributes: %s", err) 177 } 178 179 backends := flattenBackendPolicies(resp.LoadBalancerDescriptions[0].BackendServerDescriptions) 180 ports := d.Get("instance_ports").(*schema.Set).List() 181 _, policyName := resourceAwsProxyProtocolPolicyParseId(d.Id()) 182 183 inputs, err := resourceAwsProxyProtocolPolicyRemove(policyName, ports, backends) 184 if err != nil { 185 return fmt.Errorf("Error detaching a policy from backend: %s", err) 186 } 187 for _, input := range inputs { 188 input.LoadBalancerName = elbname 189 if _, err := elbconn.SetLoadBalancerPoliciesForBackendServer(input); err != nil { 190 return fmt.Errorf("Error setting policy for backend: %s", err) 191 } 192 } 193 194 pOpt := &elb.DeleteLoadBalancerPolicyInput{ 195 LoadBalancerName: elbname, 196 PolicyName: aws.String(policyName), 197 } 198 if _, err := elbconn.DeleteLoadBalancerPolicy(pOpt); err != nil { 199 return fmt.Errorf("Error removing a policy from load balancer: %s", err) 200 } 201 202 return nil 203 } 204 205 func resourceAwsProxyProtocolPolicyRemove(policyName string, ports []interface{}, backends map[int64][]string) ([]*elb.SetLoadBalancerPoliciesForBackendServerInput, error) { 206 inputs := make([]*elb.SetLoadBalancerPoliciesForBackendServerInput, 0, len(ports)) 207 for _, p := range ports { 208 ip, err := strconv.ParseInt(p.(string), 10, 64) 209 if err != nil { 210 return nil, fmt.Errorf("Error detaching the policy: %s", err) 211 } 212 213 newPolicies := []*string{} 214 curPolicies, found := backends[ip] 215 if !found { 216 // No policy for this instance port found, just skip it. 217 continue 218 } 219 220 for _, policy := range curPolicies { 221 if policy == policyName { 222 // remove the policy 223 continue 224 } 225 newPolicies = append(newPolicies, &policy) 226 } 227 228 inputs = append(inputs, &elb.SetLoadBalancerPoliciesForBackendServerInput{ 229 InstancePort: &ip, 230 PolicyNames: newPolicies, 231 }) 232 } 233 return inputs, nil 234 } 235 236 func resourceAwsProxyProtocolPolicyAdd(policyName string, ports []interface{}, backends map[int64][]string) ([]*elb.SetLoadBalancerPoliciesForBackendServerInput, error) { 237 inputs := make([]*elb.SetLoadBalancerPoliciesForBackendServerInput, 0, len(ports)) 238 for _, p := range ports { 239 ip, err := strconv.ParseInt(p.(string), 10, 64) 240 if err != nil { 241 return nil, fmt.Errorf("Error attaching the policy: %s", err) 242 } 243 244 newPolicies := []*string{} 245 curPolicies := backends[ip] 246 for _, p := range curPolicies { 247 if p == policyName { 248 // Just remove it for now. It will be back later. 249 continue 250 } else { 251 newPolicies = append(newPolicies, &p) 252 } 253 } 254 newPolicies = append(newPolicies, aws.String(policyName)) 255 256 inputs = append(inputs, &elb.SetLoadBalancerPoliciesForBackendServerInput{ 257 InstancePort: &ip, 258 PolicyNames: newPolicies, 259 }) 260 } 261 return inputs, nil 262 } 263 264 // resourceAwsProxyProtocolPolicyParseId takes an ID and parses it into 265 // it's constituent parts. You need two axes (LB name, policy name) 266 // to create or identify a proxy protocol policy in AWS's API. 267 func resourceAwsProxyProtocolPolicyParseId(id string) (string, string) { 268 parts := strings.SplitN(id, ":", 2) 269 return parts[0], parts[1] 270 }