Circonus Provider (#12338)
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Add support for the MySQL to the `circonus_check` resource.
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Rename all identifiers that began with a `_` and replace with a corresponding lowercase glyph.
* Remove stale comment in types.
* Move the calls to `ResourceData`'s `SetId()` calls to be first in the
list so that no resources are lost in the event of a `panic()`.
* Remove `stateSet` from the `circonus_trigger` resource.
* Remove `stateSet` from the `circonus_stream_group` resource.
* Remove `schemaSet` from the `circonus_graph` resource.
* Remove `stateSet` from the `circonus_contact` resource.
* Remove `stateSet` from the `circonus_metric` resource.
* Remove `stateSet` from the `circonus_account` data source.
* Remove `stateSet` from the `circonus_collector` data source.
* Remove stray `stateSet` call from the `circonus_contact` resource.
This is an odd artifact to find... I'm completely unsure as to why it
was there to begin with but am mostly certain it's a bug and needs to be
removed.
* Remove `stateSet` from the `circonus_check` resource.
* Remove the `stateSet` helper function.
All call sites have been converted to return errors vs `panic()`'ing at
runtime.
* Remove a pile of unused functions and type definitions.
* Remove the last of the `attrReader` interface.
* Remove an unused `Sprintf` call.
* Update `circonus-gometrics` and remove unused files.
* Document what `convertToHelperSchema()` does.
Rename `castSchemaToTF` to `convertToHelperSchema`.
Change the function parameter ordering so the `map` of attribute
descriptions: this is much easier to maintain when the description map
is first when creating schema inline.
* Move descriptions into their respective source files.
* Remove all instances of `panic()`.
In the case of software bugs, log an error. Never `panic()` and always
return a value.
* Rename `stream_group` to `metric_cluster`.
* Rename triggers to rule sets
* Rename `stream` to `metric`.
* Chase the `stream` -> `metric` change into the docs.
* Remove some unused test functions.
* Add the now required `color` attribute for graphing a `metric_cluster`.
* Add a missing description to silence a warning.
* Add `id` as a selector for the account data source.
* Futureproof testing: Randomize all asset names to prevent any possible resource conflicts.
This isn't a necessary change for our current build and regression
testing, but *just in case* we have a radical change to our testing
framework in the future, make all resource names fully random.
* Rename various values to match the Circonus docs.
* s/alarm/alert/g
* Ensure ruleset criteria can not be empty.
2017-03-10 21:19:17 +01:00
|
|
|
package circonus
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/circonus-labs/circonus-gometrics/api"
|
|
|
|
"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_rule_set.* resource attribute names
|
|
|
|
ruleSetCheckAttr = "check"
|
|
|
|
ruleSetIfAttr = "if"
|
|
|
|
ruleSetLinkAttr = "link"
|
|
|
|
ruleSetMetricTypeAttr = "metric_type"
|
|
|
|
ruleSetNotesAttr = "notes"
|
|
|
|
ruleSetParentAttr = "parent"
|
|
|
|
ruleSetMetricNameAttr = "metric_name"
|
|
|
|
ruleSetTagsAttr = "tags"
|
|
|
|
|
|
|
|
// circonus_rule_set.if.* resource attribute names
|
|
|
|
ruleSetThenAttr = "then"
|
|
|
|
ruleSetValueAttr = "value"
|
|
|
|
|
|
|
|
// circonus_rule_set.if.then.* resource attribute names
|
|
|
|
ruleSetAfterAttr = "after"
|
|
|
|
ruleSetNotifyAttr = "notify"
|
|
|
|
ruleSetSeverityAttr = "severity"
|
|
|
|
|
|
|
|
// circonus_rule_set.if.value.* resource attribute names
|
|
|
|
ruleSetAbsentAttr = "absent" // apiRuleSetAbsent
|
|
|
|
ruleSetChangedAttr = "changed" // apiRuleSetChanged
|
|
|
|
ruleSetContainsAttr = "contains" // apiRuleSetContains
|
|
|
|
ruleSetMatchAttr = "match" // apiRuleSetMatch
|
|
|
|
ruleSetMaxValueAttr = "max_value" // apiRuleSetMaxValue
|
|
|
|
ruleSetMinValueAttr = "min_value" // apiRuleSetMinValue
|
|
|
|
ruleSetNotContainAttr = "not_contain" // apiRuleSetNotContains
|
|
|
|
ruleSetNotMatchAttr = "not_match" // apiRuleSetNotMatch
|
|
|
|
ruleSetOverAttr = "over"
|
|
|
|
|
|
|
|
// circonus_rule_set.if.value.over.* resource attribute names
|
|
|
|
ruleSetLastAttr = "last"
|
|
|
|
ruleSetUsingAttr = "using"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// Different criteria that an api.RuleSetRule can return
|
|
|
|
apiRuleSetAbsent = "on absence" // ruleSetAbsentAttr
|
|
|
|
apiRuleSetChanged = "on change" // ruleSetChangedAttr
|
|
|
|
apiRuleSetContains = "contains" // ruleSetContainsAttr
|
|
|
|
apiRuleSetMatch = "match" // ruleSetMatchAttr
|
|
|
|
apiRuleSetMaxValue = "max value" // ruleSetMaxValueAttr
|
|
|
|
apiRuleSetMinValue = "min value" // ruleSetMinValueAttr
|
|
|
|
apiRuleSetNotContains = "does not contain" // ruleSetNotContainAttr
|
|
|
|
apiRuleSetNotMatch = "does not match" // ruleSetNotMatchAttr
|
|
|
|
)
|
|
|
|
|
|
|
|
var ruleSetDescriptions = attrDescrs{
|
|
|
|
// circonus_rule_set.* resource attribute names
|
|
|
|
ruleSetCheckAttr: "The CID of the check that contains the metric for this rule set",
|
|
|
|
ruleSetIfAttr: "A rule to execute for this rule set",
|
|
|
|
ruleSetLinkAttr: "URL to show users when this rule set is active (e.g. wiki)",
|
|
|
|
ruleSetMetricTypeAttr: "The type of data flowing through the specified metric stream",
|
|
|
|
ruleSetNotesAttr: "Notes describing this rule set",
|
|
|
|
ruleSetParentAttr: "Parent CID that must be healthy for this rule set to be active",
|
|
|
|
ruleSetMetricNameAttr: "The name of the metric stream within a check to register the rule set with",
|
|
|
|
ruleSetTagsAttr: "Tags associated with this rule set",
|
|
|
|
}
|
|
|
|
|
|
|
|
var ruleSetIfDescriptions = attrDescrs{
|
|
|
|
// circonus_rule_set.if.* resource attribute names
|
|
|
|
ruleSetThenAttr: "Description of the action(s) to take when this rule set is active",
|
|
|
|
ruleSetValueAttr: "Predicate that the rule set uses to evaluate a stream of metrics",
|
|
|
|
}
|
|
|
|
|
|
|
|
var ruleSetIfValueDescriptions = attrDescrs{
|
|
|
|
// circonus_rule_set.if.value.* resource attribute names
|
|
|
|
ruleSetAbsentAttr: "Fire the rule set if there has been no data for the given metric stream over the last duration",
|
|
|
|
ruleSetChangedAttr: "Boolean indicating the value has changed",
|
|
|
|
ruleSetContainsAttr: "Fire the rule set if the text metric contain the following string",
|
|
|
|
ruleSetMatchAttr: "Fire the rule set if the text metric exactly match the following string",
|
|
|
|
ruleSetNotMatchAttr: "Fire the rule set if the text metric not match the following string",
|
|
|
|
ruleSetMinValueAttr: "Fire the rule set if the numeric value less than the specified value",
|
|
|
|
ruleSetNotContainAttr: "Fire the rule set if the text metric does not contain the following string",
|
|
|
|
ruleSetMaxValueAttr: "Fire the rule set if the numeric value is more than the specified value",
|
|
|
|
ruleSetOverAttr: "Use a derived value using a window",
|
|
|
|
ruleSetThenAttr: "Action to take when the rule set is active",
|
|
|
|
}
|
|
|
|
|
|
|
|
var ruleSetIfValueOverDescriptions = attrDescrs{
|
|
|
|
// circonus_rule_set.if.value.over.* resource attribute names
|
|
|
|
ruleSetLastAttr: "Duration over which data from the last interval is examined",
|
|
|
|
ruleSetUsingAttr: "Define the window funciton to use over the last duration",
|
|
|
|
}
|
|
|
|
|
|
|
|
var ruleSetIfThenDescriptions = attrDescrs{
|
|
|
|
// circonus_rule_set.if.then.* resource attribute names
|
|
|
|
ruleSetAfterAttr: "The length of time we should wait before contacting the contact groups after this ruleset has faulted.",
|
|
|
|
ruleSetNotifyAttr: "List of contact groups to notify at the following appropriate severity if this rule set is active.",
|
|
|
|
ruleSetSeverityAttr: "Send a notification at this severity level.",
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceRuleSet() *schema.Resource {
|
|
|
|
makeConflictsWith := func(in ...schemaAttr) []string {
|
|
|
|
out := make([]string, 0, len(in))
|
|
|
|
for _, attr := range in {
|
|
|
|
out = append(out, string(ruleSetIfAttr)+"."+string(ruleSetValueAttr)+"."+string(attr))
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: ruleSetCreate,
|
|
|
|
Read: ruleSetRead,
|
|
|
|
Update: ruleSetUpdate,
|
|
|
|
Delete: ruleSetDelete,
|
|
|
|
Exists: ruleSetExists,
|
|
|
|
Importer: &schema.ResourceImporter{
|
|
|
|
State: schema.ImportStatePassthrough,
|
|
|
|
},
|
|
|
|
|
|
|
|
Schema: convertToHelperSchema(ruleSetDescriptions, map[schemaAttr]*schema.Schema{
|
|
|
|
ruleSetCheckAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetCheckAttr, config.CheckCIDRegex),
|
|
|
|
},
|
|
|
|
ruleSetIfAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Required: true,
|
|
|
|
MinItems: 1,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: convertToHelperSchema(ruleSetIfDescriptions, map[schemaAttr]*schema.Schema{
|
|
|
|
ruleSetThenAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
MaxItems: 1,
|
|
|
|
Optional: true,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: convertToHelperSchema(ruleSetIfThenDescriptions, map[schemaAttr]*schema.Schema{
|
|
|
|
ruleSetAfterAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
DiffSuppressFunc: suppressEquivalentTimeDurations,
|
|
|
|
StateFunc: normalizeTimeDurationStringToSeconds,
|
|
|
|
ValidateFunc: validateFuncs(
|
|
|
|
validateDurationMin(ruleSetAfterAttr, "0s"),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
ruleSetNotifyAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Optional: true,
|
|
|
|
MinItems: 1,
|
|
|
|
Elem: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
ValidateFunc: validateContactGroupCID(ruleSetNotifyAttr),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ruleSetSeverityAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: defaultAlertSeverity,
|
|
|
|
ValidateFunc: validateFuncs(
|
|
|
|
validateIntMax(ruleSetSeverityAttr, maxSeverity),
|
|
|
|
validateIntMin(ruleSetSeverityAttr, minSeverity),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ruleSetValueAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
MaxItems: 1,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: convertToHelperSchema(ruleSetIfValueDescriptions, map[schemaAttr]*schema.Schema{
|
|
|
|
ruleSetAbsentAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to text or numeric metrics
|
|
|
|
Optional: true,
|
|
|
|
DiffSuppressFunc: suppressEquivalentTimeDurations,
|
|
|
|
StateFunc: normalizeTimeDurationStringToSeconds,
|
|
|
|
ValidateFunc: validateFuncs(
|
|
|
|
validateDurationMin(ruleSetAbsentAttr, ruleSetAbsentMin),
|
|
|
|
),
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetChangedAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeBool, // Applies to text or numeric metrics
|
|
|
|
Optional: true,
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetContainsAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to text metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetContainsAttr, `.+`),
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetMatchAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to text metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetMatchAttr, `.+`),
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetNotMatchAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to text metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetNotMatchAttr, `.+`),
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetMinValueAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to numeric metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetMinValueAttr, `.+`), // TODO(sean): improve this regexp to match int and float
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetNotContainAttr, ruleSetMaxValueAttr),
|
|
|
|
},
|
|
|
|
ruleSetNotContainAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to text metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetNotContainAttr, `.+`),
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetMaxValueAttr, ruleSetOverAttr),
|
|
|
|
},
|
|
|
|
ruleSetMaxValueAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString, // Applies to numeric metrics only
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetMaxValueAttr, `.+`), // TODO(sean): improve this regexp to match int and float
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetMinValueAttr, ruleSetNotContainAttr),
|
|
|
|
},
|
|
|
|
ruleSetOverAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
MaxItems: 1,
|
|
|
|
// ruleSetOverAttr is only compatible with checks of
|
|
|
|
// numeric type. NOTE: It may be premature to conflict with
|
|
|
|
// ruleSetChangedAttr.
|
|
|
|
ConflictsWith: makeConflictsWith(ruleSetAbsentAttr, ruleSetChangedAttr, ruleSetContainsAttr, ruleSetMatchAttr, ruleSetNotMatchAttr, ruleSetNotContainAttr),
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: convertToHelperSchema(ruleSetIfValueOverDescriptions, map[schemaAttr]*schema.Schema{
|
|
|
|
ruleSetLastAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Default: defaultRuleSetLast,
|
|
|
|
DiffSuppressFunc: suppressEquivalentTimeDurations,
|
|
|
|
StateFunc: normalizeTimeDurationStringToSeconds,
|
|
|
|
ValidateFunc: validateFuncs(
|
|
|
|
validateDurationMin(ruleSetLastAttr, "0s"),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
ruleSetUsingAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Default: defaultRuleSetWindowFunc,
|
|
|
|
ValidateFunc: validateStringIn(ruleSetUsingAttr, validRuleSetWindowFuncs),
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ruleSetLinkAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
2017-03-12 03:59:18 +01:00
|
|
|
ValidateFunc: validateHTTPURL(ruleSetLinkAttr, urlIsAbs|urlOptional),
|
Circonus Provider (#12338)
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Add support for the MySQL to the `circonus_check` resource.
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Rename all identifiers that began with a `_` and replace with a corresponding lowercase glyph.
* Remove stale comment in types.
* Move the calls to `ResourceData`'s `SetId()` calls to be first in the
list so that no resources are lost in the event of a `panic()`.
* Remove `stateSet` from the `circonus_trigger` resource.
* Remove `stateSet` from the `circonus_stream_group` resource.
* Remove `schemaSet` from the `circonus_graph` resource.
* Remove `stateSet` from the `circonus_contact` resource.
* Remove `stateSet` from the `circonus_metric` resource.
* Remove `stateSet` from the `circonus_account` data source.
* Remove `stateSet` from the `circonus_collector` data source.
* Remove stray `stateSet` call from the `circonus_contact` resource.
This is an odd artifact to find... I'm completely unsure as to why it
was there to begin with but am mostly certain it's a bug and needs to be
removed.
* Remove `stateSet` from the `circonus_check` resource.
* Remove the `stateSet` helper function.
All call sites have been converted to return errors vs `panic()`'ing at
runtime.
* Remove a pile of unused functions and type definitions.
* Remove the last of the `attrReader` interface.
* Remove an unused `Sprintf` call.
* Update `circonus-gometrics` and remove unused files.
* Document what `convertToHelperSchema()` does.
Rename `castSchemaToTF` to `convertToHelperSchema`.
Change the function parameter ordering so the `map` of attribute
descriptions: this is much easier to maintain when the description map
is first when creating schema inline.
* Move descriptions into their respective source files.
* Remove all instances of `panic()`.
In the case of software bugs, log an error. Never `panic()` and always
return a value.
* Rename `stream_group` to `metric_cluster`.
* Rename triggers to rule sets
* Rename `stream` to `metric`.
* Chase the `stream` -> `metric` change into the docs.
* Remove some unused test functions.
* Add the now required `color` attribute for graphing a `metric_cluster`.
* Add a missing description to silence a warning.
* Add `id` as a selector for the account data source.
* Futureproof testing: Randomize all asset names to prevent any possible resource conflicts.
This isn't a necessary change for our current build and regression
testing, but *just in case* we have a radical change to our testing
framework in the future, make all resource names fully random.
* Rename various values to match the Circonus docs.
* s/alarm/alert/g
* Ensure ruleset criteria can not be empty.
2017-03-10 21:19:17 +01:00
|
|
|
},
|
|
|
|
ruleSetMetricTypeAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Default: defaultRuleSetMetricType,
|
|
|
|
ValidateFunc: validateStringIn(ruleSetMetricTypeAttr, validRuleSetMetricTypes),
|
|
|
|
},
|
|
|
|
ruleSetNotesAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
StateFunc: suppressWhitespace,
|
|
|
|
},
|
|
|
|
ruleSetParentAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
StateFunc: suppressWhitespace,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetParentAttr, `^[\d]+_[\d\w]+$`),
|
|
|
|
},
|
|
|
|
ruleSetMetricNameAttr: &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ValidateFunc: validateRegexp(ruleSetMetricNameAttr, `^[\S]+$`),
|
|
|
|
},
|
|
|
|
ruleSetTagsAttr: tagMakeConfigSchema(ruleSetTagsAttr),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
ctxt := meta.(*providerContext)
|
|
|
|
rs := newRuleSet()
|
|
|
|
|
|
|
|
if err := rs.ParseConfig(d); err != nil {
|
|
|
|
return errwrap.Wrapf("error parsing rule set schema during create: {{err}}", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := rs.Create(ctxt); err != nil {
|
|
|
|
return errwrap.Wrapf("error creating rule set: {{err}}", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(rs.CID)
|
|
|
|
|
|
|
|
return ruleSetRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetExists(d *schema.ResourceData, meta interface{}) (bool, error) {
|
|
|
|
ctxt := meta.(*providerContext)
|
|
|
|
|
|
|
|
cid := d.Id()
|
|
|
|
rs, err := ctxt.client.FetchRuleSet(api.CIDType(&cid))
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if rs.CID == "" {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ruleSetRead pulls data out of the RuleSet object and stores it into the
|
|
|
|
// appropriate place in the statefile.
|
|
|
|
func ruleSetRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
ctxt := meta.(*providerContext)
|
|
|
|
|
|
|
|
cid := d.Id()
|
|
|
|
rs, err := loadRuleSet(ctxt, api.CIDType(&cid))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(rs.CID)
|
|
|
|
|
|
|
|
ifRules := make([]interface{}, 0, defaultRuleSetRuleLen)
|
|
|
|
for _, rule := range rs.Rules {
|
|
|
|
ifAttrs := make(map[string]interface{}, 2)
|
|
|
|
valueAttrs := make(map[string]interface{}, 2)
|
|
|
|
valueOverAttrs := make(map[string]interface{}, 2)
|
|
|
|
thenAttrs := make(map[string]interface{}, 3)
|
|
|
|
|
|
|
|
switch rule.Criteria {
|
|
|
|
case apiRuleSetAbsent:
|
|
|
|
d, _ := time.ParseDuration(fmt.Sprintf("%fs", rule.Value.(float64)))
|
|
|
|
valueAttrs[string(ruleSetAbsentAttr)] = fmt.Sprintf("%ds", int(d.Seconds()))
|
|
|
|
case apiRuleSetChanged:
|
|
|
|
valueAttrs[string(ruleSetChangedAttr)] = true
|
|
|
|
case apiRuleSetContains:
|
|
|
|
valueAttrs[string(ruleSetContainsAttr)] = rule.Value
|
|
|
|
case apiRuleSetMatch:
|
|
|
|
valueAttrs[string(ruleSetMatchAttr)] = rule.Value
|
|
|
|
case apiRuleSetMaxValue:
|
|
|
|
valueAttrs[string(ruleSetMaxValueAttr)] = rule.Value
|
|
|
|
case apiRuleSetMinValue:
|
|
|
|
valueAttrs[string(ruleSetMinValueAttr)] = rule.Value
|
|
|
|
case apiRuleSetNotContains:
|
|
|
|
valueAttrs[string(ruleSetNotContainAttr)] = rule.Value
|
2017-03-12 03:59:18 +01:00
|
|
|
case apiRuleSetNotMatch:
|
|
|
|
valueAttrs[string(ruleSetNotMatchAttr)] = rule.Value
|
Circonus Provider (#12338)
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Add support for the MySQL to the `circonus_check` resource.
* Begin stubbing out the Circonus provider.
* Remove all references to `reverse:secret_key`.
This value is dynamically set by the service and unused by Terraform.
* Update the `circonus_check` resource.
Still a WIP.
* Add docs for the `circonus_check` resource.
Commit miss, this should have been included in the last commit.
* "Fix" serializing check tags
I still need to figure out how I can make them order agnostic w/o using
a TypeSet. I'm worried that's what I'm going to have to do.
* Spike a quick circonus_broker data source.
* Convert tags to a Set so the order does not matter.
* Add a `circonus_account` data source.
* Correctly spell account.
Pointed out by: @postwait
* Add the `circonus_contact_group` resource.
* Push descriptions into their own file in order to reduce the busyness of the schema when reviewing code.
* Rename `circonus_broker` and `broker` to `circonus_collector` and `collector`, respectively.
Change made with concent by Circonus to reduce confusion (@postwait, @maier, and several others).
* Use upstream contsants where available.
* Import the latest circonus-gometrics.
* Move to using a Set of collectors vs a list attached to a single attribute.
* Rename "cid" to "id" in the circonus_account data source and elsewhere
where possible.
* Inject a tag automatically. Update gometrics.
* Checkpoint `circonus_metric` resource.
* Enable provider-level auto-tagging. This is disabled by default.
* Rearrange metric. This is an experimental "style" of a provider. We'll see.
That moment. When you think you've gone off the rails on a mad scientist
experiment but like the outcome and think you may be onto something but
haven't proven it to yourself or anyone else yet? That. That exact
feeling of semi-confidence while being alone in the wilderness. Please
let this not be the Terraform provider equivalent of DJB's C style of
coding.
We'll know in another resource or two if this was a horrible mistake or
not.
* Begin moving `resource_circonus_check` over to the new world order/structure:
Much of this is WIP and incomplete, but here is the new supported
structure:
```
variable "used_metric_name" {
default = "_usage`0`_used"
}
resource "circonus_check" "usage" {
# collectors = ["${var.collectors}"]
collector {
id = "${var.collectors[0]}"
}
name = "${var.check_name}"
notes = "${var.notes}"
json {
url = "https://${var.target}/account/current"
http_headers = {
"Accept" = "application/json"
"X-Circonus-App-Name" = "TerraformCheck"
"X-Circonus-Auth-Token" = "${var.api_token}"
}
}
stream {
name = "${circonus_metric.used.name}"
tags = "${circonus_metric.used.tags}"
type = "${circonus_metric.used.type}"
}
tags = {
source = "circonus"
}
}
resource "circonus_metric" "used" {
name = "${var.used_metric_name}"
tags = {
source = "circonus"
}
type = "numeric"
}
```
* Document the `circonus_metric` resource.
* Updated `circonus_check` docs.
* If a port was present, automatically set it in the Config.
* Alpha sort the check parameters now that they've been renamed.
* Fix a handful of panics as a result of the schema changing.
* Move back to a `TypeSet` for tags. After a stint with `TypeMap`, move
back to `TypeSet`.
A set of strings seems to match the API the best. The `map` type was
convenient because it reduced the amount of boilerplate, but you loose
out on other things. For instance, tags come in the form of
`category:value`, so naturally it seems like you could use a map, but
you can't without severe loss of functionality because assigning two
values to the same category is common. And you can't normalize map
input or suppress the output correctly (this was eventually what broke
the camel's back). I tried an experiment of normalizing the input to be
`category:value` as the key in the map and a value of `""`, but... seee
diff suppress. In this case, simple is good.
While here bring some cleanups to _Metric since that was my initial
testing target.
* Rename `providerConfig` to `_ProviderConfig`
* Checkpoint the `json` check type.
* Fix a few residual issues re: missing descriptions.
* Rename `validateRegexp` to `_ValidateRegexp`
* Use tags as real sets, not just a slice of strings.
* Move the DiffSuppressFunc for tags down to the Elem.
* Fix up unit tests to chase the updated, default hasher function being used.
* Remove `Computed` attribute from `TypeSet` objects.
This fixes a pile of issues re: update that I was having.
* Rename functions.
`GetStringOk` -> `GetStringOK`
`GetSetAsListOk` -> `GetSetAsListOK`
`GetIntOk` -> `GetIntOK`
* Various small cleanups and comments rolled into a single commit.
* Add a `postgresql` check type for the `circonus_check` resource.
* Rename various validator functions to be _CapitalCase vs capitalCase.
* Err... finish the validator renames.
* Add `GetFloat64()` support.
* Add `icmp_ping` check type support.
* Catch up to the _API*Attr renames.
Deliberately left out of the previous commit in order to create a clean
example of what is required to add a new check type to the
`circonus_check` resource.
* Clarify when the `target` attribute is required for the `postgresql`
check type.
* Correctly pull the metric ID attribute from the right location.
* Add a circonus_stream_group resource (a.k.a. a Circonus "metric cluster")
* Add support for the [`caql`](https://login.circonus.com/user/docs/caql_reference) check type.
* Add support for the `http` check type.
* `s/SSL/TLS/g`
* Add support for `tcp` check types.
* Enumerate the available metrics that are supported for each check type.
* Add [`cloudwatch`](https://login.circonus.com/user/docs/Data/CheckTypes/CloudWatch) check type support.
* Add a `circonus_trigger` resource (a.k.a Circonus Ruleset).
* Rename a handful of functions to make it clear in the function name the
direction of flow for information moving through the provider.
TL;DR: Replace `parse` and `read` with "foo to bar"-like names.
* Fix the attribute name used in a validator. Absent != After.
* Set the minimum `absent` predicate to 70s per testing.
* Fix the regression tests for circonus_trigger now that absent has a 70s min
* Fix up the `tcp` check to require a `host` attribute.
Fix tests. It's clear I didn't run these before committing/pushing the
`tcp` check last time.
* Fix `circonus_check` for `cloudwatch` checks.
* Rename `parsePerCheckTypeConfig()` to `_CheckConfigToAPI` to be
consistent with other function names.
grep(1)ability of code++
* Slack buttons as an integer are string encoded.
* Fix updates for `circonus_contact`.
* Fix the out parameters for contact groups.
* Move to using `_CastSchemaToTF()` where appropriate.
* Fix circonus_contact_group. Updates work as expected now.
* Use `_StateSet()` in place of `d.Set()` everywhere.
* Make a quick pass over the collector datasource to modernize its style
* Quick pass for items identified by `golint`.
* Fix up collectors
* Fix the `json` check type.
Reconcile possible sources of drift. Update now works as expected.
* Normalize trigger durations to seconds.
* Improve the robustness of the state handling for the `circonus_contact_group` resource.
* I'm torn on this, but sort the contact groups in the notify list.
This does mean that if the first contact group in the list has a higher
lexical sort order the plan won't converge until the offending resource
is tainted and recreated. But there's also some sorting happening
elsewhere, so.... sort and taint for now and this will need to be
revisited in the future.
* Add support for the `httptrap` check type.
* Remove empty units from the state file.
* Metric clusters can return a 404. Detect this accordingly in its
respective Exists handler.
* Add a `circonus_graph` resource.
* Fix a handful of bugs in the graph provider.
* Re-enable the necessary `ConflictsWith` definitions and normalize attribute names.
* Objects that have been deleted via the UI return a 404. Handle in Exists().
* Teach `circonus_graph`'s Stack set to accept nil values.
* Set `ForceNew: true` for a graph's name.
* Chase various API fixes required to make `circonus_graph` work as expected.
* Fix up the handling of sub-1 zoom resolutions for graphs.
* Add the `check_by_collector` out parameter to the `circonus_check` resource.
* Improve validation of line vs area graphs. Fix graph_style.
* Fix up the `logarithmic` graph axis option.
* Resolve various trivial `go vet` issues.
* Add a stream_group out parameter.
* Remove incorrectly applied `Optional` attributes to the `circonus_account` resource.
* Remove various `Optional` attributes from the `circonus_collector` data source.
* Centralize the common need to suppress leading and trailing whitespace into `suppressWhitespace`.
* Sync up with upstream vendor fixes for circonus_graph.
* Update the checksum value for the http check.
* Chase `circonus_graph`'s underlying `line_style` API object change from `string` to `*string`.
* Clean up tests to use a generic terraform regression testing account.
* Rename all identifiers that began with a `_` and replace with a corresponding lowercase glyph.
* Remove stale comment in types.
* Move the calls to `ResourceData`'s `SetId()` calls to be first in the
list so that no resources are lost in the event of a `panic()`.
* Remove `stateSet` from the `circonus_trigger` resource.
* Remove `stateSet` from the `circonus_stream_group` resource.
* Remove `schemaSet` from the `circonus_graph` resource.
* Remove `stateSet` from the `circonus_contact` resource.
* Remove `stateSet` from the `circonus_metric` resource.
* Remove `stateSet` from the `circonus_account` data source.
* Remove `stateSet` from the `circonus_collector` data source.
* Remove stray `stateSet` call from the `circonus_contact` resource.
This is an odd artifact to find... I'm completely unsure as to why it
was there to begin with but am mostly certain it's a bug and needs to be
removed.
* Remove `stateSet` from the `circonus_check` resource.
* Remove the `stateSet` helper function.
All call sites have been converted to return errors vs `panic()`'ing at
runtime.
* Remove a pile of unused functions and type definitions.
* Remove the last of the `attrReader` interface.
* Remove an unused `Sprintf` call.
* Update `circonus-gometrics` and remove unused files.
* Document what `convertToHelperSchema()` does.
Rename `castSchemaToTF` to `convertToHelperSchema`.
Change the function parameter ordering so the `map` of attribute
descriptions: this is much easier to maintain when the description map
is first when creating schema inline.
* Move descriptions into their respective source files.
* Remove all instances of `panic()`.
In the case of software bugs, log an error. Never `panic()` and always
return a value.
* Rename `stream_group` to `metric_cluster`.
* Rename triggers to rule sets
* Rename `stream` to `metric`.
* Chase the `stream` -> `metric` change into the docs.
* Remove some unused test functions.
* Add the now required `color` attribute for graphing a `metric_cluster`.
* Add a missing description to silence a warning.
* Add `id` as a selector for the account data source.
* Futureproof testing: Randomize all asset names to prevent any possible resource conflicts.
This isn't a necessary change for our current build and regression
testing, but *just in case* we have a radical change to our testing
framework in the future, make all resource names fully random.
* Rename various values to match the Circonus docs.
* s/alarm/alert/g
* Ensure ruleset criteria can not be empty.
2017-03-10 21:19:17 +01:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("PROVIDER BUG: Unsupported criteria %q", rule.Criteria)
|
|
|
|
}
|
|
|
|
|
|
|
|
if rule.Wait > 0 {
|
|
|
|
thenAttrs[string(ruleSetAfterAttr)] = fmt.Sprintf("%ds", 60*rule.Wait)
|
|
|
|
}
|
|
|
|
thenAttrs[string(ruleSetSeverityAttr)] = int(rule.Severity)
|
|
|
|
|
|
|
|
if rule.WindowingFunction != nil {
|
|
|
|
valueOverAttrs[string(ruleSetUsingAttr)] = *rule.WindowingFunction
|
|
|
|
|
|
|
|
// NOTE: Only save the window duration if a function was specified
|
|
|
|
valueOverAttrs[string(ruleSetLastAttr)] = fmt.Sprintf("%ds", rule.WindowingDuration)
|
|
|
|
}
|
|
|
|
valueOverSet := schema.NewSet(ruleSetValueOverChecksum, nil)
|
|
|
|
valueOverSet.Add(valueOverAttrs)
|
|
|
|
valueAttrs[string(ruleSetOverAttr)] = valueOverSet
|
|
|
|
|
|
|
|
if contactGroups, ok := rs.ContactGroups[uint8(rule.Severity)]; ok {
|
|
|
|
sort.Strings(contactGroups)
|
|
|
|
thenAttrs[string(ruleSetNotifyAttr)] = contactGroups
|
|
|
|
}
|
|
|
|
thenSet := schema.NewSet(ruleSetThenChecksum, nil)
|
|
|
|
thenSet.Add(thenAttrs)
|
|
|
|
|
|
|
|
valueSet := schema.NewSet(ruleSetValueChecksum, nil)
|
|
|
|
valueSet.Add(valueAttrs)
|
|
|
|
ifAttrs[string(ruleSetThenAttr)] = thenSet
|
|
|
|
ifAttrs[string(ruleSetValueAttr)] = valueSet
|
|
|
|
|
|
|
|
ifRules = append(ifRules, ifAttrs)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Set(ruleSetCheckAttr, rs.CheckCID)
|
|
|
|
|
|
|
|
if err := d.Set(ruleSetIfAttr, ifRules); err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("Unable to store rule set %q attribute: {{err}}", ruleSetIfAttr), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Set(ruleSetLinkAttr, indirect(rs.Link))
|
|
|
|
d.Set(ruleSetMetricNameAttr, rs.MetricName)
|
|
|
|
d.Set(ruleSetMetricTypeAttr, rs.MetricType)
|
|
|
|
d.Set(ruleSetNotesAttr, indirect(rs.Notes))
|
|
|
|
d.Set(ruleSetParentAttr, indirect(rs.Parent))
|
|
|
|
|
|
|
|
if err := d.Set(ruleSetTagsAttr, tagsToState(apiToTags(rs.Tags))); err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("Unable to store rule set %q attribute: {{err}}", ruleSetTagsAttr), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
ctxt := meta.(*providerContext)
|
|
|
|
rs := newRuleSet()
|
|
|
|
|
|
|
|
if err := rs.ParseConfig(d); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.CID = d.Id()
|
|
|
|
if err := rs.Update(ctxt); err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("unable to update rule set %q: {{err}}", d.Id()), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ruleSetRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
ctxt := meta.(*providerContext)
|
|
|
|
|
|
|
|
cid := d.Id()
|
|
|
|
if _, err := ctxt.client.DeleteRuleSetByCID(api.CIDType(&cid)); err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("unable to delete rule set %q: {{err}}", d.Id()), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId("")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type circonusRuleSet struct {
|
|
|
|
api.RuleSet
|
|
|
|
}
|
|
|
|
|
|
|
|
func newRuleSet() circonusRuleSet {
|
|
|
|
rs := circonusRuleSet{
|
|
|
|
RuleSet: *api.NewRuleSet(),
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.ContactGroups = make(map[uint8][]string, config.NumSeverityLevels)
|
|
|
|
for i := uint8(0); i < config.NumSeverityLevels; i++ {
|
|
|
|
rs.ContactGroups[i+1] = make([]string, 0, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.Rules = make([]api.RuleSetRule, 0, 1)
|
|
|
|
|
|
|
|
return rs
|
|
|
|
}
|
|
|
|
|
|
|
|
func loadRuleSet(ctxt *providerContext, cid api.CIDType) (circonusRuleSet, error) {
|
|
|
|
var rs circonusRuleSet
|
|
|
|
crs, err := ctxt.client.FetchRuleSet(cid)
|
|
|
|
if err != nil {
|
|
|
|
return circonusRuleSet{}, err
|
|
|
|
}
|
|
|
|
rs.RuleSet = *crs
|
|
|
|
|
|
|
|
return rs, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetThenChecksum(v interface{}) int {
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
b.Grow(defaultHashBufSize)
|
|
|
|
|
|
|
|
writeInt := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
i := v.(int)
|
|
|
|
if i != 0 {
|
|
|
|
fmt.Fprintf(b, "%x", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeString := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
s := strings.TrimSpace(v.(string))
|
|
|
|
if s != "" {
|
|
|
|
fmt.Fprint(b, s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeStringArray := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
a := v.([]string)
|
|
|
|
if a != nil {
|
|
|
|
sort.Strings(a)
|
|
|
|
for _, s := range a {
|
|
|
|
fmt.Fprint(b, strings.TrimSpace(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m := v.(map[string]interface{})
|
|
|
|
|
|
|
|
writeString(m, ruleSetAfterAttr)
|
|
|
|
writeStringArray(m, ruleSetNotifyAttr)
|
|
|
|
writeInt(m, ruleSetSeverityAttr)
|
|
|
|
|
|
|
|
s := b.String()
|
|
|
|
return hashcode.String(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetValueChecksum(v interface{}) int {
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
b.Grow(defaultHashBufSize)
|
|
|
|
|
|
|
|
writeBool := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
fmt.Fprintf(b, "%t", v.(bool))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeDuration := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
d, _ := time.ParseDuration(s)
|
|
|
|
fmt.Fprint(b, d.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeString := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
s := strings.TrimSpace(v.(string))
|
|
|
|
if s != "" {
|
|
|
|
fmt.Fprint(b, s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m := v.(map[string]interface{})
|
|
|
|
|
|
|
|
if v, found := m[ruleSetValueAttr]; found {
|
|
|
|
valueMap := v.(map[string]interface{})
|
|
|
|
if valueMap != nil {
|
|
|
|
writeDuration(valueMap, ruleSetAbsentAttr)
|
|
|
|
writeBool(valueMap, ruleSetChangedAttr)
|
|
|
|
writeString(valueMap, ruleSetContainsAttr)
|
|
|
|
writeString(valueMap, ruleSetMatchAttr)
|
|
|
|
writeString(valueMap, ruleSetNotMatchAttr)
|
|
|
|
writeString(valueMap, ruleSetMinValueAttr)
|
|
|
|
writeString(valueMap, ruleSetNotContainAttr)
|
|
|
|
writeString(valueMap, ruleSetMaxValueAttr)
|
|
|
|
|
|
|
|
if v, found := valueMap[ruleSetOverAttr]; found {
|
|
|
|
overMap := v.(map[string]interface{})
|
|
|
|
writeDuration(overMap, ruleSetLastAttr)
|
|
|
|
writeString(overMap, ruleSetUsingAttr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s := b.String()
|
|
|
|
return hashcode.String(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ruleSetValueOverChecksum(v interface{}) int {
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
b.Grow(defaultHashBufSize)
|
|
|
|
|
|
|
|
writeString := func(m map[string]interface{}, attrName string) {
|
|
|
|
if v, found := m[attrName]; found {
|
|
|
|
s := strings.TrimSpace(v.(string))
|
|
|
|
if s != "" {
|
|
|
|
fmt.Fprint(b, s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m := v.(map[string]interface{})
|
|
|
|
|
|
|
|
writeString(m, ruleSetLastAttr)
|
|
|
|
writeString(m, ruleSetUsingAttr)
|
|
|
|
|
|
|
|
s := b.String()
|
|
|
|
return hashcode.String(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseConfig reads Terraform config data and stores the information into a
|
|
|
|
// Circonus RuleSet object. ParseConfig, ruleSetRead(), and ruleSetChecksum
|
|
|
|
// must be kept in sync.
|
|
|
|
func (rs *circonusRuleSet) ParseConfig(d *schema.ResourceData) error {
|
|
|
|
if v, found := d.GetOk(ruleSetCheckAttr); found {
|
|
|
|
rs.CheckCID = v.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetLinkAttr); found {
|
|
|
|
s := v.(string)
|
|
|
|
rs.Link = &s
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetMetricTypeAttr); found {
|
|
|
|
rs.MetricType = v.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetNotesAttr); found {
|
|
|
|
s := v.(string)
|
|
|
|
rs.Notes = &s
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetParentAttr); found {
|
|
|
|
s := v.(string)
|
|
|
|
rs.Parent = &s
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetMetricNameAttr); found {
|
|
|
|
rs.MetricName = v.(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.Rules = make([]api.RuleSetRule, 0, defaultRuleSetRuleLen)
|
|
|
|
if ifListRaw, found := d.GetOk(ruleSetIfAttr); found {
|
|
|
|
ifList := ifListRaw.([]interface{})
|
|
|
|
for _, ifListElem := range ifList {
|
|
|
|
ifAttrs := newInterfaceMap(ifListElem.(map[string]interface{}))
|
|
|
|
|
|
|
|
rule := api.RuleSetRule{}
|
|
|
|
|
|
|
|
if thenListRaw, found := ifAttrs[ruleSetThenAttr]; found {
|
|
|
|
thenList := thenListRaw.(*schema.Set).List()
|
|
|
|
|
|
|
|
for _, thenListRaw := range thenList {
|
|
|
|
thenAttrs := newInterfaceMap(thenListRaw)
|
|
|
|
|
|
|
|
if v, found := thenAttrs[ruleSetAfterAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
d, err := time.ParseDuration(v.(string))
|
|
|
|
if err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("unable to parse %q duration %q: {{err}}", ruleSetAfterAttr, v.(string)), err)
|
|
|
|
}
|
|
|
|
rule.Wait = uint(d.Minutes())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: break from convention of alpha sorting attributes and handle Notify after Severity
|
|
|
|
|
|
|
|
if i, found := thenAttrs[ruleSetSeverityAttr]; found {
|
|
|
|
rule.Severity = uint(i.(int))
|
|
|
|
}
|
|
|
|
|
|
|
|
if notifyListRaw, found := thenAttrs[ruleSetNotifyAttr]; found {
|
|
|
|
notifyList := interfaceList(notifyListRaw.([]interface{}))
|
|
|
|
|
|
|
|
sev := uint8(rule.Severity)
|
|
|
|
for _, contactGroupCID := range notifyList.List() {
|
|
|
|
var found bool
|
|
|
|
if contactGroups, ok := rs.ContactGroups[sev]; ok {
|
|
|
|
for _, contactGroup := range contactGroups {
|
|
|
|
if contactGroup == contactGroupCID {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
rs.ContactGroups[sev] = append(rs.ContactGroups[sev], contactGroupCID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ruleSetValueListRaw, found := ifAttrs[ruleSetValueAttr]; found {
|
|
|
|
ruleSetValueList := ruleSetValueListRaw.(*schema.Set).List()
|
|
|
|
|
|
|
|
for _, valueListRaw := range ruleSetValueList {
|
|
|
|
valueAttrs := newInterfaceMap(valueListRaw)
|
|
|
|
|
|
|
|
METRIC_TYPE:
|
|
|
|
switch rs.MetricType {
|
|
|
|
case ruleSetMetricTypeNumeric:
|
|
|
|
if v, found := valueAttrs[ruleSetAbsentAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
d, _ := time.ParseDuration(s)
|
|
|
|
rule.Criteria = apiRuleSetAbsent
|
|
|
|
rule.Value = float64(d.Seconds())
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetChangedAttr]; found {
|
|
|
|
b := v.(bool)
|
|
|
|
if b {
|
|
|
|
rule.Criteria = apiRuleSetChanged
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetMinValueAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetMinValue
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetMaxValueAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetMaxValue
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case ruleSetMetricTypeText:
|
|
|
|
if v, found := valueAttrs[ruleSetAbsentAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
d, _ := time.ParseDuration(s)
|
|
|
|
rule.Criteria = apiRuleSetAbsent
|
|
|
|
rule.Value = float64(d.Seconds())
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetChangedAttr]; found {
|
|
|
|
b := v.(bool)
|
|
|
|
if b {
|
|
|
|
rule.Criteria = apiRuleSetChanged
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetContainsAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetContains
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetMatchAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetMatch
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetNotMatchAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetNotMatch
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := valueAttrs[ruleSetNotContainAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
if s != "" {
|
|
|
|
rule.Criteria = apiRuleSetNotContains
|
|
|
|
rule.Value = s
|
|
|
|
break METRIC_TYPE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("PROVIDER BUG: unsupported rule set metric type: %q", rs.MetricType)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ruleSetOverListRaw, found := valueAttrs[ruleSetOverAttr]; found {
|
|
|
|
overList := ruleSetOverListRaw.(*schema.Set).List()
|
|
|
|
|
|
|
|
for _, overListRaw := range overList {
|
|
|
|
overAttrs := newInterfaceMap(overListRaw)
|
|
|
|
|
|
|
|
if v, found := overAttrs[ruleSetLastAttr]; found {
|
|
|
|
last, err := time.ParseDuration(v.(string))
|
|
|
|
if err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("unable to parse duration %s attribute", ruleSetLastAttr), err)
|
|
|
|
}
|
|
|
|
rule.WindowingDuration = uint(last.Seconds())
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := overAttrs[ruleSetUsingAttr]; found {
|
|
|
|
s := v.(string)
|
|
|
|
rule.WindowingFunction = &s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rs.Rules = append(rs.Rules, rule)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, found := d.GetOk(ruleSetTagsAttr); found {
|
|
|
|
rs.Tags = derefStringList(flattenSet(v.(*schema.Set)))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := rs.Validate(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rs *circonusRuleSet) Create(ctxt *providerContext) error {
|
|
|
|
crs, err := ctxt.client.CreateRuleSet(&rs.RuleSet)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
rs.CID = crs.CID
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rs *circonusRuleSet) Update(ctxt *providerContext) error {
|
|
|
|
_, err := ctxt.client.UpdateRuleSet(&rs.RuleSet)
|
|
|
|
if err != nil {
|
|
|
|
return errwrap.Wrapf(fmt.Sprintf("Unable to update rule set %s: {{err}}", rs.CID), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rs *circonusRuleSet) Validate() error {
|
|
|
|
// TODO(sean@): From https://login.circonus.com/resources/api/calls/rule_set
|
|
|
|
// under `value`:
|
|
|
|
//
|
|
|
|
// For an 'on absence' rule this is the number of seconds the metric must not
|
|
|
|
// have been collected for, and should not be lower than either the period or
|
|
|
|
// timeout of the metric being collected.
|
|
|
|
|
|
|
|
for i, rule := range rs.Rules {
|
|
|
|
if rule.Criteria == "" {
|
|
|
|
return fmt.Errorf("rule %d for check ID %s has an empty criteria", i, rs.CheckCID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|