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