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