Skip to content

Commit

Permalink
add observatory scheduled test resource
Browse files Browse the repository at this point in the history
  • Loading branch information
broswen committed Sep 29, 2023
1 parent efe362c commit 30b1384
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .changelog/2807.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
cloudflare_observatory_scheduled_test
```
53 changes: 53 additions & 0 deletions docs/resources/observatory_scheduled_test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
page_title: "cloudflare_observatory_scheduled_test Resource - Cloudflare"
subcategory: ""
description: |-
Provides a Cloudflare Observatory Scheduled Test resource.
---

# cloudflare_observatory_scheduled_test (Resource)

Provides a Cloudflare Observatory Scheduled Test resource.

## Example Usage

```terraform
resource "cloudflare_observatory_scheduled_test" "example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
url = "example.com"
region = "us-central1"
frequency = "WEEKLY"
}
```
<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `frequency` (String) The frequency to run the test. Available values: `DAILY`, `WEEKLY`. **Modifying this attribute will force creation of a new resource.**
- `region` (String) The region to run the test in. Available values: `us-central1`, `us-east1`, `us-east4`, `us-south1`, `us-west1`, `southamerica-east1`, `europe-north1`, `europe-southwest1`, `europe-west1`, `europe-west2`, `europe-west3`, `europe-west4`, `europe-west8`, `europe-west9`, `asia-east1`, `asia-southeast1`, `me-west1`, `australia-southeast1`. **Modifying this attribute will force creation of a new resource.**
- `url` (String) The page to run the test on. **Modifying this attribute will force creation of a new resource.**
- `zone_id` (String) The zone identifier to target for the resource. **Modifying this attribute will force creation of a new resource.**

### Optional

- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- `create` (String)

## Import

Import is supported using the following syntax:

```shell
$ terraform import cloudflare_observatory_scheduled_test.example <zone_id>:<url>:<region>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import cloudflare_observatory_scheduled_test.example <zone_id>:<url>:<region>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "cloudflare_observatory_scheduled_test" "example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
url = "example.com"
region = "us-central1"
frequency = "WEEKLY"
}

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.20

