github.com/danrjohnson/terraform@v0.7.0-rc2.0.20160627135212-d0fc1fa086ff/builtin/providers/datadog/resource_datadog_monitor.go (about) 1 package datadog 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "strconv" 8 "strings" 9 10 "github.com/hashicorp/terraform/helper/schema" 11 "github.com/zorkian/go-datadog-api" 12 ) 13 14 func resourceDatadogMonitor() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceDatadogMonitorCreate, 17 Read: resourceDatadogMonitorRead, 18 Update: resourceDatadogMonitorUpdate, 19 Delete: resourceDatadogMonitorDelete, 20 Exists: resourceDatadogMonitorExists, 21 22 Schema: map[string]*schema.Schema{ 23 "name": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 }, 27 "message": &schema.Schema{ 28 Type: schema.TypeString, 29 Required: true, 30 StateFunc: func(val interface{}) string { 31 return strings.TrimSpace(val.(string)) 32 }, 33 }, 34 "escalation_message": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 StateFunc: func(val interface{}) string { 38 return strings.TrimSpace(val.(string)) 39 }, 40 }, 41 "query": &schema.Schema{ 42 Type: schema.TypeString, 43 Required: true, 44 StateFunc: func(val interface{}) string { 45 return strings.TrimSpace(val.(string)) 46 }, 47 }, 48 "type": &schema.Schema{ 49 Type: schema.TypeString, 50 Required: true, 51 }, 52 53 // Options 54 "thresholds": &schema.Schema{ 55 Type: schema.TypeMap, 56 Required: true, 57 Elem: &schema.Resource{ 58 Schema: map[string]*schema.Schema{ 59 "ok": &schema.Schema{ 60 Type: schema.TypeFloat, 61 Optional: true, 62 }, 63 "warning": &schema.Schema{ 64 Type: schema.TypeFloat, 65 Optional: true, 66 }, 67 "critical": &schema.Schema{ 68 Type: schema.TypeFloat, 69 Required: true, 70 }, 71 }, 72 }, 73 }, 74 "notify_no_data": &schema.Schema{ 75 Type: schema.TypeBool, 76 Optional: true, 77 Default: true, 78 }, 79 "no_data_timeframe": &schema.Schema{ 80 Type: schema.TypeInt, 81 Optional: true, 82 }, 83 "renotify_interval": &schema.Schema{ 84 Type: schema.TypeInt, 85 Optional: true, 86 }, 87 "notify_audit": &schema.Schema{ 88 Type: schema.TypeBool, 89 Optional: true, 90 }, 91 "timeout_h": &schema.Schema{ 92 Type: schema.TypeInt, 93 Optional: true, 94 }, 95 "require_full_window": &schema.Schema{ 96 Type: schema.TypeBool, 97 Optional: true, 98 }, 99 "locked": &schema.Schema{ 100 Type: schema.TypeBool, 101 Optional: true, 102 }, 103 // TODO should actually be map[string]int 104 "silenced": &schema.Schema{ 105 Type: schema.TypeMap, 106 Optional: true, 107 Elem: &schema.Schema{ 108 Type: schema.TypeString, 109 Elem: &schema.Schema{ 110 Type: schema.TypeInt}, 111 }, 112 }, 113 "include_tags": &schema.Schema{ 114 Type: schema.TypeBool, 115 Optional: true, 116 }, 117 }, 118 } 119 } 120 121 func buildMonitorStruct(d *schema.ResourceData) *datadog.Monitor { 122 123 var thresholds datadog.ThresholdCount 124 125 if r, ok := d.GetOk("thresholds.ok"); ok { 126 thresholds.Ok = json.Number(r.(string)) 127 } 128 if r, ok := d.GetOk("thresholds.warning"); ok { 129 thresholds.Warning = json.Number(r.(string)) 130 } 131 if r, ok := d.GetOk("thresholds.critical"); ok { 132 thresholds.Critical = json.Number(r.(string)) 133 } 134 135 o := datadog.Options{ 136 Thresholds: thresholds, 137 } 138 if attr, ok := d.GetOk("silenced"); ok { 139 s := make(map[string]int) 140 // TODO: this is not very defensive, test if we can fail on non int input 141 for k, v := range attr.(map[string]interface{}) { 142 s[k], _ = strconv.Atoi(v.(string)) 143 } 144 o.Silenced = s 145 } 146 if attr, ok := d.GetOk("notify_no_data"); ok { 147 o.NotifyNoData = attr.(bool) 148 } 149 if attr, ok := d.GetOk("no_data_timeframe"); ok { 150 o.NoDataTimeframe = attr.(int) 151 } 152 if attr, ok := d.GetOk("renotify_interval"); ok { 153 o.RenotifyInterval = attr.(int) 154 } 155 if attr, ok := d.GetOk("notify_audit"); ok { 156 o.NotifyAudit = attr.(bool) 157 } 158 if attr, ok := d.GetOk("timeout_h"); ok { 159 o.TimeoutH = attr.(int) 160 } 161 if attr, ok := d.GetOk("escalation_message"); ok { 162 o.EscalationMessage = attr.(string) 163 } 164 if attr, ok := d.GetOk("include_tags"); ok { 165 o.IncludeTags = attr.(bool) 166 } 167 if attr, ok := d.GetOk("require_full_window"); ok { 168 o.RequireFullWindow = attr.(bool) 169 } 170 if attr, ok := d.GetOk("locked"); ok { 171 o.Locked = attr.(bool) 172 } 173 174 m := datadog.Monitor{ 175 Type: d.Get("type").(string), 176 Query: d.Get("query").(string), 177 Name: d.Get("name").(string), 178 Message: d.Get("message").(string), 179 Options: o, 180 } 181 182 return &m 183 } 184 185 func resourceDatadogMonitorExists(d *schema.ResourceData, meta interface{}) (b bool, e error) { 186 // Exists - This is called to verify a resource still exists. It is called prior to Read, 187 // and lowers the burden of Read to be able to assume the resource exists. 188 client := meta.(*datadog.Client) 189 190 i, err := strconv.Atoi(d.Id()) 191 if err != nil { 192 return false, err 193 } 194 195 if _, err = client.GetMonitor(i); err != nil { 196 if strings.Contains(err.Error(), "404 Not Found") { 197 return false, nil 198 } 199 return false, err 200 } 201 202 return true, nil 203 } 204 205 func resourceDatadogMonitorCreate(d *schema.ResourceData, meta interface{}) error { 206 207 client := meta.(*datadog.Client) 208 209 m := buildMonitorStruct(d) 210 m, err := client.CreateMonitor(m) 211 if err != nil { 212 return fmt.Errorf("error updating montor: %s", err.Error()) 213 } 214 215 d.SetId(strconv.Itoa(m.Id)) 216 217 return nil 218 } 219 220 func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error { 221 client := meta.(*datadog.Client) 222 223 i, err := strconv.Atoi(d.Id()) 224 if err != nil { 225 return err 226 } 227 228 m, err := client.GetMonitor(i) 229 if err != nil { 230 return err 231 } 232 233 log.Printf("[DEBUG] monitor: %v", m) 234 d.Set("name", m.Name) 235 d.Set("message", m.Message) 236 d.Set("query", m.Query) 237 d.Set("type", m.Type) 238 d.Set("thresholds", m.Options.Thresholds) 239 d.Set("notify_no_data", m.Options.NotifyNoData) 240 d.Set("no_data_timeframe", m.Options.NoDataTimeframe) 241 d.Set("renotify_interval", m.Options.RenotifyInterval) 242 d.Set("notify_audit", m.Options.NotifyAudit) 243 d.Set("timeout_h", m.Options.TimeoutH) 244 d.Set("escalation_message", m.Options.EscalationMessage) 245 d.Set("silenced", m.Options.Silenced) 246 d.Set("include_tags", m.Options.IncludeTags) 247 d.Set("require_full_window", m.Options.RequireFullWindow) 248 d.Set("locked", m.Options.Locked) 249 250 return nil 251 } 252 253 func resourceDatadogMonitorUpdate(d *schema.ResourceData, meta interface{}) error { 254 client := meta.(*datadog.Client) 255 256 m := &datadog.Monitor{} 257 258 i, err := strconv.Atoi(d.Id()) 259 if err != nil { 260 return err 261 } 262 263 m.Id = i 264 if attr, ok := d.GetOk("name"); ok { 265 m.Name = attr.(string) 266 } 267 if attr, ok := d.GetOk("message"); ok { 268 m.Message = attr.(string) 269 } 270 if attr, ok := d.GetOk("query"); ok { 271 m.Query = attr.(string) 272 } 273 274 o := datadog.Options{} 275 if attr, ok := d.GetOk("thresholds"); ok { 276 thresholds := attr.(map[string]interface{}) 277 if thresholds["ok"] != nil { 278 o.Thresholds.Ok = json.Number(thresholds["ok"].(string)) 279 } 280 if thresholds["warning"] != nil { 281 o.Thresholds.Warning = json.Number(thresholds["warning"].(string)) 282 } 283 if thresholds["critical"] != nil { 284 o.Thresholds.Critical = json.Number(thresholds["critical"].(string)) 285 } 286 } 287 288 if attr, ok := d.GetOk("notify_no_data"); ok { 289 o.NotifyNoData = attr.(bool) 290 } 291 if attr, ok := d.GetOk("no_data_timeframe"); ok { 292 o.NoDataTimeframe = attr.(int) 293 } 294 if attr, ok := d.GetOk("renotify_interval"); ok { 295 o.RenotifyInterval = attr.(int) 296 } 297 if attr, ok := d.GetOk("notify_audit"); ok { 298 o.NotifyAudit = attr.(bool) 299 } 300 if attr, ok := d.GetOk("timeout_h"); ok { 301 o.TimeoutH = attr.(int) 302 } 303 if attr, ok := d.GetOk("escalation_message"); ok { 304 o.EscalationMessage = attr.(string) 305 } 306 if attr, ok := d.GetOk("silenced"); ok { 307 // TODO: this is not very defensive, test if we can fail non int input 308 s := make(map[string]int) 309 for k, v := range attr.(map[string]interface{}) { 310 s[k], _ = strconv.Atoi(v.(string)) 311 } 312 o.Silenced = s 313 } 314 if attr, ok := d.GetOk("include_tags"); ok { 315 o.IncludeTags = attr.(bool) 316 } 317 if attr, ok := d.GetOk("require_full_window"); ok { 318 o.RequireFullWindow = attr.(bool) 319 } 320 if attr, ok := d.GetOk("locked"); ok { 321 o.Locked = attr.(bool) 322 } 323 324 m.Options = o 325 326 if err = client.UpdateMonitor(m); err != nil { 327 return fmt.Errorf("error updating monitor: %s", err.Error()) 328 } 329 330 return resourceDatadogMonitorRead(d, meta) 331 } 332 333 func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) error { 334 client := meta.(*datadog.Client) 335 336 i, err := strconv.Atoi(d.Id()) 337 if err != nil { 338 return err 339 } 340 341 if err = client.DeleteMonitor(i); err != nil { 342 return err 343 } 344 345 return nil 346 }