github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/openstack/resource_openstack_lb_monitor_v1.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "time" 8 9 "github.com/hashicorp/terraform/helper/resource" 10 "github.com/hashicorp/terraform/helper/schema" 11 12 "github.com/gophercloud/gophercloud" 13 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors" 14 ) 15 16 func resourceLBMonitorV1() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceLBMonitorV1Create, 19 Read: resourceLBMonitorV1Read, 20 Update: resourceLBMonitorV1Update, 21 Delete: resourceLBMonitorV1Delete, 22 Importer: &schema.ResourceImporter{ 23 State: schema.ImportStatePassthrough, 24 }, 25 26 Schema: map[string]*schema.Schema{ 27 "region": &schema.Schema{ 28 Type: schema.TypeString, 29 Required: true, 30 ForceNew: true, 31 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 32 }, 33 "tenant_id": &schema.Schema{ 34 Type: schema.TypeString, 35 Optional: true, 36 ForceNew: true, 37 Computed: true, 38 }, 39 "type": &schema.Schema{ 40 Type: schema.TypeString, 41 Required: true, 42 ForceNew: true, 43 }, 44 "delay": &schema.Schema{ 45 Type: schema.TypeInt, 46 Required: true, 47 ForceNew: false, 48 }, 49 "timeout": &schema.Schema{ 50 Type: schema.TypeInt, 51 Required: true, 52 ForceNew: false, 53 }, 54 "max_retries": &schema.Schema{ 55 Type: schema.TypeInt, 56 Required: true, 57 ForceNew: false, 58 }, 59 "url_path": &schema.Schema{ 60 Type: schema.TypeString, 61 Optional: true, 62 ForceNew: false, 63 }, 64 "http_method": &schema.Schema{ 65 Type: schema.TypeString, 66 Optional: true, 67 ForceNew: false, 68 }, 69 "expected_codes": &schema.Schema{ 70 Type: schema.TypeString, 71 Optional: true, 72 ForceNew: false, 73 }, 74 "admin_state_up": &schema.Schema{ 75 Type: schema.TypeString, 76 Optional: true, 77 ForceNew: false, 78 Computed: true, 79 }, 80 }, 81 } 82 } 83 84 func resourceLBMonitorV1Create(d *schema.ResourceData, meta interface{}) error { 85 config := meta.(*Config) 86 networkingClient, err := config.networkingV2Client(GetRegion(d)) 87 if err != nil { 88 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 89 } 90 91 createOpts := monitors.CreateOpts{ 92 TenantID: d.Get("tenant_id").(string), 93 Delay: d.Get("delay").(int), 94 Timeout: d.Get("timeout").(int), 95 MaxRetries: d.Get("max_retries").(int), 96 URLPath: d.Get("url_path").(string), 97 ExpectedCodes: d.Get("expected_codes").(string), 98 HTTPMethod: d.Get("http_method").(string), 99 } 100 101 if v, ok := d.GetOk("type"); ok { 102 monitorType := resourceLBMonitorV1DetermineType(v.(string)) 103 createOpts.Type = monitorType 104 } 105 106 asuRaw := d.Get("admin_state_up").(string) 107 if asuRaw != "" { 108 asu, err := strconv.ParseBool(asuRaw) 109 if err != nil { 110 return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'") 111 } 112 createOpts.AdminStateUp = &asu 113 } 114 115 log.Printf("[DEBUG] Create Options: %#v", createOpts) 116 m, err := monitors.Create(networkingClient, createOpts).Extract() 117 if err != nil { 118 return fmt.Errorf("Error creating OpenStack LB Monitor: %s", err) 119 } 120 log.Printf("[INFO] LB Monitor ID: %s", m.ID) 121 122 log.Printf("[DEBUG] Waiting for OpenStack LB Monitor (%s) to become available.", m.ID) 123 124 stateConf := &resource.StateChangeConf{ 125 Pending: []string{"PENDING_CREATE"}, 126 Target: []string{"ACTIVE"}, 127 Refresh: waitForLBMonitorActive(networkingClient, m.ID), 128 Timeout: 2 * time.Minute, 129 Delay: 5 * time.Second, 130 MinTimeout: 3 * time.Second, 131 } 132 133 _, err = stateConf.WaitForState() 134 if err != nil { 135 return err 136 } 137 138 d.SetId(m.ID) 139 140 return resourceLBMonitorV1Read(d, meta) 141 } 142 143 func resourceLBMonitorV1Read(d *schema.ResourceData, meta interface{}) error { 144 config := meta.(*Config) 145 networkingClient, err := config.networkingV2Client(GetRegion(d)) 146 if err != nil { 147 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 148 } 149 150 m, err := monitors.Get(networkingClient, d.Id()).Extract() 151 if err != nil { 152 return CheckDeleted(d, err, "LB monitor") 153 } 154 155 log.Printf("[DEBUG] Retrieved OpenStack LB Monitor %s: %+v", d.Id(), m) 156 157 d.Set("type", m.Type) 158 d.Set("delay", m.Delay) 159 d.Set("timeout", m.Timeout) 160 d.Set("max_retries", m.MaxRetries) 161 d.Set("tenant_id", m.TenantID) 162 d.Set("url_path", m.URLPath) 163 d.Set("http_method", m.HTTPMethod) 164 d.Set("expected_codes", m.ExpectedCodes) 165 d.Set("admin_state_up", strconv.FormatBool(m.AdminStateUp)) 166 d.Set("region", GetRegion(d)) 167 168 return nil 169 } 170 171 func resourceLBMonitorV1Update(d *schema.ResourceData, meta interface{}) error { 172 config := meta.(*Config) 173 networkingClient, err := config.networkingV2Client(GetRegion(d)) 174 if err != nil { 175 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 176 } 177 178 updateOpts := monitors.UpdateOpts{ 179 Delay: d.Get("delay").(int), 180 Timeout: d.Get("timeout").(int), 181 MaxRetries: d.Get("max_retries").(int), 182 URLPath: d.Get("url_path").(string), 183 HTTPMethod: d.Get("http_method").(string), 184 ExpectedCodes: d.Get("expected_codes").(string), 185 } 186 187 if d.HasChange("admin_state_up") { 188 asuRaw := d.Get("admin_state_up").(string) 189 if asuRaw != "" { 190 asu, err := strconv.ParseBool(asuRaw) 191 if err != nil { 192 return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'") 193 } 194 updateOpts.AdminStateUp = &asu 195 } 196 } 197 198 log.Printf("[DEBUG] Updating OpenStack LB Monitor %s with options: %+v", d.Id(), updateOpts) 199 200 _, err = monitors.Update(networkingClient, d.Id(), updateOpts).Extract() 201 if err != nil { 202 return fmt.Errorf("Error updating OpenStack LB Monitor: %s", err) 203 } 204 205 return resourceLBMonitorV1Read(d, meta) 206 } 207 208 func resourceLBMonitorV1Delete(d *schema.ResourceData, meta interface{}) error { 209 config := meta.(*Config) 210 networkingClient, err := config.networkingV2Client(GetRegion(d)) 211 if err != nil { 212 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 213 } 214 215 stateConf := &resource.StateChangeConf{ 216 Pending: []string{"ACTIVE", "PENDING_DELETE"}, 217 Target: []string{"DELETED"}, 218 Refresh: waitForLBMonitorDelete(networkingClient, d.Id()), 219 Timeout: 2 * time.Minute, 220 Delay: 5 * time.Second, 221 MinTimeout: 3 * time.Second, 222 } 223 224 _, err = stateConf.WaitForState() 225 if err != nil { 226 return fmt.Errorf("Error deleting OpenStack LB Monitor: %s", err) 227 } 228 229 d.SetId("") 230 return nil 231 } 232 233 func resourceLBMonitorV1DetermineType(t string) monitors.MonitorType { 234 var monitorType monitors.MonitorType 235 switch t { 236 case "PING": 237 monitorType = monitors.TypePING 238 case "TCP": 239 monitorType = monitors.TypeTCP 240 case "HTTP": 241 monitorType = monitors.TypeHTTP 242 case "HTTPS": 243 monitorType = monitors.TypeHTTPS 244 } 245 246 return monitorType 247 } 248 249 func waitForLBMonitorActive(networkingClient *gophercloud.ServiceClient, monitorId string) resource.StateRefreshFunc { 250 return func() (interface{}, string, error) { 251 m, err := monitors.Get(networkingClient, monitorId).Extract() 252 if err != nil { 253 return nil, "", err 254 } 255 256 // The monitor resource has no Status attribute, so a successful Get is the best we can do 257 log.Printf("[DEBUG] OpenStack LB Monitor: %+v", m) 258 return m, "ACTIVE", nil 259 } 260 } 261 262 func waitForLBMonitorDelete(networkingClient *gophercloud.ServiceClient, monitorId string) resource.StateRefreshFunc { 263 return func() (interface{}, string, error) { 264 log.Printf("[DEBUG] Attempting to delete OpenStack LB Monitor %s", monitorId) 265 266 m, err := monitors.Get(networkingClient, monitorId).Extract() 267 if err != nil { 268 if _, ok := err.(gophercloud.ErrDefault404); ok { 269 log.Printf("[DEBUG] Successfully deleted OpenStack LB Monitor %s", monitorId) 270 return m, "DELETED", nil 271 } 272 273 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 274 if errCode.Actual == 409 { 275 log.Printf("[DEBUG] OpenStack LB Monitor (%s) is waiting for Pool to delete.", monitorId) 276 return m, "PENDING", nil 277 } 278 } 279 280 return m, "ACTIVE", err 281 } 282 283 log.Printf("[DEBUG] OpenStack LB Monitor: %+v", m) 284 err = monitors.Delete(networkingClient, monitorId).ExtractErr() 285 if err != nil { 286 if _, ok := err.(gophercloud.ErrDefault404); ok { 287 log.Printf("[DEBUG] Successfully deleted OpenStack LB Monitor %s", monitorId) 288 return m, "DELETED", nil 289 } 290 291 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 292 if errCode.Actual == 409 { 293 log.Printf("[DEBUG] OpenStack LB Monitor (%s) is waiting for Pool to delete.", monitorId) 294 return m, "PENDING", nil 295 } 296 } 297 298 return m, "ACTIVE", err 299 } 300 301 log.Printf("[DEBUG] OpenStack LB Monitor %s still active.", monitorId) 302 return m, "ACTIVE", nil 303 } 304 305 }