terraform/builtin/providers/circonus/resource_circonus_check_icm...

158 lines
4.8 KiB
Go

package circonus
import (
"bytes"
"fmt"
"strconv"
"time"
"github.com/circonus-labs/circonus-gometrics/api/config"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
const (
// circonus_check.icmp_ping.* resource attribute names
checkICMPPingAvailabilityAttr = "availability"
checkICMPPingCountAttr = "count"
checkICMPPingIntervalAttr = "interval"
)
var checkICMPPingDescriptions = attrDescrs{
checkICMPPingAvailabilityAttr: `The percentage of ICMP available required for the check to be considered "good."`,
checkICMPPingCountAttr: "The number of ICMP requests to send during a single check.",
checkICMPPingIntervalAttr: "The number of milliseconds between ICMP requests.",
}
var schemaCheckICMPPing = &schema.Schema{
Type: schema.TypeSet,
Optional: true,
MaxItems: 1,
MinItems: 1,
Set: hashCheckICMPPing,
Elem: &schema.Resource{
Schema: convertToHelperSchema(checkICMPPingDescriptions, map[schemaAttr]*schema.Schema{
checkICMPPingAvailabilityAttr: &schema.Schema{
Type: schema.TypeFloat,
Optional: true,
Default: defaultCheckICMPPingAvailability,
ValidateFunc: validateFuncs(
validateFloatMin(checkICMPPingAvailabilityAttr, 0.0),
validateFloatMax(checkICMPPingAvailabilityAttr, 100.0),
),
},
checkICMPPingCountAttr: &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: defaultCheckICMPPingCount,
ValidateFunc: validateFuncs(
validateIntMin(checkICMPPingCountAttr, 0),
validateIntMax(checkICMPPingCountAttr, 20),
),
},
checkICMPPingIntervalAttr: &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: defaultCheckICMPPingInterval,
ValidateFunc: validateFuncs(
validateDurationMin(checkICMPPingIntervalAttr, "100µs"),
validateDurationMax(checkICMPPingIntervalAttr, "5m"),
),
},
}),
},
}
// checkAPIToStateICMPPing reads the Config data out of circonusCheck.CheckBundle
// into the statefile.
func checkAPIToStateICMPPing(c *circonusCheck, d *schema.ResourceData) error {
icmpPingConfig := make(map[string]interface{}, len(c.Config))
availNeeded, err := strconv.ParseFloat(c.Config[config.AvailNeeded], 64)
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.AvailNeeded), err)
}
count, err := strconv.ParseInt(c.Config[config.Count], 10, 64)
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.Count), err)
}
interval, err := time.ParseDuration(fmt.Sprintf("%sms", c.Config[config.Interval]))
if err != nil {
return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.Interval), err)
}
icmpPingConfig[string(checkICMPPingAvailabilityAttr)] = availNeeded
icmpPingConfig[string(checkICMPPingCountAttr)] = int(count)
icmpPingConfig[string(checkICMPPingIntervalAttr)] = interval.String()
if err := d.Set(checkICMPPingAttr, schema.NewSet(hashCheckICMPPing, []interface{}{icmpPingConfig})); err != nil {
return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkICMPPingAttr), err)
}
return nil
}
// hashCheckICMPPing creates a stable hash of the normalized values
func hashCheckICMPPing(v interface{}) int {
m := v.(map[string]interface{})
b := &bytes.Buffer{}
b.Grow(defaultHashBufSize)
writeFloat64 := func(attrName schemaAttr) {
if v, ok := m[string(attrName)]; ok {
fmt.Fprintf(b, "%f", v.(float64))
}
}
writeInt := func(attrName schemaAttr) {
if v, ok := m[string(attrName)]; ok {
fmt.Fprintf(b, "%x", v.(int))
}
}
writeDuration := func(attrName schemaAttr) {
if v, ok := m[string(attrName)]; ok && v.(string) != "" {
d, _ := time.ParseDuration(v.(string))
fmt.Fprint(b, d.String())
}
}
// Order writes to the buffer using lexically sorted list for easy visual
// reconciliation with other lists.
writeFloat64(checkICMPPingAvailabilityAttr)
writeInt(checkICMPPingCountAttr)
writeDuration(checkICMPPingIntervalAttr)
s := b.String()
return hashcode.String(s)
}
func checkConfigToAPIICMPPing(c *circonusCheck, l interfaceList) error {
c.Type = string(apiCheckTypeICMPPing)
// Iterate over all `icmp_ping` attributes, even though we have a max of 1 in
// the schema.
for _, mapRaw := range l {
icmpPingConfig := newInterfaceMap(mapRaw)
if v, found := icmpPingConfig[checkICMPPingAvailabilityAttr]; found {
f := v.(float64)
c.Config[config.AvailNeeded] = fmt.Sprintf("%d", int(f))
}
if v, found := icmpPingConfig[checkICMPPingCountAttr]; found {
c.Config[config.Count] = fmt.Sprintf("%d", v.(int))
}
if v, found := icmpPingConfig[checkICMPPingIntervalAttr]; found {
d, _ := time.ParseDuration(v.(string))
c.Config[config.Interval] = fmt.Sprintf("%d", int64(d/time.Millisecond))
}
}
return nil
}