158 lines
4.8 KiB
Go
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
|
|
}
|