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  }