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  }