github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/builtin/providers/openstack/resource_openstack_lb_pool_v1.go (about) 1 package openstack 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 8 "github.com/hashicorp/terraform/helper/hashcode" 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members" 11 "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools" 12 "github.com/rackspace/gophercloud/pagination" 13 ) 14 15 func resourceLBPoolV1() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceLBPoolV1Create, 18 Read: resourceLBPoolV1Read, 19 Update: resourceLBPoolV1Update, 20 Delete: resourceLBPoolV1Delete, 21 22 Schema: map[string]*schema.Schema{ 23 "region": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 DefaultFunc: envDefaultFunc("OS_REGION_NAME"), 28 }, 29 "name": &schema.Schema{ 30 Type: schema.TypeString, 31 Required: true, 32 ForceNew: false, 33 }, 34 "protocol": &schema.Schema{ 35 Type: schema.TypeString, 36 Required: true, 37 ForceNew: true, 38 }, 39 "subnet_id": &schema.Schema{ 40 Type: schema.TypeString, 41 Required: true, 42 ForceNew: true, 43 }, 44 45 "lb_method": &schema.Schema{ 46 Type: schema.TypeString, 47 Required: true, 48 ForceNew: false, 49 }, 50 "tenant_id": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 ForceNew: true, 54 }, 55 "member": &schema.Schema{ 56 Type: schema.TypeSet, 57 Optional: true, 58 Elem: &schema.Resource{ 59 Schema: map[string]*schema.Schema{ 60 "region": &schema.Schema{ 61 Type: schema.TypeString, 62 Required: true, 63 ForceNew: true, 64 DefaultFunc: envDefaultFunc("OS_REGION_NAME"), 65 }, 66 "tenant_id": &schema.Schema{ 67 Type: schema.TypeString, 68 Optional: true, 69 ForceNew: true, 70 }, 71 "address": &schema.Schema{ 72 Type: schema.TypeString, 73 Required: true, 74 ForceNew: true, 75 }, 76 "port": &schema.Schema{ 77 Type: schema.TypeInt, 78 Required: true, 79 ForceNew: true, 80 }, 81 "admin_state_up": &schema.Schema{ 82 Type: schema.TypeBool, 83 Required: true, 84 ForceNew: false, 85 }, 86 }, 87 }, 88 Set: resourceLBMemberV1Hash, 89 }, 90 "monitor_ids": &schema.Schema{ 91 Type: schema.TypeSet, 92 Optional: true, 93 ForceNew: false, 94 Elem: &schema.Schema{Type: schema.TypeString}, 95 Set: func(v interface{}) int { 96 return hashcode.String(v.(string)) 97 }, 98 }, 99 }, 100 } 101 } 102 103 func resourceLBPoolV1Create(d *schema.ResourceData, meta interface{}) error { 104 config := meta.(*Config) 105 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 106 if err != nil { 107 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 108 } 109 110 createOpts := pools.CreateOpts{ 111 Name: d.Get("name").(string), 112 Protocol: d.Get("protocol").(string), 113 SubnetID: d.Get("subnet_id").(string), 114 LBMethod: d.Get("lb_method").(string), 115 TenantID: d.Get("tenant_id").(string), 116 } 117 118 log.Printf("[DEBUG] Create Options: %#v", createOpts) 119 p, err := pools.Create(networkingClient, createOpts).Extract() 120 if err != nil { 121 return fmt.Errorf("Error creating OpenStack LB pool: %s", err) 122 } 123 log.Printf("[INFO] LB Pool ID: %s", p.ID) 124 125 d.SetId(p.ID) 126 127 if mIDs := resourcePoolMonitorIDsV1(d); mIDs != nil { 128 for _, mID := range mIDs { 129 _, err := pools.AssociateMonitor(networkingClient, p.ID, mID).Extract() 130 if err != nil { 131 return fmt.Errorf("Error associating monitor (%s) with OpenStack LB pool (%s): %s", mID, p.ID, err) 132 } 133 } 134 } 135 136 if memberOpts := resourcePoolMembersV1(d); memberOpts != nil { 137 for _, memberOpt := range memberOpts { 138 _, err := members.Create(networkingClient, memberOpt).Extract() 139 if err != nil { 140 return fmt.Errorf("Error creating OpenStack LB member: %s", err) 141 } 142 } 143 } 144 145 return resourceLBPoolV1Read(d, meta) 146 } 147 148 func resourceLBPoolV1Read(d *schema.ResourceData, meta interface{}) error { 149 config := meta.(*Config) 150 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 151 if err != nil { 152 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 153 } 154 155 p, err := pools.Get(networkingClient, d.Id()).Extract() 156 if err != nil { 157 return CheckDeleted(d, err, "LB pool") 158 } 159 160 log.Printf("[DEBUG] Retreived OpenStack LB Pool %s: %+v", d.Id(), p) 161 162 d.Set("name", p.Name) 163 d.Set("protocol", p.Protocol) 164 d.Set("subnet_id", p.SubnetID) 165 d.Set("lb_method", p.LBMethod) 166 d.Set("tenant_id", p.TenantID) 167 d.Set("monitor_ids", p.MonitorIDs) 168 d.Set("member_ids", p.MemberIDs) 169 170 return nil 171 } 172 173 func resourceLBPoolV1Update(d *schema.ResourceData, meta interface{}) error { 174 config := meta.(*Config) 175 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 176 if err != nil { 177 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 178 } 179 180 var updateOpts pools.UpdateOpts 181 if d.HasChange("name") { 182 updateOpts.Name = d.Get("name").(string) 183 } 184 if d.HasChange("lb_method") { 185 updateOpts.LBMethod = d.Get("lb_method").(string) 186 } 187 188 log.Printf("[DEBUG] Updating OpenStack LB Pool %s with options: %+v", d.Id(), updateOpts) 189 190 _, err = pools.Update(networkingClient, d.Id(), updateOpts).Extract() 191 if err != nil { 192 return fmt.Errorf("Error updating OpenStack LB Pool: %s", err) 193 } 194 195 if d.HasChange("monitor_ids") { 196 oldMIDsRaw, newMIDsRaw := d.GetChange("security_groups") 197 oldMIDsSet, newMIDsSet := oldMIDsRaw.(*schema.Set), newMIDsRaw.(*schema.Set) 198 monitorsToAdd := newMIDsSet.Difference(oldMIDsSet) 199 monitorsToRemove := oldMIDsSet.Difference(newMIDsSet) 200 201 log.Printf("[DEBUG] Monitors to add: %v", monitorsToAdd) 202 203 log.Printf("[DEBUG] Monitors to remove: %v", monitorsToRemove) 204 205 for _, m := range monitorsToAdd.List() { 206 _, err := pools.AssociateMonitor(networkingClient, d.Id(), m.(string)).Extract() 207 if err != nil { 208 return fmt.Errorf("Error associating monitor (%s) with OpenStack server (%s): %s", m.(string), d.Id(), err) 209 } 210 log.Printf("[DEBUG] Associated monitor (%s) with pool (%s)", m.(string), d.Id()) 211 } 212 213 for _, m := range monitorsToRemove.List() { 214 _, err := pools.DisassociateMonitor(networkingClient, d.Id(), m.(string)).Extract() 215 if err != nil { 216 return fmt.Errorf("Error disassociating monitor (%s) from OpenStack server (%s): %s", m.(string), d.Id(), err) 217 } 218 log.Printf("[DEBUG] Disassociated monitor (%s) from pool (%s)", m.(string), d.Id()) 219 } 220 } 221 222 if d.HasChange("member") { 223 oldMembersRaw, newMembersRaw := d.GetChange("member") 224 oldMembersSet, newMembersSet := oldMembersRaw.(*schema.Set), newMembersRaw.(*schema.Set) 225 membersToAdd := newMembersSet.Difference(oldMembersSet) 226 membersToRemove := oldMembersSet.Difference(newMembersSet) 227 228 log.Printf("[DEBUG] Members to add: %v", membersToAdd) 229 230 log.Printf("[DEBUG] Members to remove: %v", membersToRemove) 231 232 for _, m := range membersToRemove.List() { 233 oldMember := resourcePoolMemberV1(d, m) 234 listOpts := members.ListOpts{ 235 PoolID: d.Id(), 236 Address: oldMember.Address, 237 ProtocolPort: oldMember.ProtocolPort, 238 } 239 err = members.List(networkingClient, listOpts).EachPage(func(page pagination.Page) (bool, error) { 240 extractedMembers, err := members.ExtractMembers(page) 241 if err != nil { 242 return false, err 243 } 244 for _, member := range extractedMembers { 245 err := members.Delete(networkingClient, member.ID).ExtractErr() 246 if err != nil { 247 return false, fmt.Errorf("Error deleting member (%s) from OpenStack LB pool (%s): %s", member.ID, d.Id(), err) 248 } 249 log.Printf("[DEBUG] Deleted member (%s) from pool (%s)", member.ID, d.Id()) 250 } 251 return true, nil 252 }) 253 } 254 255 for _, m := range membersToAdd.List() { 256 createOpts := resourcePoolMemberV1(d, m) 257 newMember, err := members.Create(networkingClient, createOpts).Extract() 258 if err != nil { 259 return fmt.Errorf("Error creating LB member: %s", err) 260 } 261 log.Printf("[DEBUG] Created member (%s) in OpenStack LB pool (%s)", newMember.ID, d.Id()) 262 } 263 } 264 265 return resourceLBPoolV1Read(d, meta) 266 } 267 268 func resourceLBPoolV1Delete(d *schema.ResourceData, meta interface{}) error { 269 config := meta.(*Config) 270 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 271 if err != nil { 272 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 273 } 274 275 err = pools.Delete(networkingClient, d.Id()).ExtractErr() 276 if err != nil { 277 return fmt.Errorf("Error deleting OpenStack LB Pool: %s", err) 278 } 279 280 d.SetId("") 281 return nil 282 } 283 284 func resourcePoolMonitorIDsV1(d *schema.ResourceData) []string { 285 mIDsRaw := d.Get("monitor_ids").(*schema.Set) 286 mIDs := make([]string, mIDsRaw.Len()) 287 for i, raw := range mIDsRaw.List() { 288 mIDs[i] = raw.(string) 289 } 290 return mIDs 291 } 292 293 func resourcePoolMembersV1(d *schema.ResourceData) []members.CreateOpts { 294 memberOptsRaw := (d.Get("member")).(*schema.Set) 295 memberOpts := make([]members.CreateOpts, memberOptsRaw.Len()) 296 for i, raw := range memberOptsRaw.List() { 297 rawMap := raw.(map[string]interface{}) 298 memberOpts[i] = members.CreateOpts{ 299 TenantID: rawMap["tenant_id"].(string), 300 Address: rawMap["address"].(string), 301 ProtocolPort: rawMap["port"].(int), 302 PoolID: d.Id(), 303 } 304 } 305 return memberOpts 306 } 307 308 func resourcePoolMemberV1(d *schema.ResourceData, raw interface{}) members.CreateOpts { 309 rawMap := raw.(map[string]interface{}) 310 return members.CreateOpts{ 311 TenantID: rawMap["tenant_id"].(string), 312 Address: rawMap["address"].(string), 313 ProtocolPort: rawMap["port"].(int), 314 PoolID: d.Id(), 315 } 316 } 317 318 func resourceLBMemberV1Hash(v interface{}) int { 319 var buf bytes.Buffer 320 m := v.(map[string]interface{}) 321 buf.WriteString(fmt.Sprintf("%s-", m["region"].(string))) 322 buf.WriteString(fmt.Sprintf("%s-", m["tenant_id"].(string))) 323 buf.WriteString(fmt.Sprintf("%s-", m["address"].(string))) 324 buf.WriteString(fmt.Sprintf("%d-", m["port"].(int))) 325 326 return hashcode.String(buf.String()) 327 }