diff --git a/builtin/providers/circonus/check.go b/builtin/providers/circonus/check.go index 039dc7452..6200e94bf 100644 --- a/builtin/providers/circonus/check.go +++ b/builtin/providers/circonus/check.go @@ -29,6 +29,7 @@ const ( apiCheckTypeHTTP circonusCheckType = "http" apiCheckTypeJSON circonusCheckType = "json" apiCheckTypeMySQL circonusCheckType = "mysql" + apiCheckTypeStatsd circonusCheckType = "statsd" apiCheckTypePostgreSQL circonusCheckType = "postgres" apiCheckTypeTCP circonusCheckType = "tcp" ) diff --git a/builtin/providers/circonus/resource_circonus_check.go b/builtin/providers/circonus/resource_circonus_check.go index 26eebc0b7..c182a514b 100644 --- a/builtin/providers/circonus/resource_circonus_check.go +++ b/builtin/providers/circonus/resource_circonus_check.go @@ -44,6 +44,7 @@ const ( checkPeriodAttr = "period" checkPostgreSQLAttr = "postgresql" checkMetricAttr = "metric" + checkStatsdAttr = "statsd" checkTagsAttr = "tags" checkTargetAttr = "target" checkTCPAttr = "tcp" @@ -79,6 +80,7 @@ const ( apiCheckTypeJSONAttr apiCheckType = "json" apiCheckTypeMySQLAttr apiCheckType = "mysql" apiCheckTypePostgreSQLAttr apiCheckType = "postgres" + apiCheckTypeStatsdAttr apiCheckType = "statsd" apiCheckTypeTCPAttr apiCheckType = "tcp" ) @@ -91,16 +93,17 @@ var checkDescriptions = attrDescrs{ checkHTTPTrapAttr: "HTTP Trap check configuration", checkICMPPingAttr: "ICMP ping check configuration", checkJSONAttr: "JSON check configuration", + checkMetricAttr: "Configuration for a stream of metrics", checkMetricLimitAttr: `Setting a metric_limit will enable all (-1), disable (0), or allow up to the specified limit of metrics for this check ("N+", where N is a positive integer)`, checkMySQLAttr: "MySQL check configuration", checkNameAttr: "The name of the check bundle that will be displayed in the web interface", checkNotesAttr: "Notes about this check bundle", checkPeriodAttr: "The period between each time the check is made", checkPostgreSQLAttr: "PostgreSQL check configuration", - checkMetricAttr: "Configuration for a stream of metrics", + checkStatsdAttr: "statsd check configuration", + checkTCPAttr: "TCP check configuration", checkTagsAttr: "A list of tags assigned to the check", checkTargetAttr: "The target of the check (e.g. hostname, URL, IP, etc)", - checkTCPAttr: "TCP check configuration", checkTimeoutAttr: "The length of time in seconds (and fractions of a second) before the check will timeout if no response is returned to the collector", checkTypeAttr: "The check type", @@ -156,37 +159,6 @@ func resourceCheck() *schema.Resource { checkHTTPTrapAttr: schemaCheckHTTPTrap, checkJSONAttr: schemaCheckJSON, checkICMPPingAttr: schemaCheckICMPPing, - checkMetricLimitAttr: &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Computed: true, - ValidateFunc: validateFuncs( - validateIntMin(checkMetricLimitAttr, -1), - ), - }, - checkMySQLAttr: schemaCheckMySQL, - checkNameAttr: &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - checkNotesAttr: &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - StateFunc: suppressWhitespace, - }, - checkPeriodAttr: &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - StateFunc: normalizeTimeDurationStringToSeconds, - ValidateFunc: validateFuncs( - validateDurationMin(checkPeriodAttr, defaultCirconusCheckPeriodMin), - validateDurationMax(checkPeriodAttr, defaultCirconusCheckPeriodMax), - ), - }, - checkPostgreSQLAttr: schemaCheckPostgreSQL, checkMetricAttr: &schema.Schema{ Type: schema.TypeSet, Optional: true, @@ -219,7 +191,39 @@ func resourceCheck() *schema.Resource { }), }, }, - checkTagsAttr: tagMakeConfigSchema(checkTagsAttr), + checkMetricLimitAttr: &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validateFuncs( + validateIntMin(checkMetricLimitAttr, -1), + ), + }, + checkMySQLAttr: schemaCheckMySQL, + checkNameAttr: &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + checkNotesAttr: &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + StateFunc: suppressWhitespace, + }, + checkPeriodAttr: &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + StateFunc: normalizeTimeDurationStringToSeconds, + ValidateFunc: validateFuncs( + validateDurationMin(checkPeriodAttr, defaultCirconusCheckPeriodMin), + validateDurationMax(checkPeriodAttr, defaultCirconusCheckPeriodMax), + ), + }, + checkPostgreSQLAttr: schemaCheckPostgreSQL, + checkStatsdAttr: schemaCheckStatsd, + checkTagsAttr: tagMakeConfigSchema(checkTagsAttr), checkTargetAttr: &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -564,6 +568,7 @@ func checkConfigToAPI(c *circonusCheck, d *schema.ResourceData) error { checkJSONAttr: checkConfigToAPIJSON, checkMySQLAttr: checkConfigToAPIMySQL, checkPostgreSQLAttr: checkConfigToAPIPostgreSQL, + checkStatsdAttr: checkConfigToAPIStatsd, checkTCPAttr: checkConfigToAPITCP, } @@ -590,6 +595,7 @@ func parseCheckTypeConfig(c *circonusCheck, d *schema.ResourceData) error { apiCheckTypeJSONAttr: checkAPIToStateJSON, apiCheckTypeMySQLAttr: checkAPIToStateMySQL, apiCheckTypePostgreSQLAttr: checkAPIToStatePostgreSQL, + apiCheckTypeStatsdAttr: checkAPIToStateStatsd, apiCheckTypeTCPAttr: checkAPIToStateTCP, } diff --git a/builtin/providers/circonus/resource_circonus_check_caql.go b/builtin/providers/circonus/resource_circonus_check_caql.go index addf794ba..a3d876b63 100644 --- a/builtin/providers/circonus/resource_circonus_check_caql.go +++ b/builtin/providers/circonus/resource_circonus_check_caql.go @@ -75,8 +75,8 @@ func checkConfigToAPICAQL(c *circonusCheck, l interfaceList) error { c.Type = string(apiCheckTypeCAQL) c.Target = defaultCheckCAQLTarget - // Iterate over all `icmp_ping` attributes, even though we have a max of 1 in - // the schema. + // Iterate over all `caql` attributes, even though we have a max of 1 in the + // schema. for _, mapRaw := range l { caqlConfig := newInterfaceMap(mapRaw) diff --git a/builtin/providers/circonus/resource_circonus_check_mysql.go b/builtin/providers/circonus/resource_circonus_check_mysql.go index 4414e1c71..3fe2094ed 100644 --- a/builtin/providers/circonus/resource_circonus_check_mysql.go +++ b/builtin/providers/circonus/resource_circonus_check_mysql.go @@ -84,8 +84,8 @@ func hashCheckMySQL(v interface{}) int { func checkConfigToAPIMySQL(c *circonusCheck, l interfaceList) error { c.Type = string(apiCheckTypeMySQL) - // Iterate over all `postgres` attributes, even though we have a max of 1 in - // the schema. + // Iterate over all `mysql` attributes, even though we have a max of 1 in the + // schema. for _, mapRaw := range l { mysqlConfig := newInterfaceMap(mapRaw) diff --git a/builtin/providers/circonus/resource_circonus_check_statsd.go b/builtin/providers/circonus/resource_circonus_check_statsd.go new file mode 100644 index 000000000..0320afe95 --- /dev/null +++ b/builtin/providers/circonus/resource_circonus_check_statsd.go @@ -0,0 +1,69 @@ +package circonus + +import ( + "fmt" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + // circonus_check.statsd.* resource attribute names + checkStatsdSourceIPAttr = "source_ip" +) + +var checkStatsdDescriptions = attrDescrs{ + checkStatsdSourceIPAttr: "The source IP of the statsd metrics stream", +} + +var schemaCheckStatsd = &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + MinItems: 1, + Elem: &schema.Resource{ + Schema: convertToHelperSchema(checkStatsdDescriptions, map[schemaAttr]*schema.Schema{ + checkStatsdSourceIPAttr: &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validateRegexp(checkStatsdSourceIPAttr, `.+`), + }, + }), + }, +} + +// checkAPIToStateStatsd reads the Config data out of circonusCheck.CheckBundle +// into the statefile. +func checkAPIToStateStatsd(c *circonusCheck, d *schema.ResourceData) error { + statsdConfig := make(map[string]interface{}, len(c.Config)) + + // Unconditionally map the target to the source_ip config attribute + statsdConfig[string(checkStatsdSourceIPAttr)] = c.Target + + if err := d.Set(checkStatsdAttr, []interface{}{statsdConfig}); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkStatsdAttr), err) + } + + return nil +} + +func checkConfigToAPIStatsd(c *circonusCheck, l interfaceList) error { + c.Type = string(apiCheckTypeStatsd) + + // Iterate over all `statsd` attributes, even though we have a max of 1 in the + // schema. + for _, mapRaw := range l { + statsdConfig := newInterfaceMap(mapRaw) + + if v, found := statsdConfig[checkStatsdSourceIPAttr]; found { + switch { + case c.Target == "": + c.Target = v.(string) + case c.Target != v.(string): + return fmt.Errorf("Target (%q) must match %s (%q)", c.Target, checkStatsdSourceIPAttr, v.(string)) + } + } + } + + return nil +} diff --git a/builtin/providers/circonus/resource_circonus_check_statsd_test.go b/builtin/providers/circonus/resource_circonus_check_statsd_test.go new file mode 100644 index 000000000..f7963588b --- /dev/null +++ b/builtin/providers/circonus/resource_circonus_check_statsd_test.go @@ -0,0 +1,71 @@ +package circonus + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccCirconusCheckStatsd_basic(t *testing.T) { + checkName := fmt.Sprintf("statsd test check - %s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDestroyCirconusCheckBundle, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccCirconusCheckStatsdConfigFmt, checkName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "active", "true"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "collector.#", "1"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "collector.2084916526.id", "/broker/2110"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "statsd.#", "1"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "statsd.3733287963.source_ip", `127.0.0.2`), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "name", checkName), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "period", "60s"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "metric.#", "1"), + + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "tags.#", "4"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "tags.3728194417", "app:consul"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "tags.2087084518", "author:terraform"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "tags.1401442048", "lifecycle:unittest"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "tags.2812916752", "source:statsd"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "target", "127.0.0.2"), + resource.TestCheckResourceAttr("circonus_check.statsd_dump", "type", "statsd"), + ), + }, + }, + }) +} + +const testAccCirconusCheckStatsdConfigFmt = ` +variable "test_tags" { + type = "list" + default = [ "app:consul", "author:terraform", "lifecycle:unittest", "source:statsd" ] +} + +resource "circonus_check" "statsd_dump" { + active = true + name = "%s" + period = "60s" + + collector { + id = "/broker/2110" + } + + statsd { + source_ip = "127.0.0.2" + } + + metric { + name = "rando_metric" + tags = [ "${var.test_tags}" ] + type = "histogram" + } + + tags = [ "${var.test_tags}" ] +} +` diff --git a/vendor/github.com/circonus-labs/circonus-gometrics/api/check_bundle.go b/vendor/github.com/circonus-labs/circonus-gometrics/api/check_bundle.go index 8ab851e0c..c202853c2 100644 --- a/vendor/github.com/circonus-labs/circonus-gometrics/api/check_bundle.go +++ b/vendor/github.com/circonus-labs/circonus-gometrics/api/check_bundle.go @@ -38,7 +38,7 @@ type CheckBundle struct { Checks []string `json:"_checks,omitempty"` // [] len >= 0 CheckUUIDs []string `json:"_check_uuids,omitempty"` // [] len >= 0 CID string `json:"_cid,omitempty"` // string - Config CheckBundleConfig `json:"config,omitempty"` // NOTE contents of config are check type specific, map len >= 0 + Config CheckBundleConfig `json:"config"` // NOTE contents of config are check type specific, map len >= 0 Created uint `json:"_created,omitempty"` // uint DisplayName string `json:"display_name"` // string LastModifedBy string `json:"_last_modifed_by,omitempty"` // string diff --git a/vendor/vendor.json b/vendor/vendor.json index e047e38c7..f5b009299 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1178,16 +1178,16 @@ "revisionTime": "2017-01-10T09:44:45Z" }, { - "checksumSHA1": "PDusd0EuHz0oKiQKwKxFhbETxd8=", + "checksumSHA1": "6fUPaqXabil0m2nqKONt9lOmo4c=", "path": "github.com/circonus-labs/circonus-gometrics/api", - "revision": "dbab9a33438e3f8317407ef5d3a51c29340541db", - "revisionTime": "2017-02-21T20:27:28Z" + "revision": "55add91cfb689b0fd6e9fa67c58c7a948310a80e", + "revisionTime": "2017-03-17T00:26:31Z" }, { "checksumSHA1": "bQhz/fcyZPmuHSH2qwC4ZtATy5c=", "path": "github.com/circonus-labs/circonus-gometrics/api/config", - "revision": "dbab9a33438e3f8317407ef5d3a51c29340541db", - "revisionTime": "2017-02-21T20:27:28Z" + "revision": "55add91cfb689b0fd6e9fa67c58c7a948310a80e", + "revisionTime": "2017-03-17T00:26:31Z" }, { "checksumSHA1": "QhYMdplKQJAMptRaHZBB8CF6HdM=", diff --git a/website/source/docs/providers/circonus/r/check.html.markdown b/website/source/docs/providers/circonus/r/check.html.markdown index 6879e9f10..ef1b30fa3 100644 --- a/website/source/docs/providers/circonus/r/check.html.markdown +++ b/website/source/docs/providers/circonus/r/check.html.markdown @@ -101,6 +101,10 @@ resource "circonus_metric" "used" { * `json` - (Optional) A JSON check. See below for details on how to configure the `json` check. +* `metric` - (Required) A list of one or more `metric` configurations. All + metrics obtained from this check instance will be available as individual + metric streams. See below for a list of supported `metric` attrbutes. + * `metric_limit` - (Optional) Setting a metric limit will tell the Circonus backend to periodically look at the check to see if there are additional metrics the collector has seen that we should collect. It will not reactivate @@ -122,9 +126,8 @@ resource "circonus_metric" "used" { * `postgresql` - (Optional) A PostgreSQL check. See below for details on how to configure the `postgresql` check. -* `metric` - (Required) A list of one or more `metric` configurations. All - metrics obtained from this check instance will be available as individual - metric streams. See below for a list of supported `metric` attrbutes. +* `statsd` - (Optional) A statsd check. See below for details on how to + configure the `statsd` check. * `tags` - (Optional) A list of tags assigned to this check. @@ -399,6 +402,13 @@ The `postgresql` check requires the `target` top-level attribute to be set. Available metric names are dependent on the output of the `query` being run. +### `statsd` Check Type Attributes + +* `source_ip` - (Required) Any statsd messages from this IP address (IPv4 or + IPv6) will be associated with this check. + +Available metrics depend on the metrics sent to the `statsd` check. + ### `tcp` Check Type Attributes * `banner_regexp` - (Optional) This regular expression is matched against the