From aafa6aca1b446bcc0c7a64b33222040b2709bf84 Mon Sep 17 00:00:00 2001 From: Koenraad Verheyden Date: Wed, 12 Aug 2020 00:25:58 +0200 Subject: [PATCH] Add honeycombio_trigger_recipient data source --- docs/data-sources/trigger_recipient.md | 70 ++++++++++++++++ docs/resources/trigger.md | 10 +-- honeycombio/data_source_trigger_recipient.go | 56 +++++++++++++ .../data_source_trigger_recipient_test.go | 80 +++++++++++++++++++ honeycombio/provider.go | 3 +- honeycombio/resource_trigger.go | 3 +- 6 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 docs/data-sources/trigger_recipient.md create mode 100644 honeycombio/data_source_trigger_recipient.go create mode 100644 honeycombio/data_source_trigger_recipient_test.go diff --git a/docs/data-sources/trigger_recipient.md b/docs/data-sources/trigger_recipient.md new file mode 100644 index 00000000..ec420724 --- /dev/null +++ b/docs/data-sources/trigger_recipient.md @@ -0,0 +1,70 @@ +# Data Source: honeycombio_trigger_recipient + +Search the triggers of a dataset for a trigger recipient. The ID of the already existing trigger recipient can be used when creating new triggers. Specifying a trigger recipient by ID is necessary when creating Slack recipients using the API. + +## Example Usage + +```hcl +variable "dataset" { + type = string +} + +# search for a trigger recipient of type "slack" and target "honeycomb-triggers" in the given dataaset +data "honeycombio_trigger_recipient" "slack" { + dataset = var.dataset + type = "slack" + target = "honeycomb-triggers" +} + +data "honeycombio_query" "example" { + calculation { + op = "AVG" + column = "duration_ms" + } +} + +resource "honeycombio_trigger" "example" { + name = "Requests are slower than usuals" + + query_json = data.honeycombio_query.example.json + dataset = var.dataset + + frequency = 600 // in seconds, 10 minutes + + threshold { + op = ">" + value = 1000 + } + + recipient { + type = "email" + target = "hello@example.com" + } + + # add an already existing recipient + recipient { + id = data.honeycombio_trigger_recipient.slack + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `dataset` - (Required) Search through all triggers linked to this dataset. +* `type` - (Required) The type of recipient, allowed types are `email`, `marker`, `pagerduty` and `slack`. +* `target` - (Optional) Target of the trigger, this has another meaning depending on the type of recipient (see the table below). + +Type | Target +----------|------------------------- +email | an email address +marker | name of the marker +pagerduty | _N/A_ +slack | name of the channel + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the trigger recipient. diff --git a/docs/resources/trigger.md b/docs/resources/trigger.md index 5e6787f3..1e219180 100644 --- a/docs/resources/trigger.md +++ b/docs/resources/trigger.md @@ -66,11 +66,11 @@ Each trigger configuration must contain exactly one `threshold` block, which acc * `op` - (Required) The operator to apply, allowed threshold operators are `>`, `>=`, `<`, and `<=`. * `value` - (Required) The value to be used with the operator. -Each trigger configuration may have zero or more `recipient` blocks, which each accept the following arguments: +Each trigger configuration may have zero or more `recipient` blocks, which each accept the following arguments. A trigger recipient block can either refer to an existing recipient, i.e. a recipient that is already present in another trigger, or a new recipient. When specifying an existing recipient, only `id` must be set. To retrieve the ID of an existing recipient, refer to the [`honeycombio_trigger_recipient`](../data-sources/trigger_recipient.md) data source. -* `type` - (Required) The type of recipient, allowed types are `email`, `marker`, `pagerduty` and `slack`. -* `target` - (Optional) Target of the trigger, this has another meaning depending on the type of recipient (see the table below). -* `id` - (Optional) The ID of the recipient, this is necessary when type is Slack (see the note below). +* `type` - (Optional) The type of the trigger recipient, allowed types are `email`, `marker`, `pagerduty` and `slack`. Should not be used in combination with `id`. +* `target` - (Optional) Target of the trigger recipient, this has another meaning depending on the type of recipient (see the table below). Should not be used in combination with `id`. +* `id` - (Optional) The ID of an already existing recipient, this is necessary when type is Slack (see the note below). Should not be used in combination with `type`. Type | Target ----------|------------------------- @@ -79,7 +79,7 @@ marker | name of the marker pagerduty | _N/A_ slack | name of the channel -~> **NOTE** When type is Slack you have to specify the ID. Refer to [Specifying Recipients](https://docs.honeycomb.io/api/triggers/#specifying-recipients) for more information. It's currently not possible to retrieve this ID using the Terraform provider. +~> **NOTE** Recipients of type `slack` can not be created using the API. Instead, you have to refer to existing Slack recipients using their ID. Refer to [Specifying Recipients](https://docs.honeycomb.io/api/triggers/#specifying-recipients) for more information. You can use the [`honeycombio_trigger_recipient`](../data-sources/trigger_recipient.md) data source to find an already existing recipient. ## Attribute Reference diff --git a/honeycombio/data_source_trigger_recipient.go b/honeycombio/data_source_trigger_recipient.go new file mode 100644 index 00000000..da8d2928 --- /dev/null +++ b/honeycombio/data_source_trigger_recipient.go @@ -0,0 +1,56 @@ +package honeycombio + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + honeycombio "github.com/kvrhdn/go-honeycombio" +) + +func dataSourceHoneycombioSlackRecipient() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceHoneycombioSlackRecipientRead, + + Schema: map[string]*schema.Schema{ + "dataset": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(validTriggerRecipientTypes, false), + }, + "target": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func dataSourceHoneycombioSlackRecipientRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*honeycombio.Client) + dataset := d.Get("dataset").(string) + + triggers, err := client.Triggers.List(dataset) + if err != nil { + return diag.FromErr(err) + } + + searchType := honeycombio.TriggerRecipientType(d.Get("type").(string)) + searchTarget := d.Get("target").(string) + + for _, t := range triggers { + for _, r := range t.Recipients { + if r.Type == searchType && r.Target == searchTarget { + d.SetId(r.ID) + return nil + } + } + } + + return diag.Errorf("could not find a trigger recipient in \"%s\" with type = \"%s\" and target = \"%s\"", dataset, searchType, searchTarget) +} diff --git a/honeycombio/data_source_trigger_recipient_test.go b/honeycombio/data_source_trigger_recipient_test.go new file mode 100644 index 00000000..bbe795ce --- /dev/null +++ b/honeycombio/data_source_trigger_recipient_test.go @@ -0,0 +1,80 @@ +package honeycombio + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + honeycombio "github.com/kvrhdn/go-honeycombio" +) + +func TestAccDataSourceHoneycombioTriggerRecipient_basic(t *testing.T) { + c := testAccProvider.Meta().(*honeycombio.Client) + dataset := testAccDataset() + + trigger := testAccTriggerRecipientCreateTrigger(t, c, dataset) + defer testAccTriggerRecipientDeleteTrigger(t, c, dataset, trigger) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccTriggerRecipient(dataset, "email", "acctest@example.com"), + }, + { + Config: testAccTriggerRecipient(dataset, "email", "another@example.com"), + ExpectError: regexp.MustCompile("could not find a trigger recipient in "), + }, + { + Config: testAccTriggerRecipient(dataset, "slack", "acctest@example.com"), + ExpectError: regexp.MustCompile("could not find a trigger recipient in "), + }, + }, + }) +} + +func testAccTriggerRecipient(dataset, recipientType, target string) string { + return fmt.Sprintf(` +data "honeycombio_trigger_recipient" "test" { + dataset = "%s" + type = "%s" + target = "%s" +}`, dataset, recipientType, target) +} + +func testAccTriggerRecipientCreateTrigger(t *testing.T, c *honeycombio.Client, dataset string) *honeycombio.Trigger { + trigger := &honeycombio.Trigger{ + Name: "Terraform provider - acc test trigger recipient", + Query: &honeycombio.QuerySpec{ + Calculations: []honeycombio.CalculationSpec{ + { + Op: honeycombio.CalculateOpCount, + }, + }, + }, + Threshold: &honeycombio.TriggerThreshold{ + Op: honeycombio.TriggerThresholdOpGreaterThan, + Value: &[]float64{100}[0], + }, + Recipients: []honeycombio.TriggerRecipient{ + { + Type: honeycombio.TriggerRecipientTypeEmail, + Target: "acctest@example.com", + }, + }, + } + trigger, err := c.Triggers.Create(dataset, trigger) + if err != nil { + t.Error(err) + } + return trigger +} + +func testAccTriggerRecipientDeleteTrigger(t *testing.T, c *honeycombio.Client, dataset string, trigger *honeycombio.Trigger) { + err := c.Triggers.Delete(dataset, trigger.ID) + if err != nil { + t.Error(err) + } +} diff --git a/honeycombio/provider.go b/honeycombio/provider.go index 77cc518b..1210ed90 100644 --- a/honeycombio/provider.go +++ b/honeycombio/provider.go @@ -37,7 +37,8 @@ func Provider() *schema.Provider { }, }, DataSourcesMap: map[string]*schema.Resource{ - "honeycombio_query": dataSourceHoneycombioQuery(), + "honeycombio_query": dataSourceHoneycombioQuery(), + "honeycombio_trigger_recipient": dataSourceHoneycombioSlackRecipient(), }, ResourcesMap: map[string]*schema.Resource{ "honeycombio_board": newBoard(), diff --git a/honeycombio/resource_trigger.go b/honeycombio/resource_trigger.go index ac17f725..dd2d85ef 100644 --- a/honeycombio/resource_trigger.go +++ b/honeycombio/resource_trigger.go @@ -77,6 +77,7 @@ func newTrigger() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ + // TODO can we validate either id or type+target is set? Schema: map[string]*schema.Schema{ "id": { Type: schema.TypeString, @@ -85,7 +86,7 @@ func newTrigger() *schema.Resource { }, "type": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringInSlice(validTriggerRecipientTypes, false), }, "target": {