github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/builtin/providers/datadog/resource_datadog_monitor.go (about) 1 package datadog 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "strings" 8 9 "encoding/json" 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 // TODO should actually be map[string]int 96 "silenced": &schema.Schema{ 97 Type: schema.TypeMap, 98 Optional: true, 99 Elem: &schema.Schema{ 100 Type: schema.TypeString, 101 Elem: &schema.Schema{ 102 Type: schema.TypeInt}, 103 }, 104 }, 105 "include_tags": &schema.Schema{ 106 Type: schema.TypeBool, 107 Optional: true, 108 }, 109 }, 110 } 111 } 112 113 func buildMonitorStruct(d *schema.ResourceData) *datadog.Monitor { 114 115 var thresholds datadog.ThresholdCount 116 117 if r, ok := d.GetOk("thresholds.ok"); ok { 118 thresholds.Ok = json.Number(r.(string)) 119 } 120 if r, ok := d.GetOk("thresholds.warning"); ok { 121 thresholds.Warning = json.Number(r.(string)) 122 } 123 if r, ok := d.GetOk("thresholds.critical"); ok { 124 thresholds.Critical = json.Number(r.(string)) 125 } 126 127 o := datadog.Options{ 128 Thresholds: thresholds, 129 } 130 if attr, ok := d.GetOk("silenced"); ok { 131 s := make(map[string]int) 132 // TODO: this is not very defensive, test if we can fail on non int input 133 for k, v := range attr.(map[string]interface{}) { 134 s[k], _ = strconv.Atoi(v.(string)) 135 } 136 o.Silenced = s 137 } 138 if attr, ok := d.GetOk("notify_data"); ok { 139 o.NotifyNoData = attr.(bool) 140 } 141 if attr, ok := d.GetOk("no_data_timeframe"); ok { 142 o.NoDataTimeframe = attr.(int) 143 } 144 if attr, ok := d.GetOk("renotify_interval"); ok { 145 o.RenotifyInterval = attr.(int) 146 } 147 if attr, ok := d.GetOk("notify_audit"); ok { 148 o.NotifyAudit = attr.(bool) 149 } 150 if attr, ok := d.GetOk("timeout_h"); ok { 151 o.TimeoutH = attr.(int) 152 } 153 if attr, ok := d.GetOk("escalation_message"); ok { 154 o.EscalationMessage = attr.(string) 155 } 156 if attr, ok := d.GetOk("escalation_message"); ok { 157 o.EscalationMessage = attr.(string) 158 } 159 if attr, ok := d.GetOk("include_tags"); ok { 160 o.IncludeTags = attr.(bool) 161 } 162 163 m := datadog.Monitor{ 164 Type: d.Get("type").(string), 165 Query: d.Get("query").(string), 166 Name: d.Get("name").(string), 167 Message: d.Get("message").(string), 168 Options: o, 169 } 170 171 return &m 172 } 173 174 func resourceDatadogMonitorExists(d *schema.ResourceData, meta interface{}) (b bool, e error) { 175 // Exists - This is called to verify a resource still exists. It is called prior to Read, 176 // and lowers the burden of Read to be able to assume the resource exists. 177 client := meta.(*datadog.Client) 178 179 i, err := strconv.Atoi(d.Id()) 180 if err != nil { 181 return false, err 182 } 183 184 if _, err = client.GetMonitor(i); err != nil { 185 if strings.Contains(err.Error(), "404 Not Found") { 186 return false, nil 187 } 188 return false, err 189 } 190 191 return true, nil 192 } 193 194 func resourceDatadogMonitorCreate(d *schema.ResourceData, meta interface{}) error { 195 196 client := meta.(*datadog.Client) 197 198 m := buildMonitorStruct(d) 199 m, err := client.CreateMonitor(m) 200 if err != nil { 201 return fmt.Errorf("error updating montor: %s", err.Error()) 202 } 203 204 d.SetId(strconv.Itoa(m.Id)) 205 206 return nil 207 } 208 209 func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error { 210 client := meta.(*datadog.Client) 211 212 i, err := strconv.Atoi(d.Id()) 213 if err != nil { 214 return err 215 } 216 217 m, err := client.GetMonitor(i) 218 if err != nil { 219 return err 220 } 221 222 log.Printf("[DEBUG] monitor: %v", m) 223 d.Set("name", m.Name) 224 d.Set("message", m.Message) 225 d.Set("query", m.Query) 226 d.Set("type", m.Type) 227 d.Set("thresholds", m.Options.Thresholds) 228 d.Set("notify_no_data", m.Options.NotifyNoData) 229 d.Set("notify_no_data_timeframe", m.Options.NoDataTimeframe) 230 d.Set("renotify_interval", m.Options.RenotifyInterval) 231 d.Set("notify_audit", m.Options.NotifyAudit) 232 d.Set("timeout_h", m.Options.TimeoutH) 233 d.Set("escalation_message", m.Options.EscalationMessage) 234 d.Set("silenced", m.Options.Silenced) 235 d.Set("include_tags", m.Options.IncludeTags) 236 237 return nil 238 } 239 240 func resourceDatadogMonitorUpdate(d *schema.ResourceData, meta interface{}) error { 241 client := meta.(*datadog.Client) 242 243 m := &datadog.Monitor{} 244 245 i, err := strconv.Atoi(d.Id()) 246 if err != nil { 247 return err 248 } 249 250 m.Id = i 251 if attr, ok := d.GetOk("name"); ok { 252 m.Name = attr.(string) 253 } 254 if attr, ok := d.GetOk("message"); ok { 255 m.Message = attr.(string) 256 } 257 if attr, ok := d.GetOk("query"); ok { 258 m.Query = attr.(string) 259 } 260 261 o := datadog.Options{} 262 if attr, ok := d.GetOk("thresholds"); ok { 263 thresholds := attr.(map[string]interface{}) 264 if thresholds["ok"] != nil { 265 o.Thresholds.Ok = json.Number(thresholds["ok"].(string)) 266 } 267 if thresholds["warning"] != nil { 268 o.Thresholds.Warning = json.Number(thresholds["warning"].(string)) 269 } 270 if thresholds["critical"] != nil { 271 o.Thresholds.Critical = json.Number(thresholds["critical"].(string)) 272 } 273 } 274 275 if attr, ok := d.GetOk("notify_no_data"); ok { 276 o.NotifyNoData = attr.(bool) 277 } 278 if attr, ok := d.GetOk("notify_no_data_timeframe"); ok { 279 o.NoDataTimeframe = attr.(int) 280 } 281 if attr, ok := d.GetOk("renotify_interval"); ok { 282 o.RenotifyInterval = attr.(int) 283 } 284 if attr, ok := d.GetOk("notify_audit"); ok { 285 o.NotifyAudit = attr.(bool) 286 } 287 if attr, ok := d.GetOk("timeout_h"); ok { 288 o.TimeoutH = attr.(int) 289 } 290 if attr, ok := d.GetOk("escalation_message"); ok { 291 o.EscalationMessage = attr.(string) 292 } 293 if attr, ok := d.GetOk("silenced"); ok { 294 // TODO: this is not very defensive, test if we can fail non int input 295 s := make(map[string]int) 296 for k, v := range attr.(map[string]interface{}) { 297 s[k], _ = strconv.Atoi(v.(string)) 298 } 299 o.Silenced = s 300 } 301 if attr, ok := d.GetOk("include_tags"); ok { 302 o.IncludeTags = attr.(bool) 303 } 304 305 m.Options = o 306 307 if err = client.UpdateMonitor(m); err != nil { 308 return fmt.Errorf("error updating monitor: %s", err.Error()) 309 } 310 311 return resourceDatadogMonitorRead(d, meta) 312 } 313 314 func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) error { 315 client := meta.(*datadog.Client) 316 317 i, err := strconv.Atoi(d.Id()) 318 if err != nil { 319 return err 320 } 321 322 if err = client.DeleteMonitor(i); err != nil { 323 return err 324 } 325 326 return nil 327 }