github.com/jdextraze/terraform@v0.6.17-0.20160511153921-e33847c8a8af/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 // 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_no_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("include_tags"); ok { 157 o.IncludeTags = attr.(bool) 158 } 159 160 m := datadog.Monitor{ 161 Type: d.Get("type").(string), 162 Query: d.Get("query").(string), 163 Name: d.Get("name").(string), 164 Message: d.Get("message").(string), 165 Options: o, 166 } 167 168 return &m 169 } 170 171 func resourceDatadogMonitorExists(d *schema.ResourceData, meta interface{}) (b bool, e error) { 172 // Exists - This is called to verify a resource still exists. It is called prior to Read, 173 // and lowers the burden of Read to be able to assume the resource exists. 174 client := meta.(*datadog.Client) 175 176 i, err := strconv.Atoi(d.Id()) 177 if err != nil { 178 return false, err 179 } 180 181 if _, err = client.GetMonitor(i); err != nil { 182 if strings.Contains(err.Error(), "404 Not Found") { 183 return false, nil 184 } 185 return false, err 186 } 187 188 return true, nil 189 } 190 191 func resourceDatadogMonitorCreate(d *schema.ResourceData, meta interface{}) error { 192 193 client := meta.(*datadog.Client) 194 195 m := buildMonitorStruct(d) 196 m, err := client.CreateMonitor(m) 197 if err != nil { 198 return fmt.Errorf("error updating montor: %s", err.Error()) 199 } 200 201 d.SetId(strconv.Itoa(m.Id)) 202 203 return nil 204 } 205 206 func resourceDatadogMonitorRead(d *schema.ResourceData, meta interface{}) error { 207 client := meta.(*datadog.Client) 208 209 i, err := strconv.Atoi(d.Id()) 210 if err != nil { 211 return err 212 } 213 214 m, err := client.GetMonitor(i) 215 if err != nil { 216 return err 217 } 218 219 log.Printf("[DEBUG] monitor: %v", m) 220 d.Set("name", m.Name) 221 d.Set("message", m.Message) 222 d.Set("query", m.Query) 223 d.Set("type", m.Type) 224 d.Set("thresholds", m.Options.Thresholds) 225 d.Set("notify_no_data", m.Options.NotifyNoData) 226 d.Set("no_data_timeframe", m.Options.NoDataTimeframe) 227 d.Set("renotify_interval", m.Options.RenotifyInterval) 228 d.Set("notify_audit", m.Options.NotifyAudit) 229 d.Set("timeout_h", m.Options.TimeoutH) 230 d.Set("escalation_message", m.Options.EscalationMessage) 231 d.Set("silenced", m.Options.Silenced) 232 d.Set("include_tags", m.Options.IncludeTags) 233 234 return nil 235 } 236 237 func resourceDatadogMonitorUpdate(d *schema.ResourceData, meta interface{}) error { 238 client := meta.(*datadog.Client) 239 240 m := &datadog.Monitor{} 241 242 i, err := strconv.Atoi(d.Id()) 243 if err != nil { 244 return err 245 } 246 247 m.Id = i 248 if attr, ok := d.GetOk("name"); ok { 249 m.Name = attr.(string) 250 } 251 if attr, ok := d.GetOk("message"); ok { 252 m.Message = attr.(string) 253 } 254 if attr, ok := d.GetOk("query"); ok { 255 m.Query = attr.(string) 256 } 257 258 o := datadog.Options{} 259 if attr, ok := d.GetOk("thresholds"); ok { 260 thresholds := attr.(map[string]interface{}) 261 if thresholds["ok"] != nil { 262 o.Thresholds.Ok = json.Number(thresholds["ok"].(string)) 263 } 264 if thresholds["warning"] != nil { 265 o.Thresholds.Warning = json.Number(thresholds["warning"].(string)) 266 } 267 if thresholds["critical"] != nil { 268 o.Thresholds.Critical = json.Number(thresholds["critical"].(string)) 269 } 270 } 271 272 if attr, ok := d.GetOk("notify_no_data"); ok { 273 o.NotifyNoData = attr.(bool) 274 } 275 if attr, ok := d.GetOk("no_data_timeframe"); ok { 276 o.NoDataTimeframe = attr.(int) 277 } 278 if attr, ok := d.GetOk("renotify_interval"); ok { 279 o.RenotifyInterval = attr.(int) 280 } 281 if attr, ok := d.GetOk("notify_audit"); ok { 282 o.NotifyAudit = attr.(bool) 283 } 284 if attr, ok := d.GetOk("timeout_h"); ok { 285 o.TimeoutH = attr.(int) 286 } 287 if attr, ok := d.GetOk("escalation_message"); ok { 288 o.EscalationMessage = attr.(string) 289 } 290 if attr, ok := d.GetOk("silenced"); ok { 291 // TODO: this is not very defensive, test if we can fail non int input 292 s := make(map[string]int) 293 for k, v := range attr.(map[string]interface{}) { 294 s[k], _ = strconv.Atoi(v.(string)) 295 } 296 o.Silenced = s 297 } 298 if attr, ok := d.GetOk("include_tags"); ok { 299 o.IncludeTags = attr.(bool) 300 } 301 302 m.Options = o 303 304 if err = client.UpdateMonitor(m); err != nil { 305 return fmt.Errorf("error updating monitor: %s", err.Error()) 306 } 307 308 return resourceDatadogMonitorRead(d, meta) 309 } 310 311 func resourceDatadogMonitorDelete(d *schema.ResourceData, meta interface{}) error { 312 client := meta.(*datadog.Client) 313 314 i, err := strconv.Atoi(d.Id()) 315 if err != nil { 316 return err 317 } 318 319 if err = client.DeleteMonitor(i); err != nil { 320 return err 321 } 322 323 return nil 324 }