github.com/pmcatominey/terraform@v0.7.0-rc2.0.20160708105029-1401a52a5cc5/builtin/providers/openstack/resource_openstack_lb_loadbalancer_v2.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "github.com/rackspace/gophercloud" 12 "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers" 13 ) 14 15 func resourceLoadBalancerV2() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceLoadBalancerV2Create, 18 Read: resourceLoadBalancerV2Read, 19 Update: resourceLoadBalancerV2Update, 20 Delete: resourceLoadBalancerV2Delete, 21 22 Schema: map[string]*schema.Schema{ 23 "region": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 28 }, 29 30 "name": &schema.Schema{ 31 Type: schema.TypeString, 32 Optional: true, 33 }, 34 35 "description": &schema.Schema{ 36 Type: schema.TypeString, 37 Optional: true, 38 }, 39 40 "vip_subnet_id": &schema.Schema{ 41 Type: schema.TypeString, 42 Required: true, 43 ForceNew: true, 44 }, 45 46 "tenant_id": &schema.Schema{ 47 Type: schema.TypeString, 48 Optional: true, 49 Computed: true, 50 ForceNew: true, 51 }, 52 53 "vip_address": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 Computed: true, 57 ForceNew: true, 58 }, 59 60 "admin_state_up": &schema.Schema{ 61 Type: schema.TypeBool, 62 Optional: true, 63 }, 64 65 "flavor": &schema.Schema{ 66 Type: schema.TypeString, 67 Optional: true, 68 ForceNew: true, 69 }, 70 71 "provider": &schema.Schema{ 72 Type: schema.TypeString, 73 Optional: true, 74 Computed: true, 75 ForceNew: true, 76 }, 77 }, 78 } 79 } 80 81 func resourceLoadBalancerV2Create(d *schema.ResourceData, meta interface{}) error { 82 config := meta.(*Config) 83 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 84 if err != nil { 85 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 86 } 87 88 adminStateUp := d.Get("admin_state_up").(bool) 89 createOpts := loadbalancers.CreateOpts{ 90 Name: d.Get("name").(string), 91 Description: d.Get("description").(string), 92 VipSubnetID: d.Get("vip_subnet_id").(string), 93 TenantID: d.Get("tenant_id").(string), 94 VipAddress: d.Get("vip_address").(string), 95 AdminStateUp: &adminStateUp, 96 Flavor: d.Get("flavor").(string), 97 Provider: d.Get("provider").(string), 98 } 99 100 log.Printf("[DEBUG] Create Options: %#v", createOpts) 101 lb, err := loadbalancers.Create(networkingClient, createOpts).Extract() 102 if err != nil { 103 return fmt.Errorf("Error creating OpenStack LoadBalancer: %s", err) 104 } 105 log.Printf("[INFO] LoadBalancer ID: %s", lb.ID) 106 107 log.Printf("[DEBUG] Waiting for Openstack LoadBalancer (%s) to become available.", lb.ID) 108 109 stateConf := &resource.StateChangeConf{ 110 Pending: []string{"PENDING_CREATE"}, 111 Target: []string{"ACTIVE"}, 112 Refresh: waitForLoadBalancerActive(networkingClient, lb.ID), 113 Timeout: 20 * time.Minute, 114 Delay: 5 * time.Second, 115 MinTimeout: 3 * time.Second, 116 } 117 118 _, err = stateConf.WaitForState() 119 if err != nil { 120 return err 121 } 122 123 d.SetId(lb.ID) 124 125 return resourceLoadBalancerV2Read(d, meta) 126 } 127 128 func resourceLoadBalancerV2Read(d *schema.ResourceData, meta interface{}) error { 129 config := meta.(*Config) 130 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 131 if err != nil { 132 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 133 } 134 135 lb, err := loadbalancers.Get(networkingClient, d.Id()).Extract() 136 if err != nil { 137 return CheckDeleted(d, err, "LoadBalancerV2") 138 } 139 140 log.Printf("[DEBUG] Retreived OpenStack LoadBalancerV2 %s: %+v", d.Id(), lb) 141 142 d.Set("name", lb.Name) 143 d.Set("description", lb.Description) 144 d.Set("vip_subnet_id", lb.VipSubnetID) 145 d.Set("tenant_id", lb.TenantID) 146 d.Set("vip_address", lb.VipAddress) 147 d.Set("admin_state_up", lb.AdminStateUp) 148 d.Set("flavor", lb.Flavor) 149 d.Set("provider", lb.Provider) 150 151 return nil 152 } 153 154 func resourceLoadBalancerV2Update(d *schema.ResourceData, meta interface{}) error { 155 config := meta.(*Config) 156 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 157 if err != nil { 158 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 159 } 160 161 var updateOpts loadbalancers.UpdateOpts 162 if d.HasChange("name") { 163 updateOpts.Name = d.Get("name").(string) 164 } 165 if d.HasChange("description") { 166 updateOpts.Description = d.Get("description").(string) 167 } 168 if d.HasChange("admin_state_up") { 169 asu := d.Get("admin_state_up").(bool) 170 updateOpts.AdminStateUp = &asu 171 } 172 173 log.Printf("[DEBUG] Updating OpenStack LBaaSV2 LoadBalancer %s with options: %+v", d.Id(), updateOpts) 174 175 _, err = loadbalancers.Update(networkingClient, d.Id(), updateOpts).Extract() 176 if err != nil { 177 return fmt.Errorf("Error updating OpenStack LBaaSV2 LoadBalancer: %s", err) 178 } 179 180 return resourceLoadBalancerV2Read(d, meta) 181 } 182 183 func resourceLoadBalancerV2Delete(d *schema.ResourceData, meta interface{}) error { 184 config := meta.(*Config) 185 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 186 if err != nil { 187 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 188 } 189 190 stateConf := &resource.StateChangeConf{ 191 Pending: []string{"ACTIVE", "PENDING_DELETE"}, 192 Target: []string{"DELETED"}, 193 Refresh: waitForLoadBalancerDelete(networkingClient, d.Id()), 194 Timeout: 2 * time.Minute, 195 Delay: 5 * time.Second, 196 MinTimeout: 3 * time.Second, 197 } 198 199 _, err = stateConf.WaitForState() 200 if err != nil { 201 return fmt.Errorf("Error deleting OpenStack LB Pool: %s", err) 202 } 203 204 d.SetId("") 205 return nil 206 } 207 208 func waitForLoadBalancerActive(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 209 return func() (interface{}, string, error) { 210 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 211 if err != nil { 212 return nil, "", err 213 } 214 215 log.Printf("[DEBUG] OpenStack LoadBalancer: %+v", lb) 216 if lb.ProvisioningStatus == "ACTIVE" { 217 return lb, "ACTIVE", nil 218 } 219 220 return lb, lb.ProvisioningStatus, nil 221 } 222 } 223 224 func waitForLoadBalancerDelete(networkingClient *gophercloud.ServiceClient, lbID string) resource.StateRefreshFunc { 225 return func() (interface{}, string, error) { 226 log.Printf("[DEBUG] Attempting to delete OpenStack LoadBalancerV2 %s", lbID) 227 228 lb, err := loadbalancers.Get(networkingClient, lbID).Extract() 229 if err != nil { 230 errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) 231 if !ok { 232 return lb, "ACTIVE", err 233 } 234 if errCode.Actual == 404 { 235 log.Printf("[DEBUG] Successfully deleted OpenStack LoadBalancerV2 %s", lbID) 236 return lb, "DELETED", nil 237 } 238 } 239 240 log.Printf("[DEBUG] Openstack LoadBalancerV2: %+v", lb) 241 err = loadbalancers.Delete(networkingClient, lbID).ExtractErr() 242 if err != nil { 243 errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) 244 if !ok { 245 return lb, "ACTIVE", err 246 } 247 if errCode.Actual == 404 { 248 log.Printf("[DEBUG] Successfully deleted OpenStack LoadBalancerV2 %s", lbID) 249 return lb, "DELETED", nil 250 } 251 } 252 253 log.Printf("[DEBUG] OpenStack LoadBalancerV2 %s still active.", lbID) 254 return lb, "ACTIVE", nil 255 } 256 }