From 58623a84f3c8fb28f1ecad6f00272f5ede0db5f1 Mon Sep 17 00:00:00 2001 From: Benjamin Toueg Date: Fri, 12 Apr 2019 17:53:43 +0200 Subject: [PATCH 01/22] Add synthetics_test resource --- datadog/provider.go | 1 + datadog/resource_datadog_synthetics_test_.go | 404 +++++ .../resource_datadog_synthetics_test_test.go | 381 +++++ go.mod | 3 + go.sum | 10 +- .../terraform/helper/resource/testing.go | 2 +- .../zorkian/go-datadog-api/README.md | 2 +- .../go-datadog-api/datadog-accessors.go | 1302 +++++++++++++++++ .../zorkian/go-datadog-api/events.go | 2 +- .../zorkian/go-datadog-api/helpers.go | 6 +- .../zorkian/go-datadog-api/monitors.go | 4 +- .../zorkian/go-datadog-api/synthetics.go | 197 +++ vendor/modules.txt | 4 +- website/docs/r/synthetics.html.markdown | 86 ++ 14 files changed, 2392 insertions(+), 12 deletions(-) create mode 100644 datadog/resource_datadog_synthetics_test_.go create mode 100644 datadog/resource_datadog_synthetics_test_test.go create mode 100644 vendor/github.com/zorkian/go-datadog-api/synthetics.go create mode 100644 website/docs/r/synthetics.html.markdown diff --git a/datadog/provider.go b/datadog/provider.go index b15e34aee0..e463573b14 100644 --- a/datadog/provider.go +++ b/datadog/provider.go @@ -35,6 +35,7 @@ func Provider() terraform.ResourceProvider { "datadog_downtime": resourceDatadogDowntime(), "datadog_metric_metadata": resourceDatadogMetricMetadata(), "datadog_monitor": resourceDatadogMonitor(), + "datadog_synthetics_test": resourceDatadogSyntheticsTest(), "datadog_timeboard": resourceDatadogTimeboard(), "datadog_screenboard": resourceDatadogScreenboard(), "datadog_user": resourceDatadogUser(), diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go new file mode 100644 index 0000000000..46ef8d4632 --- /dev/null +++ b/datadog/resource_datadog_synthetics_test_.go @@ -0,0 +1,404 @@ +// For more info about writing custom provider: shttps://www.terraform.io/docs/extend/writing-custom-providers.html + +package datadog + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + datadog "github.com/zorkian/go-datadog-api" +) + +var syntheticsTypes = []string{"api", "browser"} + +func resourceDatadogSyntheticsTest() *schema.Resource { + return &schema.Resource{ + Create: resourceDatadogSyntheticsTestCreate, + Read: resourceDatadogSyntheticsTestRead, + Update: resourceDatadogSyntheticsTestUpdate, + Delete: resourceDatadogSyntheticsTestDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(syntheticsTypes, false), + }, + "request": syntheticsTestRequest(), + "request_headers": { + Type: schema.TypeMap, + Optional: true, + }, + "assertions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeMap, + }, + }, + "device_ids": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "locations": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "options": syntheticsTestOptions(), + "name": { + Type: schema.TypeString, + Required: true, + }, + "message": { + Type: schema.TypeString, + Optional: true, + Default: "", + }, + "tags": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "paused": { + Type: schema.TypeBool, + Optional: true, + }, + }, + } +} + +func syntheticsTestRequest() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "method": { + Type: schema.TypeString, + Required: true, + }, + "url": { + Type: schema.TypeString, + Required: true, + }, + "body": { + Type: schema.TypeString, + Optional: true, + }, + "timeout": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + }, + }, + }, + } +} + +func syntheticsTestOptions() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tick_every": { + Type: schema.TypeInt, + Required: true, + }, + "min_failure_duration": { + Type: schema.TypeInt, + Optional: true, + }, + "min_location_failed": { + Type: schema.TypeInt, + Optional: true, + }, + }, + }, + } +} + +func resourceDatadogSyntheticsTestCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*datadog.Client) + + syntheticsTest := newSyntheticsTestFromLocalState(d) + createdSyntheticsTest, err := client.CreateSyntheticsTest(syntheticsTest) + if err != nil { + // Note that Id won't be set, so no state will be saved. + return fmt.Errorf("error creating synthetics test: %s", err.Error()) + } + + // If the Create callback returns with or without an error without an ID set using SetId, + // the resource is assumed to not be created, and no state is saved. + d.SetId(createdSyntheticsTest.GetPublicId()) + + // Call resume/pause webservice, because it is a dedicated endpoint apart from classical CRUD operations + updateSyntheticsTestLiveness(d, client) + + // Return the read function to ensure the state is reflected in the terraform.state file + return resourceDatadogSyntheticsTestRead(d, meta) +} + +func resourceDatadogSyntheticsTestRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*datadog.Client) + + syntheticsTest, err := client.GetSyntheticsTest(d.Id()) + if err != nil { + if strings.Contains(err.Error(), "404 Not Found") { + // Delete the resource from the local state since it doesn't exist anymore in the actual state + d.SetId("") + } + return err + } + + updateSyntheticsTestLocalState(d, syntheticsTest) + + return nil +} + +func resourceDatadogSyntheticsTestUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*datadog.Client) + + syntheticsTest := newSyntheticsTestFromLocalState(d) + if _, err := client.UpdateSyntheticsTest(d.Id(), syntheticsTest); err != nil { + // If the Update callback returns with or without an error, the full state is saved. + return err + } + + // Call resume/pause webservice, because it is a dedicated endpoint apart from classical CRUD operations + updateSyntheticsTestLiveness(d, client) + + // Return the read function to ensure the state is reflected in the terraform.state file + return resourceDatadogSyntheticsTestRead(d, meta) +} + +func resourceDatadogSyntheticsTestDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*datadog.Client) + + if err := client.DeleteSyntheticsTests([]string{d.Id()}); err != nil { + // The resource is assumed to still exist, and all prior state is preserved. + return err + } + + // The resource is assumed to be destroyed, and all state is removed. + return nil +} + +func isTargetOfTypeInt(assertionType string) bool { + for _, intTargetAssertionType := range []string{"responseTime", "statusCode"} { + if assertionType == intTargetAssertionType { + return true + } + } + return false +} + +func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.SyntheticsTest { + request := datadog.SyntheticsRequest{} + if attr, ok := d.GetOk("request.method"); ok { + request.SetMethod(attr.(string)) + } + if attr, ok := d.GetOk("request.url"); ok { + request.SetUrl(attr.(string)) + } + if attr, ok := d.GetOk("request.body"); ok { + request.SetBody(attr.(string)) + } + if attr, ok := d.GetOk("request.timeout"); ok { + timeoutInt, _ := strconv.Atoi(attr.(string)) + request.SetTimeout(timeoutInt) + } + if attr, ok := d.GetOk("request_headers"); ok { + headers := attr.(map[string]interface{}) + if len(headers) > 0 { + request.Headers = make(map[string]string) + } + for k, v := range headers { + request.Headers[k] = v.(string) + } + } + + config := datadog.SyntheticsConfig{ + Request: &request, + Variables: []interface{}{}, + } + + if attr, ok := d.GetOk("assertions"); ok { + for _, attr := range attr.([]interface{}) { + assertion := datadog.SyntheticsAssertion{} + assertionMap := attr.(map[string]interface{}) + if v, ok := assertionMap["type"]; ok { + assertionType := v.(string) + assertion.Type = &assertionType + } + if v, ok := assertionMap["property"]; ok { + assertionProperty := v.(string) + assertion.Property = &assertionProperty + } + if v, ok := assertionMap["operator"]; ok { + assertionOperator := v.(string) + assertion.Operator = &assertionOperator + } + if v, ok := assertionMap["target"]; ok { + if isTargetOfTypeInt(*assertion.Type) { + assertionTargetInt, _ := strconv.Atoi(v.(string)) + assertion.Target = assertionTargetInt + } else if *assertion.Operator == "validates" { + assertion.Target = json.RawMessage(v.(string)) + } else { + assertion.Target = v.(string) + } + } + config.Assertions = append(config.Assertions, assertion) + } + } + + options := datadog.SyntheticsOptions{} + if attr, ok := d.GetOk("options.tick_every"); ok { + tickEvery, _ := strconv.Atoi(attr.(string)) + options.SetTickEvery(tickEvery) + } + if attr, ok := d.GetOk("options.follow_redirects"); ok { + followRedirects, _ := attr.(bool) + options.SetFollowRedirects(followRedirects) + } + if attr, ok := d.GetOk("options.min_failure_duration"); ok { + minFailureDuration, _ := strconv.Atoi(attr.(string)) + options.SetMinFailureDuration(minFailureDuration) + } + if attr, ok := d.GetOk("options.min_location_failed"); ok { + minLocationFailed, _ := strconv.Atoi(attr.(string)) + options.SetMinFailureDuration(minLocationFailed) + } + if attr, ok := d.GetOk("device_ids"); ok { + deviceIds := []string{} + for _, s := range attr.([]interface{}) { + deviceIds := append(deviceIds, s.(string)) + } + options.DeviceIds = deviceIds + } + + syntheticsTest := datadog.SyntheticsTest{ + Name: datadog.String(d.Get("name").(string)), + Type: datadog.String(d.Get("type").(string)), + Config: &config, + Options: &options, + Message: datadog.String(d.Get("message").(string)), + } + + if attr, ok := d.GetOk("locations"); ok { + locations := []string{} + for _, s := range attr.([]interface{}) { + locations = append(locations, s.(string)) + } + syntheticsTest.Locations = locations + } + + if attr, ok := d.GetOk("tags"); ok { + tags := []string{} + for _, s := range attr.([]interface{}) { + tags = append(tags, s.(string)) + } + syntheticsTest.Tags = tags + } + + return &syntheticsTest +} + +func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *datadog.SyntheticsTest) { + d.Set("type", syntheticsTest.GetType()) + + actualRequest := syntheticsTest.GetConfig().Request + localRequest := newLocalMap(map[string]interface{}{ + "method": actualRequest.GetMethod(), + "url": actualRequest.GetUrl(), + "body": actualRequest.GetBody(), + "timeout": actualRequest.GetTimeout(), + }) + d.Set("request", localRequest) + d.Set("request_headers", actualRequest.Headers) + + actualAssertions := syntheticsTest.GetConfig().Assertions + localAssertions := []map[string]string{} + for _, assertion := range actualAssertions { + localAssertion := newLocalMap(map[string]interface{}{ + "type": assertion.GetType(), + "property": assertion.GetProperty(), + "operator": assertion.GetOperator(), + "target": assertion.Target, + }) + localAssertions = append(localAssertions, localAssertion) + } + d.Set("assertions", localAssertions) + + d.Set("device_ids", syntheticsTest.GetOptions().DeviceIds) + + d.Set("locations", syntheticsTest.Locations) + + actualOptions := syntheticsTest.GetOptions() + localOptions := newLocalMap(map[string]interface{}{ + "tick_every": actualOptions.GetTickEvery(), + "follow_redirects": actualOptions.GetFollowRedirects(), + "min_failure_duration": actualOptions.GetMinFailureDuration(), + "min_location_failed": actualOptions.GetMinLocationFailed(), + }) + d.Set("options", localOptions) + + d.Set("name", syntheticsTest.GetName()) + d.Set("message", syntheticsTest.GetMessage()) + d.Set("tags", syntheticsTest.Tags) + d.Set("paused", *syntheticsTest.Status == "paused") +} + +func updateSyntheticsTestLiveness(d *schema.ResourceData, client *datadog.Client) { + paused, ok := d.GetOk("paused") + if !ok { + return + } + if paused.(bool) { + client.PauseSyntheticsTest(d.Id()) + } else { + client.ResumeSyntheticsTest(d.Id()) + } +} + +func newLocalMap(actualMap map[string]interface{}) map[string]string { + localMap := make(map[string]string) + for k, i := range actualMap { + var valStr string + switch v := i.(type) { + case bool: + if v { + valStr = "1" + } else { + valStr = "0" + } + case int: + valStr = strconv.Itoa(v) + case float64: + valStr = strconv.FormatFloat(v, 'f', -1, 64) + case string: + valStr = v + default: + // TODO: manage target for JSON body assertions + valStrr, err := json.Marshal(v) + if err == nil { + valStr = string(valStrr) + } + } + if valStr != "" { + localMap[k] = valStr + } + } + return localMap +} diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go new file mode 100644 index 0000000000..480272ed6a --- /dev/null +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -0,0 +1,381 @@ +package datadog + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + datadog "github.com/zorkian/go-datadog-api" +) + +func TestAccDatadogSyntheticsAPITest_importBasic(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + { + Config: createSyntheticsAPITestConfig, + }, + { + ResourceName: "datadog_synthetics_test.foo", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccDatadogSyntheticsBrowserTest_importBasic(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + { + Config: createSyntheticsBrowserTestConfig, + }, + { + ResourceName: "datadog_synthetics_test.bar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccDatadogSyntheticsAPITest_Basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + createSyntheticsAPITestStep, + }, + }) +} + +func TestAccDatadogSyntheticsAPITest_Updated(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + createSyntheticsAPITestStep, + updateSyntheticsAPITestStep, + }, + }) +} + +func TestAccDatadogSyntheticsBrowserTest_Basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + createSyntheticsBrowserTestStep, + }, + }) +} + +var createSyntheticsAPITestStep = resource.TestStep{ + Config: createSyntheticsAPITestConfig, + Check: resource.ComposeTestCheckFunc( + testSyntheticsTestExists(), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "type", "api"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "request.method", "GET"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "request.url", "https://www.datadoghq.com"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.#", "4"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.type", "header"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.property", "content-type"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.operator", "contains"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.target", "application/json"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.1.type", "statusCode"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.1.operator", "is"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.1.target", "200"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.2.type", "responseTime"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.2.operator", "lessThan"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.2.target", "2000"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.3.type", "body"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.3.operator", "doesNotContain"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.3.target", "terraform"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "locations.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "locations.0", "aws:eu-central-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "locations.1", "aws:ap-northeast-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.tick_every", "60"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "name", "name for synthetics test foo"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "message", "Notify @datadog.user"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.0", "foo:bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.1", "baz"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "paused", "true"), + ), +} + +const createSyntheticsAPITestConfig = ` +resource "datadog_synthetics_test" "foo" { + type = "api" + + request { + method = "GET" + url = "https://www.datadoghq.com" + body = "this is a body" + timeout = 30 + } + request_headers { + "Accept" = "application/json" + "X-Datadog-Trace-ID" = "1234566789" + } + + assertions = [ + { + type = "header" + property = "content-type" + operator = "contains" + target = "application/json" + }, + { + type = "statusCode" + operator = "is" + target = "200" + }, + { + type = "responseTime" + operator = "lessThan" + target = "2000" + }, + { + type = "body" + operator = "doesNotContain" + target = "terraform" + } + ] + + locations = [ "aws:eu-central-1", "aws:ap-northeast-1" ] + options { + tick_every = 60 + min_failure_duration = 0 + min_location_failed = 0 + } + + name = "name for synthetics test foo" + message = "Notify @datadog.user" + tags = ["foo:bar", "baz"] + + paused = true +} +` + +var updateSyntheticsAPITestStep = resource.TestStep{ + Config: updateSyntheticsAPITestConfig, + Check: resource.ComposeTestCheckFunc( + testSyntheticsTestExists(), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "type", "api"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "request.method", "GET"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "request.url", "https://docs.datadoghq.com"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "request.timeout", "60"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.#", "1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.type", "statusCode"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.operator", "isNot"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "assertions.0.target", "500"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "locations.#", "1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "locations.0", "aws:eu-central-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.tick_every", "900"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "name", "updated name"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "message", "Notify @pagerduty"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.#", "3"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.0", "foo:bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.1", "foo"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "tags.2", "env:test"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "paused", "true"), + ), +} + +const updateSyntheticsAPITestConfig = ` +resource "datadog_synthetics_test" "foo" { + type = "api" + + request { + method = "GET" + url = "https://docs.datadoghq.com" + timeout = 60 + } + + assertions = [ + { + type = "statusCode" + operator = "isNot" + target = "500" + } + ] + + locations = [ "aws:eu-central-1" ] + + options { + tick_every = 900 + min_failure_duration = 0 + min_location_failed = 0 + } + + name = "updated name" + message = "Notify @pagerduty" + tags = ["foo:bar", "foo", "env:test"] + + paused = true +} +` + +var createSyntheticsBrowserTestStep = resource.TestStep{ + Config: createSyntheticsBrowserTestConfig, + Check: resource.ComposeTestCheckFunc( + testSyntheticsTestExists(), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "type", "browser"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.method", "GET"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.url", "https://www.datadoghq.com"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.body", "this is a body"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.timeout", "30"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.%", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.Accept", "application/json"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.X-Datadog-Trace-ID", "123456789"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "devices.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "devices.0", "laptop_large"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "devices.1", "mobile_small"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "assertions.#", "0"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "locations.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "locations.0", "aws:eu-central-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "locations.1", "aws:ap-northeast-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.tick_every", "900"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "name", "name for synthetics browser test bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "message", "Notify @datadog.user"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.0", "foo:bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.1", "baz"), + ), +} + +const createSyntheticsBrowserTestConfig = ` +resource "datadog_synthetics_test" "bar" { + type = "browser" + + request { + method = "GET" + url = "https://www.datadoghq.com" + body = "this is a body" + timeout = 30 + } + request_headers { + "Accept" = "application/json" + "X-Datadog-Trace-ID" = "123456789" + } + + devices = [ "laptop_large", "mobile_small" ] + locations = [ "aws:eu-central-1", "aws:ap-northeast-1" ] + options { + tick_every = 900 + min_failure_duration = 0 + min_location_failed = 0 + } + + name = "name for synthetics browser test bar" + message = "Notify @datadog.user" + tags = ["foo:bar", "baz"] + + paused = true +} +` + +func testSyntheticsTestExists() resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*datadog.Client) + + for _, r := range s.RootModule().Resources { + if _, err := client.GetSyntheticsTest(r.Primary.ID); err != nil { + return fmt.Errorf("Received an error retrieving synthetics test %s", err) + } + } + return nil + } +} + +func testSyntheticsTestIsDestroyed(s *terraform.State) error { + client := testAccProvider.Meta().(*datadog.Client) + + for _, r := range s.RootModule().Resources { + if _, err := client.GetSyntheticsTest(r.Primary.ID); err != nil { + if strings.Contains(err.Error(), "404 Not Found") { + continue + } + return fmt.Errorf("Received an error retrieving synthetics test %s", err) + } + return fmt.Errorf("Synthetics test still exists") + } + return nil +} diff --git a/go.mod b/go.mod index e46f8159f6..f66af57d2a 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/cenkalti/backoff v0.0.0-20161020194410-b02f2bbce11d // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/hashicorp/go-cleanhttp v0.5.0 github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001 // indirect github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f // indirect github.com/hashicorp/go-plugin v0.0.0-20181004024435-314501b665e0 // indirect @@ -23,3 +24,5 @@ require ( golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 // indirect google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e // indirect ) + +replace github.com/zorkian/go-datadog-api => github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d diff --git a/go.sum b/go.sum index e6b802d4d8..4bca84408f 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,14 @@ github.com/Azure/go-ntlmssp v0.0.0-20170803034930-c92175d54006/go.mod h1:chxPXzS github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290 h1:K9I21XUHNbYD3GNMmJBN0UKJCpdP+glftwNZ7Bo8kqY= github.com/ChrisTrenkamp/goxpath v0.0.0-20170625215350-4fe035839290/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= github.com/DHowett/go-plist v0.0.0-20180609054337-500bd5b9081b/go.mod h1:5paT5ZDrOm8eAJPem2Bd+q3FTi3Gxm/U4tb2tH8YIUQ= +github.com/DataDog/go-datadog-api v0.0.0-20190402145118-e4672b7066ac h1:2lpq/xj2C5pKzMPDRSLaakf7BomK3InPfcq42S/vAf4= +github.com/DataDog/go-datadog-api v0.0.0-20190402145118-e4672b7066ac/go.mod h1:M39kErhCx5HcdIQ1FA2NHJSWPA6qvUGkJ/Bhz6MAOa4= +github.com/DataDog/go-datadog-api v0.0.0-20190403100613-64d00d08241a h1:xutdLApqBruGT3dYCw+18pDWiYXRaHZxf94SaOB97Vc= +github.com/DataDog/go-datadog-api v0.0.0-20190403100613-64d00d08241a/go.mod h1:M39kErhCx5HcdIQ1FA2NHJSWPA6qvUGkJ/Bhz6MAOa4= +github.com/DataDog/go-datadog-api v0.0.0-20190409090430-627e185509df h1:hUKMb79rABpaespgHpSekKoALS47XPID/Ni6fRfmivo= +github.com/DataDog/go-datadog-api v0.0.0-20190409090430-627e185509df/go.mod h1:M39kErhCx5HcdIQ1FA2NHJSWPA6qvUGkJ/Bhz6MAOa4= +github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d h1:qWou04uTL243M06V6n7CB4LadBxNPGhv/TREJa9OVik= +github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d/go.mod h1:M39kErhCx5HcdIQ1FA2NHJSWPA6qvUGkJ/Bhz6MAOa4= github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292 h1:tuQ7w+my8a8mkwN7x2TSd7OzTjkZ7rAeSyH4xncuAMI= github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292/go.mod h1:KYCjqMOeHpNuTOiFQU6WEcTG7poCJrUs0YgyHNtn1no= github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= @@ -293,8 +301,6 @@ github.com/zclconf/go-cty v0.0.0-20180302160414-49fa5e03c418/go.mod h1:LnDKxj8gN github.com/zclconf/go-cty v0.0.0-20180815031001-58bb2bc0302a/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v0.0.0-20181017232614-01c5aba823a6 h1:Y9SzKuDy2J5QLFPmFk7/ZIzbu4/FrQK9Zwv4vjivNiM= github.com/zclconf/go-cty v0.0.0-20181017232614-01c5aba823a6/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zorkian/go-datadog-api v2.19.0+incompatible h1:G17NtfeHwrsQ2degevkwiVEirZENSOjbGOjLLT/kwa4= -github.com/zorkian/go-datadog-api v2.19.0+incompatible/go.mod h1:PkXwHX9CUQa/FpB9ZwAD45N1uhCW4MT/Wj7m36PbKss= golang.org/x/crypto v0.0.0-20180211211603-9de5f2eaf759/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 h1:gCHhzI+1R9peHIMyiWVxoVaWlk1cYK7VThX5ptLtbXY= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go index b97673fdf5..534230aefe 100644 --- a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go +++ b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go @@ -16,7 +16,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/hashicorp/errwrap" - "github.com/hashicorp/go-multierror" + multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/logutils" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/helper/logging" diff --git a/vendor/github.com/zorkian/go-datadog-api/README.md b/vendor/github.com/zorkian/go-datadog-api/README.md index b9d7fcbf95..73dd9cecc0 100644 --- a/vendor/github.com/zorkian/go-datadog-api/README.md +++ b/vendor/github.com/zorkian/go-datadog-api/README.md @@ -117,4 +117,4 @@ make generate Please see the LICENSE file for the included license information. -Copyright 2013-2017 by authors and contributors. +Copyright 2013-2019 by authors and contributors. diff --git a/vendor/github.com/zorkian/go-datadog-api/datadog-accessors.go b/vendor/github.com/zorkian/go-datadog-api/datadog-accessors.go index d08aacba3a..4dc457448a 100644 --- a/vendor/github.com/zorkian/go-datadog-api/datadog-accessors.go +++ b/vendor/github.com/zorkian/go-datadog-api/datadog-accessors.go @@ -7329,6 +7329,1277 @@ func (s *Style) SetPaletteFlip(v bool) { s.PaletteFlip = &v } +// GetOperator returns the Operator field if non-nil, zero value otherwise. +func (s *SyntheticsAssertion) GetOperator() string { + if s == nil || s.Operator == nil { + return "" + } + return *s.Operator +} + +// GetOperatorOk returns a tuple with the Operator field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsAssertion) GetOperatorOk() (string, bool) { + if s == nil || s.Operator == nil { + return "", false + } + return *s.Operator, true +} + +// HasOperator returns a boolean if a field has been set. +func (s *SyntheticsAssertion) HasOperator() bool { + if s != nil && s.Operator != nil { + return true + } + + return false +} + +// SetOperator allocates a new s.Operator and returns the pointer to it. +func (s *SyntheticsAssertion) SetOperator(v string) { + s.Operator = &v +} + +// GetProperty returns the Property field if non-nil, zero value otherwise. +func (s *SyntheticsAssertion) GetProperty() string { + if s == nil || s.Property == nil { + return "" + } + return *s.Property +} + +// GetPropertyOk returns a tuple with the Property field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsAssertion) GetPropertyOk() (string, bool) { + if s == nil || s.Property == nil { + return "", false + } + return *s.Property, true +} + +// HasProperty returns a boolean if a field has been set. +func (s *SyntheticsAssertion) HasProperty() bool { + if s != nil && s.Property != nil { + return true + } + + return false +} + +// SetProperty allocates a new s.Property and returns the pointer to it. +func (s *SyntheticsAssertion) SetProperty(v string) { + s.Property = &v +} + +// GetType returns the Type field if non-nil, zero value otherwise. +func (s *SyntheticsAssertion) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetTypeOk returns a tuple with the Type field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsAssertion) GetTypeOk() (string, bool) { + if s == nil || s.Type == nil { + return "", false + } + return *s.Type, true +} + +// HasType returns a boolean if a field has been set. +func (s *SyntheticsAssertion) HasType() bool { + if s != nil && s.Type != nil { + return true + } + + return false +} + +// SetType allocates a new s.Type and returns the pointer to it. +func (s *SyntheticsAssertion) SetType(v string) { + s.Type = &v +} + +// GetRequest returns the Request field if non-nil, zero value otherwise. +func (s *SyntheticsConfig) GetRequest() SyntheticsRequest { + if s == nil || s.Request == nil { + return SyntheticsRequest{} + } + return *s.Request +} + +// GetRequestOk returns a tuple with the Request field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsConfig) GetRequestOk() (SyntheticsRequest, bool) { + if s == nil || s.Request == nil { + return SyntheticsRequest{}, false + } + return *s.Request, true +} + +// HasRequest returns a boolean if a field has been set. +func (s *SyntheticsConfig) HasRequest() bool { + if s != nil && s.Request != nil { + return true + } + + return false +} + +// SetRequest allocates a new s.Request and returns the pointer to it. +func (s *SyntheticsConfig) SetRequest(v SyntheticsRequest) { + s.Request = &v +} + +// GetHeight returns the Height field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetHeight() int { + if s == nil || s.Height == nil { + return 0 + } + return *s.Height +} + +// GetHeightOk returns a tuple with the Height field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetHeightOk() (int, bool) { + if s == nil || s.Height == nil { + return 0, false + } + return *s.Height, true +} + +// HasHeight returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasHeight() bool { + if s != nil && s.Height != nil { + return true + } + + return false +} + +// SetHeight allocates a new s.Height and returns the pointer to it. +func (s *SyntheticsDevice) SetHeight(v int) { + s.Height = &v +} + +// GetId returns the Id field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetId() string { + if s == nil || s.Id == nil { + return "" + } + return *s.Id +} + +// GetIdOk returns a tuple with the Id field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetIdOk() (string, bool) { + if s == nil || s.Id == nil { + return "", false + } + return *s.Id, true +} + +// HasId returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasId() bool { + if s != nil && s.Id != nil { + return true + } + + return false +} + +// SetId allocates a new s.Id and returns the pointer to it. +func (s *SyntheticsDevice) SetId(v string) { + s.Id = &v +} + +// GetIsLandscape returns the IsLandscape field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetIsLandscape() bool { + if s == nil || s.IsLandscape == nil { + return false + } + return *s.IsLandscape +} + +// GetIsLandscapeOk returns a tuple with the IsLandscape field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetIsLandscapeOk() (bool, bool) { + if s == nil || s.IsLandscape == nil { + return false, false + } + return *s.IsLandscape, true +} + +// HasIsLandscape returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasIsLandscape() bool { + if s != nil && s.IsLandscape != nil { + return true + } + + return false +} + +// SetIsLandscape allocates a new s.IsLandscape and returns the pointer to it. +func (s *SyntheticsDevice) SetIsLandscape(v bool) { + s.IsLandscape = &v +} + +// GetIsMobile returns the IsMobile field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetIsMobile() bool { + if s == nil || s.IsMobile == nil { + return false + } + return *s.IsMobile +} + +// GetIsMobileOk returns a tuple with the IsMobile field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetIsMobileOk() (bool, bool) { + if s == nil || s.IsMobile == nil { + return false, false + } + return *s.IsMobile, true +} + +// HasIsMobile returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasIsMobile() bool { + if s != nil && s.IsMobile != nil { + return true + } + + return false +} + +// SetIsMobile allocates a new s.IsMobile and returns the pointer to it. +func (s *SyntheticsDevice) SetIsMobile(v bool) { + s.IsMobile = &v +} + +// GetName returns the Name field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetNameOk returns a tuple with the Name field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetNameOk() (string, bool) { + if s == nil || s.Name == nil { + return "", false + } + return *s.Name, true +} + +// HasName returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasName() bool { + if s != nil && s.Name != nil { + return true + } + + return false +} + +// SetName allocates a new s.Name and returns the pointer to it. +func (s *SyntheticsDevice) SetName(v string) { + s.Name = &v +} + +// GetUserAgent returns the UserAgent field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetUserAgent() string { + if s == nil || s.UserAgent == nil { + return "" + } + return *s.UserAgent +} + +// GetUserAgentOk returns a tuple with the UserAgent field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetUserAgentOk() (string, bool) { + if s == nil || s.UserAgent == nil { + return "", false + } + return *s.UserAgent, true +} + +// HasUserAgent returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasUserAgent() bool { + if s != nil && s.UserAgent != nil { + return true + } + + return false +} + +// SetUserAgent allocates a new s.UserAgent and returns the pointer to it. +func (s *SyntheticsDevice) SetUserAgent(v string) { + s.UserAgent = &v +} + +// GetWidth returns the Width field if non-nil, zero value otherwise. +func (s *SyntheticsDevice) GetWidth() int { + if s == nil || s.Width == nil { + return 0 + } + return *s.Width +} + +// GetWidthOk returns a tuple with the Width field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsDevice) GetWidthOk() (int, bool) { + if s == nil || s.Width == nil { + return 0, false + } + return *s.Width, true +} + +// HasWidth returns a boolean if a field has been set. +func (s *SyntheticsDevice) HasWidth() bool { + if s != nil && s.Width != nil { + return true + } + + return false +} + +// SetWidth allocates a new s.Width and returns the pointer to it. +func (s *SyntheticsDevice) SetWidth(v int) { + s.Width = &v +} + +// GetDisplayName returns the DisplayName field if non-nil, zero value otherwise. +func (s *SyntheticsLocation) GetDisplayName() string { + if s == nil || s.DisplayName == nil { + return "" + } + return *s.DisplayName +} + +// GetDisplayNameOk returns a tuple with the DisplayName field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsLocation) GetDisplayNameOk() (string, bool) { + if s == nil || s.DisplayName == nil { + return "", false + } + return *s.DisplayName, true +} + +// HasDisplayName returns a boolean if a field has been set. +func (s *SyntheticsLocation) HasDisplayName() bool { + if s != nil && s.DisplayName != nil { + return true + } + + return false +} + +// SetDisplayName allocates a new s.DisplayName and returns the pointer to it. +func (s *SyntheticsLocation) SetDisplayName(v string) { + s.DisplayName = &v +} + +// GetId returns the Id field if non-nil, zero value otherwise. +func (s *SyntheticsLocation) GetId() int { + if s == nil || s.Id == nil { + return 0 + } + return *s.Id +} + +// GetIdOk returns a tuple with the Id field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsLocation) GetIdOk() (int, bool) { + if s == nil || s.Id == nil { + return 0, false + } + return *s.Id, true +} + +// HasId returns a boolean if a field has been set. +func (s *SyntheticsLocation) HasId() bool { + if s != nil && s.Id != nil { + return true + } + + return false +} + +// SetId allocates a new s.Id and returns the pointer to it. +func (s *SyntheticsLocation) SetId(v int) { + s.Id = &v +} + +// GetIsLandscape returns the IsLandscape field if non-nil, zero value otherwise. +func (s *SyntheticsLocation) GetIsLandscape() bool { + if s == nil || s.IsLandscape == nil { + return false + } + return *s.IsLandscape +} + +// GetIsLandscapeOk returns a tuple with the IsLandscape field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsLocation) GetIsLandscapeOk() (bool, bool) { + if s == nil || s.IsLandscape == nil { + return false, false + } + return *s.IsLandscape, true +} + +// HasIsLandscape returns a boolean if a field has been set. +func (s *SyntheticsLocation) HasIsLandscape() bool { + if s != nil && s.IsLandscape != nil { + return true + } + + return false +} + +// SetIsLandscape allocates a new s.IsLandscape and returns the pointer to it. +func (s *SyntheticsLocation) SetIsLandscape(v bool) { + s.IsLandscape = &v +} + +// GetName returns the Name field if non-nil, zero value otherwise. +func (s *SyntheticsLocation) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetNameOk returns a tuple with the Name field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsLocation) GetNameOk() (string, bool) { + if s == nil || s.Name == nil { + return "", false + } + return *s.Name, true +} + +// HasName returns a boolean if a field has been set. +func (s *SyntheticsLocation) HasName() bool { + if s != nil && s.Name != nil { + return true + } + + return false +} + +// SetName allocates a new s.Name and returns the pointer to it. +func (s *SyntheticsLocation) SetName(v string) { + s.Name = &v +} + +// GetRegion returns the Region field if non-nil, zero value otherwise. +func (s *SyntheticsLocation) GetRegion() string { + if s == nil || s.Region == nil { + return "" + } + return *s.Region +} + +// GetRegionOk returns a tuple with the Region field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsLocation) GetRegionOk() (string, bool) { + if s == nil || s.Region == nil { + return "", false + } + return *s.Region, true +} + +// HasRegion returns a boolean if a field has been set. +func (s *SyntheticsLocation) HasRegion() bool { + if s != nil && s.Region != nil { + return true + } + + return false +} + +// SetRegion allocates a new s.Region and returns the pointer to it. +func (s *SyntheticsLocation) SetRegion(v string) { + s.Region = &v +} + +// GetFollowRedirects returns the FollowRedirects field if non-nil, zero value otherwise. +func (s *SyntheticsOptions) GetFollowRedirects() bool { + if s == nil || s.FollowRedirects == nil { + return false + } + return *s.FollowRedirects +} + +// GetFollowRedirectsOk returns a tuple with the FollowRedirects field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsOptions) GetFollowRedirectsOk() (bool, bool) { + if s == nil || s.FollowRedirects == nil { + return false, false + } + return *s.FollowRedirects, true +} + +// HasFollowRedirects returns a boolean if a field has been set. +func (s *SyntheticsOptions) HasFollowRedirects() bool { + if s != nil && s.FollowRedirects != nil { + return true + } + + return false +} + +// SetFollowRedirects allocates a new s.FollowRedirects and returns the pointer to it. +func (s *SyntheticsOptions) SetFollowRedirects(v bool) { + s.FollowRedirects = &v +} + +// GetMinFailureDuration returns the MinFailureDuration field if non-nil, zero value otherwise. +func (s *SyntheticsOptions) GetMinFailureDuration() int { + if s == nil || s.MinFailureDuration == nil { + return 0 + } + return *s.MinFailureDuration +} + +// GetMinFailureDurationOk returns a tuple with the MinFailureDuration field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsOptions) GetMinFailureDurationOk() (int, bool) { + if s == nil || s.MinFailureDuration == nil { + return 0, false + } + return *s.MinFailureDuration, true +} + +// HasMinFailureDuration returns a boolean if a field has been set. +func (s *SyntheticsOptions) HasMinFailureDuration() bool { + if s != nil && s.MinFailureDuration != nil { + return true + } + + return false +} + +// SetMinFailureDuration allocates a new s.MinFailureDuration and returns the pointer to it. +func (s *SyntheticsOptions) SetMinFailureDuration(v int) { + s.MinFailureDuration = &v +} + +// GetMinLocationFailed returns the MinLocationFailed field if non-nil, zero value otherwise. +func (s *SyntheticsOptions) GetMinLocationFailed() int { + if s == nil || s.MinLocationFailed == nil { + return 0 + } + return *s.MinLocationFailed +} + +// GetMinLocationFailedOk returns a tuple with the MinLocationFailed field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsOptions) GetMinLocationFailedOk() (int, bool) { + if s == nil || s.MinLocationFailed == nil { + return 0, false + } + return *s.MinLocationFailed, true +} + +// HasMinLocationFailed returns a boolean if a field has been set. +func (s *SyntheticsOptions) HasMinLocationFailed() bool { + if s != nil && s.MinLocationFailed != nil { + return true + } + + return false +} + +// SetMinLocationFailed allocates a new s.MinLocationFailed and returns the pointer to it. +func (s *SyntheticsOptions) SetMinLocationFailed(v int) { + s.MinLocationFailed = &v +} + +// GetTickEvery returns the TickEvery field if non-nil, zero value otherwise. +func (s *SyntheticsOptions) GetTickEvery() int { + if s == nil || s.TickEvery == nil { + return 0 + } + return *s.TickEvery +} + +// GetTickEveryOk returns a tuple with the TickEvery field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsOptions) GetTickEveryOk() (int, bool) { + if s == nil || s.TickEvery == nil { + return 0, false + } + return *s.TickEvery, true +} + +// HasTickEvery returns a boolean if a field has been set. +func (s *SyntheticsOptions) HasTickEvery() bool { + if s != nil && s.TickEvery != nil { + return true + } + + return false +} + +// SetTickEvery allocates a new s.TickEvery and returns the pointer to it. +func (s *SyntheticsOptions) SetTickEvery(v int) { + s.TickEvery = &v +} + +// GetBody returns the Body field if non-nil, zero value otherwise. +func (s *SyntheticsRequest) GetBody() string { + if s == nil || s.Body == nil { + return "" + } + return *s.Body +} + +// GetBodyOk returns a tuple with the Body field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsRequest) GetBodyOk() (string, bool) { + if s == nil || s.Body == nil { + return "", false + } + return *s.Body, true +} + +// HasBody returns a boolean if a field has been set. +func (s *SyntheticsRequest) HasBody() bool { + if s != nil && s.Body != nil { + return true + } + + return false +} + +// SetBody allocates a new s.Body and returns the pointer to it. +func (s *SyntheticsRequest) SetBody(v string) { + s.Body = &v +} + +// GetMethod returns the Method field if non-nil, zero value otherwise. +func (s *SyntheticsRequest) GetMethod() string { + if s == nil || s.Method == nil { + return "" + } + return *s.Method +} + +// GetMethodOk returns a tuple with the Method field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsRequest) GetMethodOk() (string, bool) { + if s == nil || s.Method == nil { + return "", false + } + return *s.Method, true +} + +// HasMethod returns a boolean if a field has been set. +func (s *SyntheticsRequest) HasMethod() bool { + if s != nil && s.Method != nil { + return true + } + + return false +} + +// SetMethod allocates a new s.Method and returns the pointer to it. +func (s *SyntheticsRequest) SetMethod(v string) { + s.Method = &v +} + +// GetTimeout returns the Timeout field if non-nil, zero value otherwise. +func (s *SyntheticsRequest) GetTimeout() int { + if s == nil || s.Timeout == nil { + return 0 + } + return *s.Timeout +} + +// GetTimeoutOk returns a tuple with the Timeout field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsRequest) GetTimeoutOk() (int, bool) { + if s == nil || s.Timeout == nil { + return 0, false + } + return *s.Timeout, true +} + +// HasTimeout returns a boolean if a field has been set. +func (s *SyntheticsRequest) HasTimeout() bool { + if s != nil && s.Timeout != nil { + return true + } + + return false +} + +// SetTimeout allocates a new s.Timeout and returns the pointer to it. +func (s *SyntheticsRequest) SetTimeout(v int) { + s.Timeout = &v +} + +// GetUrl returns the Url field if non-nil, zero value otherwise. +func (s *SyntheticsRequest) GetUrl() string { + if s == nil || s.Url == nil { + return "" + } + return *s.Url +} + +// GetUrlOk returns a tuple with the Url field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsRequest) GetUrlOk() (string, bool) { + if s == nil || s.Url == nil { + return "", false + } + return *s.Url, true +} + +// HasUrl returns a boolean if a field has been set. +func (s *SyntheticsRequest) HasUrl() bool { + if s != nil && s.Url != nil { + return true + } + + return false +} + +// SetUrl allocates a new s.Url and returns the pointer to it. +func (s *SyntheticsRequest) SetUrl(v string) { + s.Url = &v +} + +// GetConfig returns the Config field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetConfig() SyntheticsConfig { + if s == nil || s.Config == nil { + return SyntheticsConfig{} + } + return *s.Config +} + +// GetConfigOk returns a tuple with the Config field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetConfigOk() (SyntheticsConfig, bool) { + if s == nil || s.Config == nil { + return SyntheticsConfig{}, false + } + return *s.Config, true +} + +// HasConfig returns a boolean if a field has been set. +func (s *SyntheticsTest) HasConfig() bool { + if s != nil && s.Config != nil { + return true + } + + return false +} + +// SetConfig allocates a new s.Config and returns the pointer to it. +func (s *SyntheticsTest) SetConfig(v SyntheticsConfig) { + s.Config = &v +} + +// GetCreatedAt returns the CreatedAt field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetCreatedAt() string { + if s == nil || s.CreatedAt == nil { + return "" + } + return *s.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetCreatedAtOk() (string, bool) { + if s == nil || s.CreatedAt == nil { + return "", false + } + return *s.CreatedAt, true +} + +// HasCreatedAt returns a boolean if a field has been set. +func (s *SyntheticsTest) HasCreatedAt() bool { + if s != nil && s.CreatedAt != nil { + return true + } + + return false +} + +// SetCreatedAt allocates a new s.CreatedAt and returns the pointer to it. +func (s *SyntheticsTest) SetCreatedAt(v string) { + s.CreatedAt = &v +} + +// GetCreatedBy returns the CreatedBy field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetCreatedBy() SyntheticsUser { + if s == nil || s.CreatedBy == nil { + return SyntheticsUser{} + } + return *s.CreatedBy +} + +// GetCreatedByOk returns a tuple with the CreatedBy field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetCreatedByOk() (SyntheticsUser, bool) { + if s == nil || s.CreatedBy == nil { + return SyntheticsUser{}, false + } + return *s.CreatedBy, true +} + +// HasCreatedBy returns a boolean if a field has been set. +func (s *SyntheticsTest) HasCreatedBy() bool { + if s != nil && s.CreatedBy != nil { + return true + } + + return false +} + +// SetCreatedBy allocates a new s.CreatedBy and returns the pointer to it. +func (s *SyntheticsTest) SetCreatedBy(v SyntheticsUser) { + s.CreatedBy = &v +} + +// GetDeletedAt returns the DeletedAt field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetDeletedAt() string { + if s == nil || s.DeletedAt == nil { + return "" + } + return *s.DeletedAt +} + +// GetDeletedAtOk returns a tuple with the DeletedAt field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetDeletedAtOk() (string, bool) { + if s == nil || s.DeletedAt == nil { + return "", false + } + return *s.DeletedAt, true +} + +// HasDeletedAt returns a boolean if a field has been set. +func (s *SyntheticsTest) HasDeletedAt() bool { + if s != nil && s.DeletedAt != nil { + return true + } + + return false +} + +// SetDeletedAt allocates a new s.DeletedAt and returns the pointer to it. +func (s *SyntheticsTest) SetDeletedAt(v string) { + s.DeletedAt = &v +} + +// GetMessage returns the Message field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetMessage() string { + if s == nil || s.Message == nil { + return "" + } + return *s.Message +} + +// GetMessageOk returns a tuple with the Message field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetMessageOk() (string, bool) { + if s == nil || s.Message == nil { + return "", false + } + return *s.Message, true +} + +// HasMessage returns a boolean if a field has been set. +func (s *SyntheticsTest) HasMessage() bool { + if s != nil && s.Message != nil { + return true + } + + return false +} + +// SetMessage allocates a new s.Message and returns the pointer to it. +func (s *SyntheticsTest) SetMessage(v string) { + s.Message = &v +} + +// GetModifiedAt returns the ModifiedAt field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetModifiedAt() string { + if s == nil || s.ModifiedAt == nil { + return "" + } + return *s.ModifiedAt +} + +// GetModifiedAtOk returns a tuple with the ModifiedAt field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetModifiedAtOk() (string, bool) { + if s == nil || s.ModifiedAt == nil { + return "", false + } + return *s.ModifiedAt, true +} + +// HasModifiedAt returns a boolean if a field has been set. +func (s *SyntheticsTest) HasModifiedAt() bool { + if s != nil && s.ModifiedAt != nil { + return true + } + + return false +} + +// SetModifiedAt allocates a new s.ModifiedAt and returns the pointer to it. +func (s *SyntheticsTest) SetModifiedAt(v string) { + s.ModifiedAt = &v +} + +// GetModifiedBy returns the ModifiedBy field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetModifiedBy() SyntheticsUser { + if s == nil || s.ModifiedBy == nil { + return SyntheticsUser{} + } + return *s.ModifiedBy +} + +// GetModifiedByOk returns a tuple with the ModifiedBy field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetModifiedByOk() (SyntheticsUser, bool) { + if s == nil || s.ModifiedBy == nil { + return SyntheticsUser{}, false + } + return *s.ModifiedBy, true +} + +// HasModifiedBy returns a boolean if a field has been set. +func (s *SyntheticsTest) HasModifiedBy() bool { + if s != nil && s.ModifiedBy != nil { + return true + } + + return false +} + +// SetModifiedBy allocates a new s.ModifiedBy and returns the pointer to it. +func (s *SyntheticsTest) SetModifiedBy(v SyntheticsUser) { + s.ModifiedBy = &v +} + +// GetMonitorStatus returns the MonitorStatus field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetMonitorStatus() string { + if s == nil || s.MonitorStatus == nil { + return "" + } + return *s.MonitorStatus +} + +// GetMonitorStatusOk returns a tuple with the MonitorStatus field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetMonitorStatusOk() (string, bool) { + if s == nil || s.MonitorStatus == nil { + return "", false + } + return *s.MonitorStatus, true +} + +// HasMonitorStatus returns a boolean if a field has been set. +func (s *SyntheticsTest) HasMonitorStatus() bool { + if s != nil && s.MonitorStatus != nil { + return true + } + + return false +} + +// SetMonitorStatus allocates a new s.MonitorStatus and returns the pointer to it. +func (s *SyntheticsTest) SetMonitorStatus(v string) { + s.MonitorStatus = &v +} + +// GetName returns the Name field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetNameOk returns a tuple with the Name field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetNameOk() (string, bool) { + if s == nil || s.Name == nil { + return "", false + } + return *s.Name, true +} + +// HasName returns a boolean if a field has been set. +func (s *SyntheticsTest) HasName() bool { + if s != nil && s.Name != nil { + return true + } + + return false +} + +// SetName allocates a new s.Name and returns the pointer to it. +func (s *SyntheticsTest) SetName(v string) { + s.Name = &v +} + +// GetOptions returns the Options field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetOptions() SyntheticsOptions { + if s == nil || s.Options == nil { + return SyntheticsOptions{} + } + return *s.Options +} + +// GetOptionsOk returns a tuple with the Options field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetOptionsOk() (SyntheticsOptions, bool) { + if s == nil || s.Options == nil { + return SyntheticsOptions{}, false + } + return *s.Options, true +} + +// HasOptions returns a boolean if a field has been set. +func (s *SyntheticsTest) HasOptions() bool { + if s != nil && s.Options != nil { + return true + } + + return false +} + +// SetOptions allocates a new s.Options and returns the pointer to it. +func (s *SyntheticsTest) SetOptions(v SyntheticsOptions) { + s.Options = &v +} + +// GetPublicId returns the PublicId field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetPublicId() string { + if s == nil || s.PublicId == nil { + return "" + } + return *s.PublicId +} + +// GetPublicIdOk returns a tuple with the PublicId field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetPublicIdOk() (string, bool) { + if s == nil || s.PublicId == nil { + return "", false + } + return *s.PublicId, true +} + +// HasPublicId returns a boolean if a field has been set. +func (s *SyntheticsTest) HasPublicId() bool { + if s != nil && s.PublicId != nil { + return true + } + + return false +} + +// SetPublicId allocates a new s.PublicId and returns the pointer to it. +func (s *SyntheticsTest) SetPublicId(v string) { + s.PublicId = &v +} + +// GetStatus returns the Status field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetStatusOk returns a tuple with the Status field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetStatusOk() (string, bool) { + if s == nil || s.Status == nil { + return "", false + } + return *s.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (s *SyntheticsTest) HasStatus() bool { + if s != nil && s.Status != nil { + return true + } + + return false +} + +// SetStatus allocates a new s.Status and returns the pointer to it. +func (s *SyntheticsTest) SetStatus(v string) { + s.Status = &v +} + +// GetType returns the Type field if non-nil, zero value otherwise. +func (s *SyntheticsTest) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetTypeOk returns a tuple with the Type field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsTest) GetTypeOk() (string, bool) { + if s == nil || s.Type == nil { + return "", false + } + return *s.Type, true +} + +// HasType returns a boolean if a field has been set. +func (s *SyntheticsTest) HasType() bool { + if s != nil && s.Type != nil { + return true + } + + return false +} + +// SetType allocates a new s.Type and returns the pointer to it. +func (s *SyntheticsTest) SetType(v string) { + s.Type = &v +} + +// GetEmail returns the Email field if non-nil, zero value otherwise. +func (s *SyntheticsUser) GetEmail() string { + if s == nil || s.Email == nil { + return "" + } + return *s.Email +} + +// GetEmailOk returns a tuple with the Email field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsUser) GetEmailOk() (string, bool) { + if s == nil || s.Email == nil { + return "", false + } + return *s.Email, true +} + +// HasEmail returns a boolean if a field has been set. +func (s *SyntheticsUser) HasEmail() bool { + if s != nil && s.Email != nil { + return true + } + + return false +} + +// SetEmail allocates a new s.Email and returns the pointer to it. +func (s *SyntheticsUser) SetEmail(v string) { + s.Email = &v +} + +// GetHandle returns the Handle field if non-nil, zero value otherwise. +func (s *SyntheticsUser) GetHandle() string { + if s == nil || s.Handle == nil { + return "" + } + return *s.Handle +} + +// GetHandleOk returns a tuple with the Handle field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsUser) GetHandleOk() (string, bool) { + if s == nil || s.Handle == nil { + return "", false + } + return *s.Handle, true +} + +// HasHandle returns a boolean if a field has been set. +func (s *SyntheticsUser) HasHandle() bool { + if s != nil && s.Handle != nil { + return true + } + + return false +} + +// SetHandle allocates a new s.Handle and returns the pointer to it. +func (s *SyntheticsUser) SetHandle(v string) { + s.Handle = &v +} + +// GetId returns the Id field if non-nil, zero value otherwise. +func (s *SyntheticsUser) GetId() int { + if s == nil || s.Id == nil { + return 0 + } + return *s.Id +} + +// GetIdOk returns a tuple with the Id field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsUser) GetIdOk() (int, bool) { + if s == nil || s.Id == nil { + return 0, false + } + return *s.Id, true +} + +// HasId returns a boolean if a field has been set. +func (s *SyntheticsUser) HasId() bool { + if s != nil && s.Id != nil { + return true + } + + return false +} + +// SetId allocates a new s.Id and returns the pointer to it. +func (s *SyntheticsUser) SetId(v int) { + s.Id = &v +} + +// GetName returns the Name field if non-nil, zero value otherwise. +func (s *SyntheticsUser) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetNameOk returns a tuple with the Name field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (s *SyntheticsUser) GetNameOk() (string, bool) { + if s == nil || s.Name == nil { + return "", false + } + return *s.Name, true +} + +// HasName returns a boolean if a field has been set. +func (s *SyntheticsUser) HasName() bool { + if s != nil && s.Name != nil { + return true + } + + return false +} + +// SetName allocates a new s.Name and returns the pointer to it. +func (s *SyntheticsUser) SetName(v string) { + s.Name = &v +} + // GetDefault returns the Default field if non-nil, zero value otherwise. func (t *TemplateVariable) GetDefault() string { if t == nil || t.Default == nil { @@ -8755,6 +10026,37 @@ func (t *Time) SetLiveSpan(v string) { t.LiveSpan = &v } +// GetNewStatus returns the NewStatus field if non-nil, zero value otherwise. +func (t *ToggleStatus) GetNewStatus() string { + if t == nil || t.NewStatus == nil { + return "" + } + return *t.NewStatus +} + +// GetNewStatusOk returns a tuple with the NewStatus field if it's non-nil, zero value otherwise +// and a boolean to check if the value has been set. +func (t *ToggleStatus) GetNewStatusOk() (string, bool) { + if t == nil || t.NewStatus == nil { + return "", false + } + return *t.NewStatus, true +} + +// HasNewStatus returns a boolean if a field has been set. +func (t *ToggleStatus) HasNewStatus() bool { + if t != nil && t.NewStatus != nil { + return true + } + + return false +} + +// SetNewStatus allocates a new t.NewStatus and returns the pointer to it. +func (t *ToggleStatus) SetNewStatus(v string) { + t.NewStatus = &v +} + // GetFromTs returns the FromTs field if non-nil, zero value otherwise. func (t *TriggeringValue) GetFromTs() int { if t == nil || t.FromTs == nil { diff --git a/vendor/github.com/zorkian/go-datadog-api/events.go b/vendor/github.com/zorkian/go-datadog-api/events.go index 0aeedef16f..47e3ebfc5a 100644 --- a/vendor/github.com/zorkian/go-datadog-api/events.go +++ b/vendor/github.com/zorkian/go-datadog-api/events.go @@ -60,7 +60,7 @@ func (client *Client) GetEvent(id int) (*Event, error) { return out.Event, nil } -// QueryEvents returns a slice of events from the query stream. +// GetEvents returns a slice of events from the query stream. func (client *Client) GetEvents(start, end int, priority, sources, tags string) ([]Event, error) { // Since this is a GET request, we need to build a query string. diff --git a/vendor/github.com/zorkian/go-datadog-api/helpers.go b/vendor/github.com/zorkian/go-datadog-api/helpers.go index e25d51628c..f57d413b9b 100644 --- a/vendor/github.com/zorkian/go-datadog-api/helpers.go +++ b/vendor/github.com/zorkian/go-datadog-api/helpers.go @@ -28,7 +28,7 @@ func GetBool(v *bool) (bool, bool) { // to store v and returns a pointer to it. func Int(v int) *int { return &v } -// GetInt is a helper routine that returns a boolean representing +// GetIntOk is a helper routine that returns a boolean representing // if a value was set, and if so, dereferences the pointer to it. func GetIntOk(v *int) (int, bool) { if v != nil { @@ -42,7 +42,7 @@ func GetIntOk(v *int) (int, bool) { // to store v and returns a pointer to it. func String(v string) *string { return &v } -// GetString is a helper routine that returns a boolean representing +// GetStringOk is a helper routine that returns a boolean representing // if a value was set, and if so, dereferences the pointer to it. func GetStringOk(v *string) (string, bool) { if v != nil { @@ -56,7 +56,7 @@ func GetStringOk(v *string) (string, bool) { // to store v and returns a pointer to it. func JsonNumber(v json.Number) *json.Number { return &v } -// GetJsonNumber is a helper routine that returns a boolean representing +// GetJsonNumberOk is a helper routine that returns a boolean representing // if a value was set, and if so, dereferences the pointer to it. func GetJsonNumberOk(v *json.Number) (json.Number, bool) { if v != nil { diff --git a/vendor/github.com/zorkian/go-datadog-api/monitors.go b/vendor/github.com/zorkian/go-datadog-api/monitors.go index a30e41caaa..435f911d38 100644 --- a/vendor/github.com/zorkian/go-datadog-api/monitors.go +++ b/vendor/github.com/zorkian/go-datadog-api/monitors.go @@ -140,7 +140,7 @@ func (client *Client) GetMonitor(id int) (*Monitor, error) { return &out, nil } -// GetMonitor retrieves monitors by name +// GetMonitorsByName retrieves monitors by name func (self *Client) GetMonitorsByName(name string) ([]Monitor, error) { var out reqMonitors query, err := url.ParseQuery(fmt.Sprintf("name=%v", name)) @@ -155,7 +155,7 @@ func (self *Client) GetMonitorsByName(name string) ([]Monitor, error) { return out.Monitors, nil } -// GetMonitor retrieves monitors by a slice of tags +// GetMonitorsByTags retrieves monitors by a slice of tags func (self *Client) GetMonitorsByTags(tags []string) ([]Monitor, error) { var out reqMonitors query, err := url.ParseQuery(fmt.Sprintf("monitor_tags=%v", strings.Join(tags, ","))) diff --git a/vendor/github.com/zorkian/go-datadog-api/synthetics.go b/vendor/github.com/zorkian/go-datadog-api/synthetics.go new file mode 100644 index 0000000000..e0eacc8122 --- /dev/null +++ b/vendor/github.com/zorkian/go-datadog-api/synthetics.go @@ -0,0 +1,197 @@ +package datadog + +import ( + "fmt" + "net/url" +) + +// SyntheticsTest represents a synthetics test, either api or browser +type SyntheticsTest struct { + PublicId *string `json:"public_id,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + Tags []string `json:"tags"` + CreatedAt *string `json:"created_at,omitempty"` + ModifiedAt *string `json:"modified_at,omitempty"` + DeletedAt *string `json:"deleted_at,omitempty"` + Config *SyntheticsConfig `json:"config,omitempty"` + Message *string `json:"message,omitempty"` + Options *SyntheticsOptions `json:"options,omitempty"` + Locations []string `json:"locations,omitempty"` + CreatedBy *SyntheticsUser `json:"created_by,omitempty"` + ModifiedBy *SyntheticsUser `json:"modified_by,omitempty"` + Status *string `json:"status,omitempty"` + MonitorStatus *string `json:"monitor_status,omitempty"` +} + +type SyntheticsConfig struct { + Request *SyntheticsRequest `json:"request,omitempty"` + Assertions []SyntheticsAssertion `json:"assertions,omitempty"` + Variables []interface{} `json:"variables,omitempty"` +} + +type SyntheticsRequest struct { + Url *string `json:"url,omitempty"` + Method *string `json:"method,omitempty"` + Timeout *int `json:"timeout,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + Body *string `json:"body,omitempty"` +} + +type SyntheticsAssertion struct { + Operator *string `json:"operator,omitempty"` + Property *string `json:"property,omitempty"` + Type *string `json:"type,omitempty"` + // sometimes target is string ( like "text/html; charset=UTF-8" for header content-type ) + // and sometimes target is int ( like 1200 for responseTime, 200 for statusCode ) + Target interface{} `json:"target,omitempty"` +} + +type SyntheticsOptions struct { + TickEvery *int `json:"tick_every,omitempty"` + FollowRedirects *bool `json:"follow_redirects,omitempty"` + MinFailureDuration *int `json:"min_failure_duration,omitempty"` + MinLocationFailed *int `json:"min_location_failed,omitempty"` + DeviceIds []string `json:"device_ids,omitempty"` +} + +type SyntheticsUser struct { + Id *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + Handle *string `json:"handle,omitempty"` +} + +type SyntheticsDevice struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Height *int `json:"height,omitempty"` + Width *int `json:"width,omitempty"` + IsLandscape *bool `json:"isLandscape,omitempty"` + IsMobile *bool `json:"isMobile,omitempty"` + UserAgent *string `json:"userAgent,omitempty"` +} + +type SyntheticsLocation struct { + Id *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + Region *string `json:"region,omitempty"` + IsLandscape *bool `json:"is_active,omitempty"` +} + +type ToggleStatus struct { + NewStatus *string `json:"new_status,omitempty"` +} + +// GetSyntheticsTests get all tests of type API +func (client *Client) GetSyntheticsTests() ([]SyntheticsTest, error) { + var out struct { + SyntheticsTests []SyntheticsTest `json:"tests,omitempty"` + } + if err := client.doJsonRequest("GET", "/v1/synthetics/tests", nil, &out); err != nil { + return nil, err + } + return out.SyntheticsTests, nil +} + +// GetSyntheticsTestsByType get all tests by type (e.g. api or browser) +func (client *Client) GetSyntheticsTestsByType(testType string) ([]SyntheticsTest, error) { + var out struct { + SyntheticsTests []SyntheticsTest `json:"tests,omitempty"` + } + query, err := url.ParseQuery(fmt.Sprintf("type=%v", testType)) + if err != nil { + return nil, err + } + if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/synthetics/tests?%v", query.Encode()), nil, &out); err != nil { + return nil, err + } + return out.SyntheticsTests, nil +} + +// GetSyntheticsTest get test by public id +func (client *Client) GetSyntheticsTest(publicId string) (*SyntheticsTest, error) { + var out SyntheticsTest + if err := client.doJsonRequest("GET", "/v1/synthetics/tests/"+publicId, nil, &out); err != nil { + return nil, err + } + return &out, nil +} + +// CreateSyntheticsTest creates a test +func (client *Client) CreateSyntheticsTest(syntheticsTest *SyntheticsTest) (*SyntheticsTest, error) { + var out SyntheticsTest + if err := client.doJsonRequest("POST", "/v1/synthetics/tests", syntheticsTest, &out); err != nil { + return nil, err + } + return &out, nil +} + +// UpdateSyntheticsTest updates a test +func (client *Client) UpdateSyntheticsTest(publicId string, syntheticsTest *SyntheticsTest) (*SyntheticsTest, error) { + var out SyntheticsTest + if err := client.doJsonRequest("PUT", fmt.Sprintf("/v1/synthetics/tests/%s", publicId), syntheticsTest, &out); err != nil { + return nil, err + } + return &out, nil +} + +// PauseSyntheticsTest set a test status to live +func (client *Client) PauseSyntheticsTest(publicId string) (*bool, error) { + payload := ToggleStatus{NewStatus: String("paused")} + out := Bool(false) + if err := client.doJsonRequest("PUT", fmt.Sprintf("/v1/synthetics/tests/%s/status", publicId), &payload, &out); err != nil { + return nil, err + } + return out, nil +} + +// ResumeSyntheticsTest set a test status to live +func (client *Client) ResumeSyntheticsTest(publicId string) (*bool, error) { + payload := ToggleStatus{NewStatus: String("live")} + out := Bool(false) + if err := client.doJsonRequest("PUT", fmt.Sprintf("/v1/synthetics/tests/%s/status", publicId), &payload, &out); err != nil { + return nil, err + } + return out, nil +} + +// string array of public_id +type DeleteSyntheticsTestsPayload struct { + PublicIds []string `json:"public_ids,omitempty"` +} + +// DeleteSyntheticsTests deletes tests +func (client *Client) DeleteSyntheticsTests(publicIds []string) error { + req := DeleteSyntheticsTestsPayload{ + PublicIds: publicIds, + } + if err := client.doJsonRequest("POST", "/v1/synthetics/tests/delete", req, nil); err != nil { + return err + } + return nil +} + +// GetSyntheticsLocations get all test locations +func (client *Client) GetSyntheticsLocations() ([]SyntheticsLocation, error) { + var out struct { + Locations []SyntheticsLocation `json:"locations,omitempty"` + } + if err := client.doJsonRequest("GET", "/v1/synthetics/locations", nil, &out); err != nil { + return nil, err + } + return out.Locations, nil +} + +// GetSyntheticsBrowserDevices get all test devices (for browser) +func (client *Client) GetSyntheticsBrowserDevices() ([]SyntheticsDevice, error) { + var out struct { + Devices []SyntheticsDevice `json:"devices,omitempty"` + } + + if err := client.doJsonRequest("GET", "/v1/synthetics/browser/devices", nil, &out); err != nil { + return nil, err + } + return out.Devices, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 6f95a705c4..b4e7c4cd27 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -103,6 +103,7 @@ github.com/hashicorp/hil/scanner github.com/hashicorp/logutils # github.com/hashicorp/terraform v0.11.12-beta1.0.20190227065421-fc531f54a878 github.com/hashicorp/terraform/plugin +github.com/hashicorp/terraform/helper/logging github.com/hashicorp/terraform/helper/schema github.com/hashicorp/terraform/helper/validation github.com/hashicorp/terraform/terraform @@ -126,7 +127,6 @@ github.com/hashicorp/terraform/registry/regsrc github.com/hashicorp/terraform/registry/response github.com/hashicorp/terraform/svchost/disco github.com/hashicorp/terraform/helper/config -github.com/hashicorp/terraform/helper/logging github.com/hashicorp/terraform/svchost github.com/hashicorp/terraform/svchost/auth # github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb @@ -177,7 +177,7 @@ github.com/zclconf/go-cty/cty/function/stdlib github.com/zclconf/go-cty/cty/set github.com/zclconf/go-cty/cty/gocty github.com/zclconf/go-cty/cty/json -# github.com/zorkian/go-datadog-api v2.19.0+incompatible +# github.com/zorkian/go-datadog-api v2.19.0+incompatible => github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d github.com/zorkian/go-datadog-api # golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 golang.org/x/crypto/openpgp diff --git a/website/docs/r/synthetics.html.markdown b/website/docs/r/synthetics.html.markdown new file mode 100644 index 0000000000..90aff44c5b --- /dev/null +++ b/website/docs/r/synthetics.html.markdown @@ -0,0 +1,86 @@ +--- +layout: "datadog" +page_title: "Datadog: datadog_synthetics_test" +sidebar_current: "docs-datadog-resource-synthetics_test" +description: |- + Provides a Datadog synthetics resource. This can be used to create and manage synthetics. +--- + +# datadog_synthetics_test + +Provides a Datadog synthetics test resource. This can be used to create and manage Datadog synthetics test. + +## Example Usage + +```hcl +# Create a new Datadog synthetics test on https://www.example.org +resource "datadog_synthetics_test" "foo" { + type = "api" + request { + method = "GET" + url = "https://www.example.org" + } + request_headers { + "Content-Type" = "application/json" + "Authentication" = "Token: 1234566789" + } + assertions = [ + { + type = "statusCode" + operator = "is" + target = "200" + } + ] + locations = [ "aws:eu-central-1" ] + options { + tick_every = 900 + } + name = "updated name" + message = "Notify @pagerduty" + tags = ["foo:bar", "foo", "env:test"] + + paused = false +} +``` + +## Argument Reference + +The following arguments are supported: + +* `type` - (Required) Synthetics test type (api or browser) +* `name` - (Required) Name of Datadog synthetics test +* `message` - (Required) A message to include with notifications for this synthetics test. + Email notifications can be sent to specific users by using the same '@username' notation as events. +* `request` - (Required) + * `method` - (Required) DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + * `url` - (Required) Any url + * `timeout` - (Optional) Any value between 0 and 3600 +* `request_headers` - (Optional) Header name and value map +* `assertions` - (Required) Array of 1 to 10 items, only some combinations of type/operator are valid (please refer to Datadog documentation) + * `type` - (Required) body, header, responseTime, statusCode + * `operator` - (Required) "contains", "doesNotContain", "is", "isNot", "matches", "doesNotMatch", "validates" + * `target` - (Required) Expected string + * `property` - (Optional) +* `options` - (Required) + * `tick_every` - (Required) 900, 1800, 3600, 21600, 43200, 86400, 604800 plus 60 if type=api or 300 if type=browser + * `follow_redirects` - (Optional) true or false + * `min_failure_duration` - (Optional) Grace period during which a synthetics test is allowed to fail before sending notifications + * `min_location_failed` - (Optional) Threshold below which a synthetics test is allowed to fail before sending notifications +* `locations` - (Required) Please refer to Datadog documentation for available locations (e.g. "aws:eu-central-1") +* `device_ids` - (Optional) "laptop_large", "tablet" or "mobile_small" (only available if type=browser) +* `tags` - (Optional) A list of tags to associate with your synthetics test. This can help you categorize and filter tests in the manage synthetics page of the UI. +* `paused` - (Optional) Default is false if type=api and true if type=browser + +## Attributes Reference + +The following attributes are exported: + +* `public_id` - ID of the Datadog synthetics test + +## Import + +Synthetics tests can be imported using their public string ID, e.g. + +``` +$ terraform import datadog_synthetics_test.fizz abc-123-xyz +``` From db2703c4e616133924b67a8ab05445c5974500a8 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Sun, 14 Apr 2019 20:13:35 +0200 Subject: [PATCH 02/22] Fix deviceIds --- datadog/resource_datadog_synthetics_test_.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 46ef8d4632..5ef3487ee4 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -283,7 +283,7 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics if attr, ok := d.GetOk("device_ids"); ok { deviceIds := []string{} for _, s := range attr.([]interface{}) { - deviceIds := append(deviceIds, s.(string)) + deviceIds = append(deviceIds, s.(string)) } options.DeviceIds = deviceIds } From 83e1d83abce7fae0e789085e3c70f41ae1847a10 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Sun, 14 Apr 2019 21:53:45 +0200 Subject: [PATCH 03/22] Remove unecessary call to updateSyntheticsTestLiveness The create/edit web services now accept the status --- datadog/resource_datadog_synthetics_test_.go | 24 +++++--------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 5ef3487ee4..54c17a703a 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -142,9 +142,6 @@ func resourceDatadogSyntheticsTestCreate(d *schema.ResourceData, meta interface{ // the resource is assumed to not be created, and no state is saved. d.SetId(createdSyntheticsTest.GetPublicId()) - // Call resume/pause webservice, because it is a dedicated endpoint apart from classical CRUD operations - updateSyntheticsTestLiveness(d, client) - // Return the read function to ensure the state is reflected in the terraform.state file return resourceDatadogSyntheticsTestRead(d, meta) } @@ -175,9 +172,6 @@ func resourceDatadogSyntheticsTestUpdate(d *schema.ResourceData, meta interface{ return err } - // Call resume/pause webservice, because it is a dedicated endpoint apart from classical CRUD operations - updateSyntheticsTestLiveness(d, client) - // Return the read function to ensure the state is reflected in the terraform.state file return resourceDatadogSyntheticsTestRead(d, meta) } @@ -288,12 +282,18 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics options.DeviceIds = deviceIds } + status := "live" + if d.Get("paused").(bool) == true { + status = "paused" + } + syntheticsTest := datadog.SyntheticsTest{ Name: datadog.String(d.Get("name").(string)), Type: datadog.String(d.Get("type").(string)), Config: &config, Options: &options, Message: datadog.String(d.Get("message").(string)), + Status: datadog.String(status), } if attr, ok := d.GetOk("locations"); ok { @@ -360,18 +360,6 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data d.Set("paused", *syntheticsTest.Status == "paused") } -func updateSyntheticsTestLiveness(d *schema.ResourceData, client *datadog.Client) { - paused, ok := d.GetOk("paused") - if !ok { - return - } - if paused.(bool) { - client.PauseSyntheticsTest(d.Id()) - } else { - client.ResumeSyntheticsTest(d.Id()) - } -} - func newLocalMap(actualMap map[string]interface{}) map[string]string { localMap := make(map[string]string) for k, i := range actualMap { From caae50abe294b4725b3171070e271309e2c92827 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Sun, 14 Apr 2019 21:54:03 +0200 Subject: [PATCH 04/22] Fix setting min_location_failed --- datadog/resource_datadog_synthetics_test_.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 54c17a703a..1b2dd85bf2 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -272,7 +272,7 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics } if attr, ok := d.GetOk("options.min_location_failed"); ok { minLocationFailed, _ := strconv.Atoi(attr.(string)) - options.SetMinFailureDuration(minLocationFailed) + options.SetMinLocationFailed(minLocationFailed) } if attr, ok := d.GetOk("device_ids"); ok { deviceIds := []string{} From 5985eaf19e33564d2925d0772259fd1f2ac85c6f Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Sun, 14 Apr 2019 23:51:45 +0200 Subject: [PATCH 05/22] Proper types for options --- datadog/resource_datadog_synthetics_test_.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 1b2dd85bf2..3ab4aa628f 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -111,9 +111,9 @@ func syntheticsTestOptions() *schema.Schema { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "tick_every": { - Type: schema.TypeInt, - Required: true, + "follow_redirects": { + Type: schema.TypeBool, + Optional: true, }, "min_failure_duration": { Type: schema.TypeInt, @@ -123,6 +123,10 @@ func syntheticsTestOptions() *schema.Schema { Type: schema.TypeInt, Optional: true, }, + "tick_every": { + Type: schema.TypeInt, + Required: true, + }, }, }, } From 4a147cb2f752b0c60640f9ba1c877ab75d8ced14 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 00:12:28 +0200 Subject: [PATCH 06/22] Fix follow_redirects option --- datadog/resource_datadog_synthetics_test_.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 3ab4aa628f..823269a47c 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -267,7 +267,7 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics options.SetTickEvery(tickEvery) } if attr, ok := d.GetOk("options.follow_redirects"); ok { - followRedirects, _ := attr.(bool) + followRedirects := attr.(string) == "1" options.SetFollowRedirects(followRedirects) } if attr, ok := d.GetOk("options.min_failure_duration"); ok { From 247869d059468493043e700e4a8bbe4d7d53fb2c Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 02:48:12 +0200 Subject: [PATCH 07/22] Fix Terraform always seeing a diff if some optional params are not set --- datadog/resource_datadog_synthetics_test_.go | 98 +++++++++++--------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 823269a47c..d6e157ff8c 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -85,7 +85,7 @@ func syntheticsTestRequest() *schema.Schema { Schema: map[string]*schema.Schema{ "method": { Type: schema.TypeString, - Required: true, + Optional: true, }, "url": { Type: schema.TypeString, @@ -98,7 +98,7 @@ func syntheticsTestRequest() *schema.Schema { "timeout": { Type: schema.TypeInt, Optional: true, - Default: 0, + Default: 60, }, }, }, @@ -323,24 +323,32 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data d.Set("type", syntheticsTest.GetType()) actualRequest := syntheticsTest.GetConfig().Request - localRequest := newLocalMap(map[string]interface{}{ - "method": actualRequest.GetMethod(), - "url": actualRequest.GetUrl(), - "body": actualRequest.GetBody(), - "timeout": actualRequest.GetTimeout(), - }) + localRequest := make(map[string]string) + localRequest["url"] = actualRequest.GetUrl() + if actualRequest.HasBody() { + localRequest["body"] = actualRequest.GetBody() + } + if actualRequest.HasMethod() { + localRequest["method"] = actualRequest.GetMethod() + } + if actualRequest.HasTimeout() { + localRequest["timeout"] = convertToString(actualRequest.GetTimeout()) + } d.Set("request", localRequest) d.Set("request_headers", actualRequest.Headers) actualAssertions := syntheticsTest.GetConfig().Assertions localAssertions := []map[string]string{} for _, assertion := range actualAssertions { - localAssertion := newLocalMap(map[string]interface{}{ - "type": assertion.GetType(), - "property": assertion.GetProperty(), - "operator": assertion.GetOperator(), - "target": assertion.Target, - }) + localAssertion := make(map[string]string) + localAssertion["type"] = assertion.GetType() + localAssertion["operator"] = assertion.GetOperator() + if assertion.HasProperty() { + localAssertion["property"] = assertion.GetProperty() + } + if target := assertion.Target; target != nil { + localAssertion["target"] = convertToString(target) + } localAssertions = append(localAssertions, localAssertion) } d.Set("assertions", localAssertions) @@ -350,12 +358,18 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data d.Set("locations", syntheticsTest.Locations) actualOptions := syntheticsTest.GetOptions() - localOptions := newLocalMap(map[string]interface{}{ - "tick_every": actualOptions.GetTickEvery(), - "follow_redirects": actualOptions.GetFollowRedirects(), - "min_failure_duration": actualOptions.GetMinFailureDuration(), - "min_location_failed": actualOptions.GetMinLocationFailed(), - }) + localOptions := make(map[string]string) + localOptions["tick_every"] = strconv.Itoa(actualOptions.GetTickEvery()) + if actualOptions.HasFollowRedirects() { + localOptions["follow_redirects"] = convertToString(actualOptions.GetFollowRedirects()) + } + if actualOptions.HasMinFailureDuration() { + localOptions["min_failure_duration"] = convertToString(actualOptions.GetMinFailureDuration()) + } + if actualOptions.HasMinLocationFailed() { + localOptions["min_location_failed"] = convertToString(actualOptions.GetMinLocationFailed()) + } + d.Set("options", localOptions) d.Set("name", syntheticsTest.GetName()) @@ -364,33 +378,25 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data d.Set("paused", *syntheticsTest.Status == "paused") } -func newLocalMap(actualMap map[string]interface{}) map[string]string { - localMap := make(map[string]string) - for k, i := range actualMap { - var valStr string - switch v := i.(type) { - case bool: - if v { - valStr = "1" - } else { - valStr = "0" - } - case int: - valStr = strconv.Itoa(v) - case float64: - valStr = strconv.FormatFloat(v, 'f', -1, 64) - case string: - valStr = v - default: - // TODO: manage target for JSON body assertions - valStrr, err := json.Marshal(v) - if err == nil { - valStr = string(valStrr) - } +func convertToString(i interface{}) string { + switch v := i.(type) { + case bool: + if v { + return "1" } - if valStr != "" { - localMap[k] = valStr + return "0" + case int: + return strconv.Itoa(v) + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case string: + return v + default: + // TODO: manage target for JSON body assertions + valStrr, err := json.Marshal(v) + if err == nil { + return string(valStrr) } + return "" } - return localMap } From 1fc4c0bf01c1b4a8e8752475a300599a6e89c905 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 08:38:01 +0200 Subject: [PATCH 08/22] Stop assuming some properties are required --- datadog/resource_datadog_synthetics_test_.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index d6e157ff8c..41921dd6d7 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -324,7 +324,6 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data actualRequest := syntheticsTest.GetConfig().Request localRequest := make(map[string]string) - localRequest["url"] = actualRequest.GetUrl() if actualRequest.HasBody() { localRequest["body"] = actualRequest.GetBody() } @@ -334,6 +333,9 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data if actualRequest.HasTimeout() { localRequest["timeout"] = convertToString(actualRequest.GetTimeout()) } + if actualRequest.HasUrl() { + localRequest["url"] = actualRequest.GetUrl() + } d.Set("request", localRequest) d.Set("request_headers", actualRequest.Headers) @@ -341,14 +343,18 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data localAssertions := []map[string]string{} for _, assertion := range actualAssertions { localAssertion := make(map[string]string) - localAssertion["type"] = assertion.GetType() - localAssertion["operator"] = assertion.GetOperator() + if assertion.HasOperator() { + localAssertion["operator"] = assertion.GetOperator() + } if assertion.HasProperty() { localAssertion["property"] = assertion.GetProperty() } if target := assertion.Target; target != nil { localAssertion["target"] = convertToString(target) } + if assertion.HasType() { + localAssertion["type"] = assertion.GetType() + } localAssertions = append(localAssertions, localAssertion) } d.Set("assertions", localAssertions) @@ -359,7 +365,6 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data actualOptions := syntheticsTest.GetOptions() localOptions := make(map[string]string) - localOptions["tick_every"] = strconv.Itoa(actualOptions.GetTickEvery()) if actualOptions.HasFollowRedirects() { localOptions["follow_redirects"] = convertToString(actualOptions.GetFollowRedirects()) } @@ -369,6 +374,9 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data if actualOptions.HasMinLocationFailed() { localOptions["min_location_failed"] = convertToString(actualOptions.GetMinLocationFailed()) } + if actualOptions.HasTickEvery() { + localOptions["tick_every"] = convertToString(actualOptions.GetTickEvery()) + } d.Set("options", localOptions) From 2b7e2742dde6585eb7b8806bf03d46b3a8ba3621 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 09:11:33 +0200 Subject: [PATCH 09/22] In case of 404, actually delete the resource --- datadog/resource_datadog_synthetics_test_.go | 1 + 1 file changed, 1 insertion(+) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 41921dd6d7..9fb951ae81 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -158,6 +158,7 @@ func resourceDatadogSyntheticsTestRead(d *schema.ResourceData, meta interface{}) if strings.Contains(err.Error(), "404 Not Found") { // Delete the resource from the local state since it doesn't exist anymore in the actual state d.SetId("") + return nil } return err } From dcd52c9cb171a0e134102d625ebd111268db7911 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 09:11:58 +0200 Subject: [PATCH 10/22] tags are mandatory, initialize them to an empty array --- datadog/resource_datadog_synthetics_test_.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 9fb951ae81..c65c80ca0a 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -66,7 +66,7 @@ func resourceDatadogSyntheticsTest() *schema.Resource { }, "tags": { Type: schema.TypeList, - Optional: true, + Required: true, Elem: &schema.Schema{Type: schema.TypeString}, }, "paused": { @@ -309,13 +309,13 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics syntheticsTest.Locations = locations } + tags := []string{} if attr, ok := d.GetOk("tags"); ok { - tags := []string{} for _, s := range attr.([]interface{}) { tags = append(tags, s.(string)) } - syntheticsTest.Tags = tags } + syntheticsTest.Tags = tags return &syntheticsTest } From d91c15cdc30b0e5995b68929638508bed0b1f064 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 09:15:53 +0200 Subject: [PATCH 11/22] Mark method as actually required --- datadog/resource_datadog_synthetics_test_.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index c65c80ca0a..4bea695cfa 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -85,7 +85,7 @@ func syntheticsTestRequest() *schema.Schema { Schema: map[string]*schema.Schema{ "method": { Type: schema.TypeString, - Optional: true, + Required: true, }, "url": { Type: schema.TypeString, From bf63d9429145da95d678ddfcf0cff8d20b528fb8 Mon Sep 17 00:00:00 2001 From: Benjamin Toueg Date: Mon, 15 Apr 2019 10:35:09 +0200 Subject: [PATCH 12/22] Change doc --- website/docs/r/synthetics.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/r/synthetics.html.markdown b/website/docs/r/synthetics.html.markdown index 90aff44c5b..a7e1bf0c37 100644 --- a/website/docs/r/synthetics.html.markdown +++ b/website/docs/r/synthetics.html.markdown @@ -39,7 +39,7 @@ resource "datadog_synthetics_test" "foo" { message = "Notify @pagerduty" tags = ["foo:bar", "foo", "env:test"] - paused = false + status = "paused" } ``` @@ -51,8 +51,9 @@ The following arguments are supported: * `name` - (Required) Name of Datadog synthetics test * `message` - (Required) A message to include with notifications for this synthetics test. Email notifications can be sent to specific users by using the same '@username' notation as events. +* `tags` - (Required) A list of tags to associate with your synthetics test. This can help you categorize and filter tests in the manage synthetics page of the UI. * `request` - (Required) - * `method` - (Required) DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + * `method` - (Required) DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT (noop if type=browser) * `url` - (Required) Any url * `timeout` - (Optional) Any value between 0 and 3600 * `request_headers` - (Optional) Header name and value map @@ -68,8 +69,7 @@ The following arguments are supported: * `min_location_failed` - (Optional) Threshold below which a synthetics test is allowed to fail before sending notifications * `locations` - (Required) Please refer to Datadog documentation for available locations (e.g. "aws:eu-central-1") * `device_ids` - (Optional) "laptop_large", "tablet" or "mobile_small" (only available if type=browser) -* `tags` - (Optional) A list of tags to associate with your synthetics test. This can help you categorize and filter tests in the manage synthetics page of the UI. -* `paused` - (Optional) Default is false if type=api and true if type=browser +* `status` - (Optional) "live", "paused" (default is "live" if type=api and "paused" if type=browser) ## Attributes Reference From 27948121ad5f2d345b75b59b96f6dc738a911574 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 10:47:45 +0200 Subject: [PATCH 13/22] =?UTF-8?q?Transform=20status=20into=20a=20string=20?= =?UTF-8?q?=E2=80=9Clive=E2=80=9D/=E2=80=9Cpaused=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- datadog/resource_datadog_synthetics_test_.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_.go b/datadog/resource_datadog_synthetics_test_.go index 4bea695cfa..05a18d9d6b 100644 --- a/datadog/resource_datadog_synthetics_test_.go +++ b/datadog/resource_datadog_synthetics_test_.go @@ -69,9 +69,9 @@ func resourceDatadogSyntheticsTest() *schema.Resource { Required: true, Elem: &schema.Schema{Type: schema.TypeString}, }, - "paused": { - Type: schema.TypeBool, - Optional: true, + "status": { + Type: schema.TypeString, + Required: true, }, }, } @@ -287,18 +287,13 @@ func newSyntheticsTestFromLocalState(d *schema.ResourceData) *datadog.Synthetics options.DeviceIds = deviceIds } - status := "live" - if d.Get("paused").(bool) == true { - status = "paused" - } - syntheticsTest := datadog.SyntheticsTest{ Name: datadog.String(d.Get("name").(string)), Type: datadog.String(d.Get("type").(string)), Config: &config, Options: &options, Message: datadog.String(d.Get("message").(string)), - Status: datadog.String(status), + Status: datadog.String(d.Get("status").(string)), } if attr, ok := d.GetOk("locations"); ok { @@ -383,8 +378,8 @@ func updateSyntheticsTestLocalState(d *schema.ResourceData, syntheticsTest *data d.Set("name", syntheticsTest.GetName()) d.Set("message", syntheticsTest.GetMessage()) + d.Set("status", syntheticsTest.GetStatus()) d.Set("tags", syntheticsTest.Tags) - d.Set("paused", *syntheticsTest.Status == "paused") } func convertToString(i interface{}) string { From f61b66bc7546dd08d9af60edcb827f84abf4786e Mon Sep 17 00:00:00 2001 From: Gabin Marignier Date: Mon, 15 Apr 2019 11:16:28 +0200 Subject: [PATCH 14/22] Update go-datadog-api to latest version --- go.mod | 4 +--- go.sum | 2 ++ .../github.com/hashicorp/terraform/helper/resource/testing.go | 2 +- vendor/modules.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index f66af57d2a..ffd9baeaf9 100644 --- a/go.mod +++ b/go.mod @@ -20,9 +20,7 @@ require ( github.com/posener/complete v1.2.1 // indirect github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa // indirect github.com/zclconf/go-cty v0.0.0-20181017232614-01c5aba823a6 // indirect - github.com/zorkian/go-datadog-api v2.19.0+incompatible + github.com/zorkian/go-datadog-api v2.19.1-0.20190415084127-efa96fedb363+incompatible golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519 // indirect google.golang.org/genproto v0.0.0-20181016170114-94acd270e44e // indirect ) - -replace github.com/zorkian/go-datadog-api => github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d diff --git a/go.sum b/go.sum index 4bca84408f..2342ed09dc 100644 --- a/go.sum +++ b/go.sum @@ -301,6 +301,8 @@ github.com/zclconf/go-cty v0.0.0-20180302160414-49fa5e03c418/go.mod h1:LnDKxj8gN github.com/zclconf/go-cty v0.0.0-20180815031001-58bb2bc0302a/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v0.0.0-20181017232614-01c5aba823a6 h1:Y9SzKuDy2J5QLFPmFk7/ZIzbu4/FrQK9Zwv4vjivNiM= github.com/zclconf/go-cty v0.0.0-20181017232614-01c5aba823a6/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= +github.com/zorkian/go-datadog-api v2.19.1-0.20190415084127-efa96fedb363+incompatible h1:uQBFFHBO8CiSo/Gp4E7vzE6cj2TTtZ/SuGO4nDyCY3g= +github.com/zorkian/go-datadog-api v2.19.1-0.20190415084127-efa96fedb363+incompatible/go.mod h1:PkXwHX9CUQa/FpB9ZwAD45N1uhCW4MT/Wj7m36PbKss= golang.org/x/crypto v0.0.0-20180211211603-9de5f2eaf759/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 h1:gCHhzI+1R9peHIMyiWVxoVaWlk1cYK7VThX5ptLtbXY= golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go index 534230aefe..b97673fdf5 100644 --- a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go +++ b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go @@ -16,7 +16,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/hashicorp/errwrap" - multierror "github.com/hashicorp/go-multierror" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/logutils" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/helper/logging" diff --git a/vendor/modules.txt b/vendor/modules.txt index b4e7c4cd27..b2b316b7ea 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -177,7 +177,7 @@ github.com/zclconf/go-cty/cty/function/stdlib github.com/zclconf/go-cty/cty/set github.com/zclconf/go-cty/cty/gocty github.com/zclconf/go-cty/cty/json -# github.com/zorkian/go-datadog-api v2.19.0+incompatible => github.com/DataDog/go-datadog-api v0.0.0-20190409155204-5497235f061d +# github.com/zorkian/go-datadog-api v2.19.1-0.20190415084127-efa96fedb363+incompatible github.com/zorkian/go-datadog-api # golang.org/x/crypto v0.0.0-20180816225734-aabede6cba87 golang.org/x/crypto/openpgp From 27cb9a404ba84a92ca9e60b5b3eae6e0204bc849 Mon Sep 17 00:00:00 2001 From: Gabin Marignier Date: Mon, 15 Apr 2019 11:40:31 +0200 Subject: [PATCH 15/22] Fix acceptance tests --- .../resource_datadog_synthetics_test_test.go | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index 480272ed6a..29e02ef9ef 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -119,11 +119,9 @@ var createSyntheticsAPITestStep = resource.TestStep{ resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "assertions.3.target", "terraform"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.foo", "locations.#", "2"), + "datadog_synthetics_test.foo", "locations.#", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "locations.0", "aws:eu-central-1"), - resource.TestCheckResourceAttr( - "datadog_synthetics_test.foo", "locations.1", "aws:ap-northeast-1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "options.tick_every", "60"), resource.TestCheckResourceAttr( @@ -137,7 +135,7 @@ var createSyntheticsAPITestStep = resource.TestStep{ resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "tags.1", "baz"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.foo", "paused", "true"), + "datadog_synthetics_test.foo", "status", "paused"), ), } @@ -180,18 +178,18 @@ resource "datadog_synthetics_test" "foo" { } ] - locations = [ "aws:eu-central-1", "aws:ap-northeast-1" ] + locations = [ "aws:eu-central-1" ] options { tick_every = 60 min_failure_duration = 0 - min_location_failed = 0 + min_location_failed = 1 } name = "name for synthetics test foo" message = "Notify @datadog.user" tags = ["foo:bar", "baz"] - paused = true + status = "paused" } ` @@ -234,7 +232,7 @@ var updateSyntheticsAPITestStep = resource.TestStep{ resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "tags.2", "env:test"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.foo", "paused", "true"), + "datadog_synthetics_test.foo", "status", "live"), ), } @@ -260,15 +258,15 @@ resource "datadog_synthetics_test" "foo" { options { tick_every = 900 - min_failure_duration = 0 - min_location_failed = 0 + min_failure_duration = 10 + min_location_failed = 1 } name = "updated name" message = "Notify @pagerduty" tags = ["foo:bar", "foo", "env:test"] - paused = true + status = "live" } ` @@ -293,19 +291,17 @@ var createSyntheticsBrowserTestStep = resource.TestStep{ resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "request_headers.X-Datadog-Trace-ID", "123456789"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "devices.#", "2"), + "datadog_synthetics_test.bar", "device_ids.#", "2"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "devices.0", "laptop_large"), + "datadog_synthetics_test.bar", "device_ids.0", "laptop_large"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "devices.1", "mobile_small"), + "datadog_synthetics_test.bar", "device_ids.1", "mobile_small"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "assertions.#", "0"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "locations.#", "2"), + "datadog_synthetics_test.bar", "locations.#", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "locations.0", "aws:eu-central-1"), - resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "locations.1", "aws:ap-northeast-1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "options.tick_every", "900"), resource.TestCheckResourceAttr( @@ -336,19 +332,19 @@ resource "datadog_synthetics_test" "bar" { "X-Datadog-Trace-ID" = "123456789" } - devices = [ "laptop_large", "mobile_small" ] - locations = [ "aws:eu-central-1", "aws:ap-northeast-1" ] + device_ids = [ "laptop_large", "mobile_small" ] + locations = [ "aws:eu-central-1" ] options { tick_every = 900 min_failure_duration = 0 - min_location_failed = 0 + min_location_failed = 1 } name = "name for synthetics browser test bar" message = "Notify @datadog.user" tags = ["foo:bar", "baz"] - paused = true + status = "paused" } ` From c4064043187da6a9ae2471a33075fc0299d2f0a7 Mon Sep 17 00:00:00 2001 From: Gabin Marignier Date: Mon, 15 Apr 2019 11:57:54 +0200 Subject: [PATCH 16/22] Add acceptance test for updated browser tests --- .../resource_datadog_synthetics_test_test.go | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index 29e02ef9ef..5d3f90e6c0 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -80,6 +80,18 @@ func TestAccDatadogSyntheticsBrowserTest_Basic(t *testing.T) { }) } +func TestAccDatadogSyntheticsBrowserTest_Updated(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testSyntheticsTestIsDestroyed, + Steps: []resource.TestStep{ + createSyntheticsBrowserTestStep, + updateSyntheticsBrowserTestStep, + }, + }) +} + var createSyntheticsAPITestStep = resource.TestStep{ Config: createSyntheticsAPITestConfig, Check: resource.ComposeTestCheckFunc( @@ -348,6 +360,84 @@ resource "datadog_synthetics_test" "bar" { } ` +var updateSyntheticsBrowserTestStep = resource.TestStep{ + Config: updateSyntheticsBrowserTestConfig, + Check: resource.ComposeTestCheckFunc( + testSyntheticsTestExists(), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "type", "browser"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.method", "PUT"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.url", "https://docs.datadoghq.com"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.body", "this is an updated body"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request.timeout", "60"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.%", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.Accept", "application/xml"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "request_headers.X-Datadog-Trace-ID", "987654321"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "device_ids.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "device_ids.0", "laptop_large"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "device_ids.1", "tablet"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "assertions.#", "0"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "locations.#", "1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "locations.0", "aws:eu-central-1"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.tick_every", "300"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "name", "updated name for synthetics browser test bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "message", "Notify @pagerduty"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.#", "2"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.0", "foo:bar"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "tags.1", "buz"), + ), +} + +const updateSyntheticsBrowserTestConfig = ` +resource "datadog_synthetics_test" "bar" { + type = "browser" + + request { + method = "PUT" + url = "https://docs.datadoghq.com" + body = "this is an updated body" + timeout = 60 + } + request_headers { + "Accept" = "application/xml" + "X-Datadog-Trace-ID" = "987654321" + } + + device_ids = [ "laptop_large", "tablet" ] + locations = [ "aws:eu-central-1" ] + options { + tick_every = 300 + min_failure_duration = 10 + min_location_failed = 1 + } + + name = "updated name for synthetics browser test bar" + message = "Notify @pagerduty" + tags = ["foo:bar", "buz"] + + status = "live" +} +` + func testSyntheticsTestExists() resource.TestCheckFunc { return func(s *terraform.State) error { client := testAccProvider.Meta().(*datadog.Client) From 1acddc5a4148dc472b5abc07e2d3ca4e2b7e02d8 Mon Sep 17 00:00:00 2001 From: Gabin Marignier Date: Mon, 15 Apr 2019 12:09:47 +0200 Subject: [PATCH 17/22] Add more tests for options --- .../resource_datadog_synthetics_test_test.go | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index 5d3f90e6c0..a1b5c7c7aa 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -136,6 +136,10 @@ var createSyntheticsAPITestStep = resource.TestStep{ "datadog_synthetics_test.foo", "locations.0", "aws:eu-central-1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "options.tick_every", "60"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.min_failure_duration", "0"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.min_location_failed", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "name", "name for synthetics test foo"), resource.TestCheckResourceAttr( @@ -231,6 +235,10 @@ var updateSyntheticsAPITestStep = resource.TestStep{ "datadog_synthetics_test.foo", "locations.0", "aws:eu-central-1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "options.tick_every", "900"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.min_failure_duration", "10"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.foo", "options.min_location_failed", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.foo", "name", "updated name"), resource.TestCheckResourceAttr( @@ -316,6 +324,10 @@ var createSyntheticsBrowserTestStep = resource.TestStep{ "datadog_synthetics_test.bar", "locations.0", "aws:eu-central-1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "options.tick_every", "900"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.min_failure_duration", "0"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.min_location_failed", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "name", "name for synthetics browser test bar"), resource.TestCheckResourceAttr( @@ -393,7 +405,11 @@ var updateSyntheticsBrowserTestStep = resource.TestStep{ resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "locations.0", "aws:eu-central-1"), resource.TestCheckResourceAttr( - "datadog_synthetics_test.bar", "options.tick_every", "300"), + "datadog_synthetics_test.bar", "options.tick_every", "1800"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.min_failure_duration", "10"), + resource.TestCheckResourceAttr( + "datadog_synthetics_test.bar", "options.min_location_failed", "1"), resource.TestCheckResourceAttr( "datadog_synthetics_test.bar", "name", "updated name for synthetics browser test bar"), resource.TestCheckResourceAttr( @@ -425,7 +441,7 @@ resource "datadog_synthetics_test" "bar" { device_ids = [ "laptop_large", "tablet" ] locations = [ "aws:eu-central-1" ] options { - tick_every = 300 + tick_every = 1800 min_failure_duration = 10 min_location_failed = 1 } From 1ec258ff2b5c7e6869c56ae9c7831978eef9bee0 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 12:21:42 +0200 Subject: [PATCH 18/22] Consistent tabs/spaces in tests --- .../resource_datadog_synthetics_test_test.go | 106 +++++++++--------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index a1b5c7c7aa..40e0630f5c 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -157,10 +157,10 @@ var createSyntheticsAPITestStep = resource.TestStep{ const createSyntheticsAPITestConfig = ` resource "datadog_synthetics_test" "foo" { - type = "api" + type = "api" - request { - method = "GET" + request { + method = "GET" url = "https://www.datadoghq.com" body = "this is a body" timeout = 30 @@ -170,27 +170,27 @@ resource "datadog_synthetics_test" "foo" { "X-Datadog-Trace-ID" = "1234566789" } - assertions = [ - { + assertions = [ + { type = "header" property = "content-type" - operator = "contains" + operator = "contains" target = "application/json" }, - { - type = "statusCode" - operator = "is" - target = "200" - }, - { - type = "responseTime" - operator = "lessThan" + { + type = "statusCode" + operator = "is" + target = "200" + }, + { + type = "responseTime" + operator = "lessThan" target = "2000" }, - { - type = "body" - operator = "doesNotContain" - target = "terraform" + { + type = "body" + operator = "doesNotContain" + target = "terraform" } ] @@ -258,33 +258,33 @@ var updateSyntheticsAPITestStep = resource.TestStep{ const updateSyntheticsAPITestConfig = ` resource "datadog_synthetics_test" "foo" { - type = "api" + type = "api" - request { + request { method = "GET" url = "https://docs.datadoghq.com" timeout = 60 - } + } - assertions = [ - { - type = "statusCode" - operator = "isNot" - target = "500" - } - ] + assertions = [ + { + type = "statusCode" + operator = "isNot" + target = "500" + } + ] - locations = [ "aws:eu-central-1" ] + locations = [ "aws:eu-central-1" ] - options { + options { tick_every = 900 min_failure_duration = 10 - min_location_failed = 1 - } + min_location_failed = 1 + } - name = "updated name" - message = "Notify @pagerduty" - tags = ["foo:bar", "foo", "env:test"] + name = "updated name" + message = "Notify @pagerduty" + tags = ["foo:bar", "foo", "env:test"] status = "live" } @@ -343,10 +343,10 @@ var createSyntheticsBrowserTestStep = resource.TestStep{ const createSyntheticsBrowserTestConfig = ` resource "datadog_synthetics_test" "bar" { - type = "browser" + type = "browser" - request { - method = "GET" + request { + method = "GET" url = "https://www.datadoghq.com" body = "this is a body" timeout = 30 @@ -357,15 +357,15 @@ resource "datadog_synthetics_test" "bar" { } device_ids = [ "laptop_large", "mobile_small" ] - locations = [ "aws:eu-central-1" ] - options { + locations = [ "aws:eu-central-1" ] + options { tick_every = 900 min_failure_duration = 0 min_location_failed = 1 - } + } - name = "name for synthetics browser test bar" - message = "Notify @datadog.user" + name = "name for synthetics browser test bar" + message = "Notify @datadog.user" tags = ["foo:bar", "baz"] status = "paused" @@ -425,10 +425,9 @@ var updateSyntheticsBrowserTestStep = resource.TestStep{ const updateSyntheticsBrowserTestConfig = ` resource "datadog_synthetics_test" "bar" { - type = "browser" - - request { - method = "PUT" + type = "browser" + request { + method = "PUT" url = "https://docs.datadoghq.com" body = "this is an updated body" timeout = 60 @@ -437,19 +436,16 @@ resource "datadog_synthetics_test" "bar" { "Accept" = "application/xml" "X-Datadog-Trace-ID" = "987654321" } - device_ids = [ "laptop_large", "tablet" ] - locations = [ "aws:eu-central-1" ] - options { + locations = [ "aws:eu-central-1" ] + options { tick_every = 1800 min_failure_duration = 10 min_location_failed = 1 - } - - name = "updated name for synthetics browser test bar" - message = "Notify @pagerduty" + } + name = "updated name for synthetics browser test bar" + message = "Notify @pagerduty" tags = ["foo:bar", "buz"] - status = "live" } ` From 88254977986eac868cf51814dabfc754502aaba2 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 12:23:57 +0200 Subject: [PATCH 19/22] Consistent tabs/spaces in tests --- .../resource_datadog_synthetics_test_test.go | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index 40e0630f5c..66360b68e1 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -192,20 +192,20 @@ resource "datadog_synthetics_test" "foo" { operator = "doesNotContain" target = "terraform" } - ] + ] - locations = [ "aws:eu-central-1" ] - options { + locations = [ "aws:eu-central-1" ] + options { tick_every = 60 min_failure_duration = 0 min_location_failed = 1 - } + } - name = "name for synthetics test foo" - message = "Notify @datadog.user" - tags = ["foo:bar", "baz"] + name = "name for synthetics test foo" + message = "Notify @datadog.user" + tags = ["foo:bar", "baz"] - status = "paused" + status = "paused" } ` @@ -261,16 +261,16 @@ resource "datadog_synthetics_test" "foo" { type = "api" request { - method = "GET" + method = "GET" url = "https://docs.datadoghq.com" timeout = 60 } assertions = [ - { - type = "statusCode" - operator = "isNot" - target = "500" + { + type = "statusCode" + operator = "isNot" + target = "500" } ] From e53784938b0f68c11c22079f6637880a8d183300 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 12:26:00 +0200 Subject: [PATCH 20/22] Consistent tabs/spaces in tests --- datadog/resource_datadog_synthetics_test_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/datadog/resource_datadog_synthetics_test_test.go b/datadog/resource_datadog_synthetics_test_test.go index 66360b68e1..74436024c6 100644 --- a/datadog/resource_datadog_synthetics_test_test.go +++ b/datadog/resource_datadog_synthetics_test_test.go @@ -178,19 +178,19 @@ resource "datadog_synthetics_test" "foo" { target = "application/json" }, { - type = "statusCode" - operator = "is" - target = "200" + type = "statusCode" + operator = "is" + target = "200" }, { - type = "responseTime" - operator = "lessThan" + type = "responseTime" + operator = "lessThan" target = "2000" }, { - type = "body" - operator = "doesNotContain" - target = "terraform" + type = "body" + operator = "doesNotContain" + target = "terraform" } ] From 7f762039ed6156a4ed78cd8d0a9e48f4b2f77b00 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 12:32:04 +0200 Subject: [PATCH 21/22] Update documentation --- website/docs/r/synthetics.html.markdown | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/website/docs/r/synthetics.html.markdown b/website/docs/r/synthetics.html.markdown index a7e1bf0c37..1ae019b17f 100644 --- a/website/docs/r/synthetics.html.markdown +++ b/website/docs/r/synthetics.html.markdown @@ -17,7 +17,7 @@ Provides a Datadog synthetics test resource. This can be used to create and mana resource "datadog_synthetics_test" "foo" { type = "api" request { - method = "GET" + method = "GET" url = "https://www.example.org" } request_headers { @@ -29,11 +29,11 @@ resource "datadog_synthetics_test" "foo" { type = "statusCode" operator = "is" target = "200" - } + } ] locations = [ "aws:eu-central-1" ] options { - tick_every = 900 + tick_every = 900 } name = "updated name" message = "Notify @pagerduty" @@ -47,35 +47,35 @@ resource "datadog_synthetics_test" "foo" { The following arguments are supported: -* `type` - (Required) Synthetics test type (api or browser) -* `name` - (Required) Name of Datadog synthetics test -* `message` - (Required) A message to include with notifications for this synthetics test. - Email notifications can be sent to specific users by using the same '@username' notation as events. -* `tags` - (Required) A list of tags to associate with your synthetics test. This can help you categorize and filter tests in the manage synthetics page of the UI. -* `request` - (Required) - * `method` - (Required) DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT (noop if type=browser) - * `url` - (Required) Any url - * `timeout` - (Optional) Any value between 0 and 3600 -* `request_headers` - (Optional) Header name and value map -* `assertions` - (Required) Array of 1 to 10 items, only some combinations of type/operator are valid (please refer to Datadog documentation) - * `type` - (Required) body, header, responseTime, statusCode - * `operator` - (Required) "contains", "doesNotContain", "is", "isNot", "matches", "doesNotMatch", "validates" - * `target` - (Required) Expected string - * `property` - (Optional) -* `options` - (Required) - * `tick_every` - (Required) 900, 1800, 3600, 21600, 43200, 86400, 604800 plus 60 if type=api or 300 if type=browser - * `follow_redirects` - (Optional) true or false - * `min_failure_duration` - (Optional) Grace period during which a synthetics test is allowed to fail before sending notifications - * `min_location_failed` - (Optional) Threshold below which a synthetics test is allowed to fail before sending notifications -* `locations` - (Required) Please refer to Datadog documentation for available locations (e.g. "aws:eu-central-1") -* `device_ids` - (Optional) "laptop_large", "tablet" or "mobile_small" (only available if type=browser) -* `status` - (Optional) "live", "paused" (default is "live" if type=api and "paused" if type=browser) +- `type` - (Required) Synthetics test type (api or browser) +- `name` - (Required) Name of Datadog synthetics test +- `message` - (Required) A message to include with notifications for this synthetics test. + Email notifications can be sent to specific users by using the same '@username' notation as events. +- `tags` - (Required) A list of tags to associate with your synthetics test. This can help you categorize and filter tests in the manage synthetics page of the UI. +- `request` - (Required) + - `method` - (Required) DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT (noop if type=browser) + - `url` - (Required) Any url + - `timeout` - (Optional) For typ=api, any value between 0 and 60. No-op for type=browser +- `request_headers` - (Optional) Header name and value map +- `assertions` - (Required) Array of 1 to 10 items, only some combinations of type/operator are valid (please refer to Datadog documentation) + - `type` - (Required) body, header, responseTime, statusCode + - `operator` - (Required) "contains", "doesNotContain", "is", "isNot", "matches", "doesNotMatch", "validates" + - `target` - (Required) Expected string + - `property` - (Optional) +- `options` - (Required) + - `tick_every` - (Required) 900, 1800, 3600, 21600, 43200, 86400, 604800 plus 60 if type=api or 300 if type=browser + - `follow_redirects` - (Optional) true or false + - `min_failure_duration` - (Optional) Grace period during which a synthetics test is allowed to fail before sending notifications + - `min_location_failed` - (Optional) Threshold below which a synthetics test is allowed to fail before sending notifications +- `locations` - (Required) Please refer to Datadog documentation for available locations (e.g. "aws:eu-central-1") +- `device_ids` - (Optional) "laptop_large", "tablet" or "mobile_small" (only available if type=browser) +- `status` - (Required) "live", "paused" ## Attributes Reference The following attributes are exported: -* `public_id` - ID of the Datadog synthetics test +- `public_id` - ID of the Datadog synthetics test ## Import From 57ab95bb95423ebc85a1dd2a42e583a1589c6d21 Mon Sep 17 00:00:00 2001 From: Tanguy Le Barzic Date: Mon, 15 Apr 2019 12:37:23 +0200 Subject: [PATCH 22/22] Add an example of a browser test --- website/docs/r/synthetics.html.markdown | 27 +++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/website/docs/r/synthetics.html.markdown b/website/docs/r/synthetics.html.markdown index 1ae019b17f..4201028325 100644 --- a/website/docs/r/synthetics.html.markdown +++ b/website/docs/r/synthetics.html.markdown @@ -13,7 +13,7 @@ Provides a Datadog synthetics test resource. This can be used to create and mana ## Example Usage ```hcl -# Create a new Datadog synthetics test on https://www.example.org +# Create a new Datadog Synthetics API test on https://www.example.org resource "datadog_synthetics_test" "foo" { type = "api" request { @@ -35,10 +35,33 @@ resource "datadog_synthetics_test" "foo" { options { tick_every = 900 } - name = "updated name" + name = "An API test on example.org" message = "Notify @pagerduty" tags = ["foo:bar", "foo", "env:test"] + status = "live" +} + +# Create a new Datadog Synthetics Browser test starting on https://www.example.org +resource "datadog_synthetics_test" "bar" { + type = "browser" + + request { + method = "GET" + url = "https://app.datadoghq.com" + } + + device_ids = ["laptop_large"] + locations = ["aws:eu-central-1"] + + options { + tick_every = 3600 + } + + name = "A Browser test on example.org" + message = "Notify @qa" + tags = [] + status = "paused" } ```