require (
github.com/agext/levenshtein v1.2.3 // indirect
github.com/cloudflare/cloudflare-go v0.77.0
github.com/cloudflare/cloudflare-go v0.78.0
github.com/fatih/color v1.13.0 // indirect
github.com/google/uuid v1.3.1
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZ
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/cloudflare-go v0.77.0 h1:bVUGkSKdXEz8+u2Yj3ASqZsqlcsPkeB+PDqVs9OE7TY=
github.com/cloudflare/cloudflare-go v0.77.0/go.mod h1:R+Q/Im0G0MzKJxj3eXOBBE8xpnchVA9tSiQwOEvfW4Y=
github.com/cloudflare/cloudflare-go v0.78.0 h1:xMPdjJ+e2tGNUkw5LyduPlsMCaILEoN1Kqq/uEMx78w=
github.com/cloudflare/cloudflare-go v0.78.0/go.mod h1:R+Q/Im0G0MzKJxj3eXOBBE8xpnchVA9tSiQwOEvfW4Y=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
5 changes: 3 additions & 2 deletions internal/sdkv2provider/data_source_account_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import (
"fmt"

"github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
)

func dataSourceCloudflareAccountRolesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
accountID := d.Get(consts.AccountIDSchemaKey).(string)

tflog.Debug(ctx, fmt.Sprintf("Reading Account Roles"))
roles, err := client.AccountRoles(ctx, accountID)
roles, err := client.ListAccountRoles(ctx, cloudflare.AccountIdentifier(accountID), cloudflare.ListAccountRolesParams{})
if err != nil {
return diag.FromErr(fmt.Errorf("error listing Account Roles: %w", err))
}
Expand Down
1 change: 1 addition & 0 deletions internal/sdkv2provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func New(version string) func() *schema.Provider {
"cloudflare_mtls_certificate": resourceCloudflareMTLSCertificate(),
"cloudflare_notification_policy_webhooks": resourceCloudflareNotificationPolicyWebhook(),
"cloudflare_notification_policy": resourceCloudflareNotificationPolicy(),
"cloudflare_observatory_scheduled_test": resourceCloudflareObservatoryScheduledTest(),
"cloudflare_origin_ca_certificate": resourceCloudflareOriginCACertificate(),
"cloudflare_page_rule": resourceCloudflarePageRule(),
"cloudflare_pages_domain": resourceCloudflarePagesDomain(),
Expand Down
5 changes: 3 additions & 2 deletions internal/sdkv2provider/resource_cloudflare_account_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (

"github.com/MakeNowJust/heredoc/v2"
cloudflare "github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
)

func resourceCloudflareAccountMember() *schema.Resource {
Expand Down Expand Up @@ -106,7 +107,7 @@ func resourceCloudflareAccountMemberUpdate(ctx context.Context, d *schema.Resour
accountID := d.Get(consts.AccountIDSchemaKey).(string)

for _, r := range memberRoles {
accountRole, _ := client.AccountRole(ctx, accountID, r.(string))
accountRole, _ := client.GetAccountRole(ctx, cloudflare.AccountIdentifier(accountID), r.(string))
accountRoles = append(accountRoles, accountRole)
}

Expand Down
125 changes: 125 additions & 0 deletions internal/sdkv2provider/resource_cloudflare_observatory_scheduled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package sdkv2provider

import (
"context"
"errors"
"fmt"
"strings"
"time"

cloudflare "github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
)

func resourceCloudflareObservatoryScheduledTest() *schema.Resource {
return &schema.Resource{
Schema: resourceCloudflareObservatoryScheduledTestSchema(),

CreateContext: resourceCloudflareObservatoryScheduledTestCreate,
ReadContext: resourceCloudflareObservatoryScheduledTestRead,
DeleteContext: resourceCloudflareObservatoryScheduledTestDelete,
Importer: &schema.ResourceImporter{
StateContext: resourceCloudflareObservatoryScheduledTestImport,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(30 * time.Second),
},
Description: "Provides a Cloudflare Observatory Scheduled Test resource.",
}
}

func resourceCloudflareObservatoryScheduledTestCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

params := cloudflare.CreateObservatoryScheduledPageTestParams{
URL: d.Get("url").(string),
Region: d.Get("region").(string),
Frequency: d.Get("frequency").(string),
}
test, err := client.CreateObservatoryScheduledPageTest(ctx, cloudflare.ZoneIdentifier(zoneID), params)

if err != nil {
return diag.FromErr(fmt.Errorf("error creating observatory scheduled test %q: %w", d.Id(), err))
}

d.SetId(fmt.Sprintf("%s:%s", test.Schedule.URL, test.Schedule.Region))

return resourceCloudflareObservatoryScheduledTestRead(ctx, d, meta)
}

func resourceCloudflareObservatoryScheduledTestRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

schedule, err := client.GetObservatoryScheduledPageTest(ctx, cloudflare.ZoneIdentifier(zoneID), cloudflare.GetObservatoryScheduledPageTestParams{
URL: d.Get("url").(string),
Region: d.Get("region").(string),
})
if err != nil {
var notFoundError *cloudflare.NotFoundError
if errors.As(err, &notFoundError) {
tflog.Warn(ctx, fmt.Sprintf("Removing observatory scheduled test from state because it's not found in API"))
d.SetId("")
return nil
}
return diag.FromErr(fmt.Errorf("error getting observatory scheduled test %q: %w", d.Id(), err))
}
d.SetId(fmt.Sprintf("%s:%s", schedule.URL, schedule.Region))
d.Set("url", schedule.URL)
d.Set("region", schedule.Region)
d.Set("frequency", schedule.Frequency)
return nil
}

func resourceCloudflareObservatoryScheduledTestDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

_, err := client.DeleteObservatoryScheduledPageTest(ctx, cloudflare.ZoneIdentifier(zoneID), cloudflare.DeleteObservatoryScheduledPageTestParams{
URL: d.Get("url").(string),
Region: d.Get("region").(string),
})

if err != nil {
return diag.FromErr(fmt.Errorf("error deleting observatory scheduled test %q: %w", d.Id(), err))
}

return nil
}

func resourceCloudflareObservatoryScheduledTestImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client := meta.(*cloudflare.API)
idAttr := strings.SplitN(d.Id(), ":", 3)
var zoneID string
var url string
var region string
if len(idAttr) == 3 {
zoneID = idAttr[0]
url = idAttr[1]
region = idAttr[2]
} else {
return nil, fmt.Errorf("invalid id (\"%s\") specified, should be in format \"zoneID:url:region\" for import", d.Id())
}

schedule, err := client.GetObservatoryScheduledPageTest(ctx, cloudflare.ZoneIdentifier(zoneID), cloudflare.GetObservatoryScheduledPageTestParams{
URL: url,
Region: region,
})
if err != nil {
return nil, fmt.Errorf("failed to fetch web analytics site: %s", url)
}

d.SetId(fmt.Sprintf("%s:%s", schedule.URL, schedule.Region))
d.Set(consts.ZoneIDSchemaKey, zoneID)
d.Set("url", schedule.URL)
d.Set("region", schedule.Region)
d.Set("frequency", schedule.Frequency)

return []*schema.ResourceData{d}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package sdkv2provider

import (
"context"
"fmt"
"os"
"testing"

cloudflare "github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

func TestAccCloudflareObservatoryScheduledTest_Create(t *testing.T) {
t.Parallel()
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
domain := os.Getenv("CLOUDFLARE_DOMAIN")
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_observatory_scheduled_test.%s", rnd)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckCloudflareWaitingRoomDestroy,
Steps: []resource.TestStep{
{
Config: testAccCloudflareObservatoryScheduledTest(rnd, zoneID, domain),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(name, "url", domain),
resource.TestCheckResourceAttr(name, "region", "us-central1"),
resource.TestCheckResourceAttr(name, "frequency", "DAILY"),
),
},
},
})
}

func testAccCheckCloudflareObservatoryScheduledTestDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*cloudflare.API)

for _, rs := range s.RootModule().Resources {
if rs.Type != "cloudflare_observatory_scheduled_test" {
continue
}

_, err := client.ObservatoryScheduledPageTest(context.Background(), cloudflare.ZoneIdentifier(rs.Primary.Attributes[consts.ZoneIDSchemaKey]), cloudflare.ObservatoryScheduledPageTestParams{
URL: rs.Primary.Attributes["url"],
Region: rs.Primary.Attributes["region"],
})
if err == nil {
return fmt.Errorf("observatory scheduled test still exists")
}
}

return nil
}

func testAccCloudflareObservatoryScheduledTest(resourceName, zoneID, domain string) string {
return fmt.Sprintf(`
resource "cloudflare_observatory_scheduled_test" "%[1]s" {
zone_id = "%[2]s"
url = "%[3]s"
region = "us-central1"
frequency = "DAILY"
}
`, resourceName, zoneID, domain)
}
Loading

0 comments on commit 30b1384

Please sign in to comment.