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