github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/circonus/resource_circonus_check_icmp_ping.go (about) 1 package circonus 2 3 import ( 4 "bytes" 5 "fmt" 6 "strconv" 7 "time" 8 9 "github.com/circonus-labs/circonus-gometrics/api/config" 10 "github.com/hashicorp/errwrap" 11 "github.com/hashicorp/terraform/helper/hashcode" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 const ( 16 // circonus_check.icmp_ping.* resource attribute names 17 checkICMPPingAvailabilityAttr = "availability" 18 checkICMPPingCountAttr = "count" 19 checkICMPPingIntervalAttr = "interval" 20 ) 21 22 var checkICMPPingDescriptions = attrDescrs{ 23 checkICMPPingAvailabilityAttr: `The percentage of ICMP available required for the check to be considered "good."`, 24 checkICMPPingCountAttr: "The number of ICMP requests to send during a single check.", 25 checkICMPPingIntervalAttr: "The number of milliseconds between ICMP requests.", 26 } 27 28 var schemaCheckICMPPing = &schema.Schema{ 29 Type: schema.TypeSet, 30 Optional: true, 31 MaxItems: 1, 32 MinItems: 1, 33 Set: hashCheckICMPPing, 34 Elem: &schema.Resource{ 35 Schema: convertToHelperSchema(checkICMPPingDescriptions, map[schemaAttr]*schema.Schema{ 36 checkICMPPingAvailabilityAttr: &schema.Schema{ 37 Type: schema.TypeFloat, 38 Optional: true, 39 Default: defaultCheckICMPPingAvailability, 40 ValidateFunc: validateFuncs( 41 validateFloatMin(checkICMPPingAvailabilityAttr, 0.0), 42 validateFloatMax(checkICMPPingAvailabilityAttr, 100.0), 43 ), 44 }, 45 checkICMPPingCountAttr: &schema.Schema{ 46 Type: schema.TypeInt, 47 Optional: true, 48 Default: defaultCheckICMPPingCount, 49 ValidateFunc: validateFuncs( 50 validateIntMin(checkICMPPingCountAttr, 0), 51 validateIntMax(checkICMPPingCountAttr, 20), 52 ), 53 }, 54 checkICMPPingIntervalAttr: &schema.Schema{ 55 Type: schema.TypeString, 56 Optional: true, 57 Default: defaultCheckICMPPingInterval, 58 ValidateFunc: validateFuncs( 59 validateDurationMin(checkICMPPingIntervalAttr, "100µs"), 60 validateDurationMax(checkICMPPingIntervalAttr, "5m"), 61 ), 62 }, 63 }), 64 }, 65 } 66 67 // checkAPIToStateICMPPing reads the Config data out of circonusCheck.CheckBundle 68 // into the statefile. 69 func checkAPIToStateICMPPing(c *circonusCheck, d *schema.ResourceData) error { 70 icmpPingConfig := make(map[string]interface{}, len(c.Config)) 71 72 availNeeded, err := strconv.ParseFloat(c.Config[config.AvailNeeded], 64) 73 if err != nil { 74 return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.AvailNeeded), err) 75 } 76 77 count, err := strconv.ParseInt(c.Config[config.Count], 10, 64) 78 if err != nil { 79 return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.Count), err) 80 } 81 82 interval, err := time.ParseDuration(fmt.Sprintf("%sms", c.Config[config.Interval])) 83 if err != nil { 84 return errwrap.Wrapf(fmt.Sprintf("unable to parse %s: {{err}}", config.Interval), err) 85 } 86 87 icmpPingConfig[string(checkICMPPingAvailabilityAttr)] = availNeeded 88 icmpPingConfig[string(checkICMPPingCountAttr)] = int(count) 89 icmpPingConfig[string(checkICMPPingIntervalAttr)] = interval.String() 90 91 if err := d.Set(checkICMPPingAttr, schema.NewSet(hashCheckICMPPing, []interface{}{icmpPingConfig})); err != nil { 92 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkICMPPingAttr), err) 93 } 94 95 return nil 96 } 97 98 // hashCheckICMPPing creates a stable hash of the normalized values 99 func hashCheckICMPPing(v interface{}) int { 100 m := v.(map[string]interface{}) 101 b := &bytes.Buffer{} 102 b.Grow(defaultHashBufSize) 103 104 writeFloat64 := func(attrName schemaAttr) { 105 if v, ok := m[string(attrName)]; ok { 106 fmt.Fprintf(b, "%f", v.(float64)) 107 } 108 } 109 110 writeInt := func(attrName schemaAttr) { 111 if v, ok := m[string(attrName)]; ok { 112 fmt.Fprintf(b, "%x", v.(int)) 113 } 114 } 115 116 writeDuration := func(attrName schemaAttr) { 117 if v, ok := m[string(attrName)]; ok && v.(string) != "" { 118 d, _ := time.ParseDuration(v.(string)) 119 fmt.Fprint(b, d.String()) 120 } 121 } 122 123 // Order writes to the buffer using lexically sorted list for easy visual 124 // reconciliation with other lists. 125 writeFloat64(checkICMPPingAvailabilityAttr) 126 writeInt(checkICMPPingCountAttr) 127 writeDuration(checkICMPPingIntervalAttr) 128 129 s := b.String() 130 return hashcode.String(s) 131 } 132 133 func checkConfigToAPIICMPPing(c *circonusCheck, l interfaceList) error { 134 c.Type = string(apiCheckTypeICMPPing) 135 136 // Iterate over all `icmp_ping` attributes, even though we have a max of 1 in 137 // the schema. 138 for _, mapRaw := range l { 139 icmpPingConfig := newInterfaceMap(mapRaw) 140 141 if v, found := icmpPingConfig[checkICMPPingAvailabilityAttr]; found { 142 f := v.(float64) 143 c.Config[config.AvailNeeded] = fmt.Sprintf("%d", int(f)) 144 } 145 146 if v, found := icmpPingConfig[checkICMPPingCountAttr]; found { 147 c.Config[config.Count] = fmt.Sprintf("%d", v.(int)) 148 } 149 150 if v, found := icmpPingConfig[checkICMPPingIntervalAttr]; found { 151 d, _ := time.ParseDuration(v.(string)) 152 c.Config[config.Interval] = fmt.Sprintf("%d", int64(d/time.Millisecond)) 153 } 154 } 155 156 return nil 157 }