Skip to content

Commit

Permalink
Add new resource for Dex tests
Browse files Browse the repository at this point in the history
  • Loading branch information
da-cf committed Feb 21, 2023
1 parent 6e29702 commit 908e9ff
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .changelog/2250.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
cloudflare_device_dex_tests
```
6 changes: 3 additions & 3 deletions docs/resources/device_dex_tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Provides a Cloudflare Device Digital Experience Monitoring (DEX) test configurat
## Example Usage

```terraform
resource "cloudflare_device_dex_tests" "example" {
resource "cloudflare_device_dex_tests" "dex_tests" {
test_id = "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
name = "GET dashboard",
description = "Send a HTTP GET request to the 'home' endpoint of the dash every half hour.",
Expand All @@ -38,7 +38,7 @@ resource "cloudflare_device_dex_tests" "example" {

### Optional

- `description` (String) A description of the test to help identify it.
- `description` (String) Additional details about the test.

### Read-Only

Expand All @@ -55,7 +55,7 @@ Required:
- `method` (String) HTTP request method. Available values: `GET`.

`traceroute` kind required fields:
- `host` (String) A valid hostname.
- `host` (String) A valid hostname or IP address.

## Import

Expand Down
1 change: 1 addition & 0 deletions examples/resources/cloudflare_device_dex_tests/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import cloudflare_device_dex_tests.example <account_id>/<device_dex_tests_id>
12 changes: 12 additions & 0 deletions examples/resources/cloudflare_device_dex_tests/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
resource "cloudflare_device_dex_tests" "dex_tests" {
test_id = "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"
name = "GET dashboard"
description = "Send a HTTP GET request to the 'home' endpoint of the dash every half hour."
interval = "0h30m0s"
enabled = true
data {
host = "https://dash.cloudflare.com/home"
kind = "http"
method = "GET"
}
}
1 change: 1 addition & 0 deletions internal/sdkv2provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func New(version string) func() *schema.Provider {
"cloudflare_custom_hostname": resourceCloudflareCustomHostname(),
"cloudflare_custom_pages": resourceCloudflareCustomPages(),
"cloudflare_custom_ssl": resourceCloudflareCustomSsl(),
"cloudflare_device_dex_tests": resourceCloudflareDeviceDexTests(),
"cloudflare_device_settings_policy": resourceCloudflareDeviceSettingsPolicy(),
"cloudflare_device_policy_certificates": resourceCloudflareDevicePolicyCertificates(),
"cloudflare_device_posture_integration": resourceCloudflareDevicePostureIntegration(),
Expand Down
177 changes: 177 additions & 0 deletions internal/sdkv2provider/resource_cloudflare_device_dex_tests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package sdkv2provider

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

"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"
)

func resourceCloudflareDeviceDexTests() *schema.Resource {
return &schema.Resource{
Schema: resourceCloudflareDeviceDexTestsSchema(),
CreateContext: resourceCloudflareDeviceDexTestsCreate,
ReadContext: resourceCloudflareDeviceDexTestsRead,
UpdateContext: resourceCloudflareDeviceDexTestsUpdate,
DeleteContext: resourceCloudflareDeviceDexTestsDelete,
Importer: &schema.ResourceImporter{
StateContext: resourceCloudflareDeviceDexTestsImport,
},
Description: "Provides a Cloudflare Device Dex Test resource. Device Dex Tests allow for building location-aware device settings policies.",
}
}

func resourceCloudflareDeviceDexTestsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
identifier := cloudflare.AccountIdentifier(d.Get(consts.AccountIDSchemaKey).(string))
tflog.Debug(ctx, fmt.Sprintf("Reading Cloudflare Device Dex Test for Id: %+v", d.Id()))

dexTest, err := client.GetDeviceDexTest(ctx, identifier, d.Id())

var notFoundError *cloudflare.NotFoundError
if errors.As(err, &notFoundError) {
tflog.Info(ctx, fmt.Sprintf("Device Dex Test %s no longer exists", d.Id()))
d.SetId("")
return nil
}
if err != nil {
return diag.FromErr(fmt.Errorf("error reading Device Dex Test: %w", err))
}

d.Set("name", dexTest.Name)
d.Set("description", dexTest.Description)
d.Set("enabled", dexTest.Enabled)
d.Set("interval", dexTest.Interval)
d.Set("updated", dexTest.Updated)
d.Set("created", dexTest.Created)
d.Set("data", convertDeviceDexTestDataToSchema(dexTest.Data))

return nil
}

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

kind := d.Get("config.0.kind").(string)

params := cloudflare.CreateDeviceDexTestParams{
Name: d.Get("name").(string),
Description: d.Get("type").(string),
Interval: d.Get("type").(string),
Enabled: d.Get("type").(bool),
Data: &cloudflare.DeviceDexTestData{
"Kind": kind,
"Host": d.Get("config.0.host").(string),
},
}

if kind == "http" {
(*params.Data)["Method"] = d.Get("config.0.method").(string)
}

tflog.Debug(ctx, fmt.Sprintf("Creating Cloudflare Device Dex Test with params: %+v", params))

dexTest, err := client.CreateDeviceDexTest(ctx, identifier, params)

if err != nil {
return diag.FromErr(fmt.Errorf("error creating Device Dex Test with provided config: %w", err))
}

d.SetId(dexTest.TestID)

return resourceCloudflareDeviceDexTestsRead(ctx, d, meta)
}

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

updatedDeviceDexTestParams := cloudflare.UpdateDeviceDexTestParams{
TestID: d.Id(),
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Interval: d.Get("interval").(string),
Enabled: d.Get("enabled").(bool),
Data: &cloudflare.DeviceDexTestData{
"Kind": d.Get("config.0.kind").(string),
"Host": d.Get("config.0.host").(string),
"Method": d.Get("config.0.method").(string),
},
}

tflog.Debug(ctx, fmt.Sprintf("Updating Cloudflare Device Dex Test with params: %+v", updatedDeviceDexTestParams))

dexTest, err := client.UpdateDeviceDexTest(ctx, identifier, updatedDeviceDexTestParams)

if err != nil {
return diag.FromErr(fmt.Errorf("error updating Device Dex Test for ID %q: %w", d.Id(), err))
}
if dexTest.TestID == "" {
return diag.FromErr(fmt.Errorf("failed to find Dex Test ID in update response; resource was empty"))
}

return resourceCloudflareDeviceDexTestsRead(ctx, d, meta)
}

func resourceCloudflareDeviceDexTestsDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
identifier := cloudflare.AccountIdentifier(d.Get(consts.AccountIDSchemaKey).(string))
tflog.Debug(ctx, fmt.Sprintf("Deleting Cloudflare Device Dex Test using ID: %s", d.Id()))

if _, err := client.DeleteDexTest(ctx, identifier, d.Id()); err != nil {
return diag.FromErr(fmt.Errorf("error deleting DLP Profile for ID %q: %w", d.Id(), err))
}

resourceCloudflareDeviceDexTestsRead(ctx, d, meta)
return nil
}

func resourceCloudflareDeviceDexTestsImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
accountID, dexTestID, err := parseDeviceDexTestsIDImport(d.Id())
if err != nil {
return nil, err
}

tflog.Debug(ctx, fmt.Sprintf("Importing Cloudflare Device Dex Test: id %s for account %s", dexTestID, accountID))

d.Set("account_id", accountID)
d.SetId(dexTestID)

resourceCloudflareDeviceDexTestsRead(ctx, d, meta)

return []*schema.ResourceData{d}, nil
}

func parseDeviceDexTestsIDImport(id string) (string, string, error) {
attributes := strings.SplitN(id, "/", 2)

if len(attributes) != 2 {
return "", "", fmt.Errorf("invalid id (\"%s\") specified, should be in format \"accountID/testID\"", id)
}

return attributes[0], attributes[1], nil
}

func convertDeviceDexTestDataToSchema(input *cloudflare.DeviceDexTestData) []interface{} {
kind, _ := (*input)["Kind"]
host, _ := (*input)["Host"]
method, _ := (*input)["Method"]

m := map[string]interface{}{
"kind": kind,
"host": host,
}

// The `method` field doesn't exist under all conditions. Only add it if we are converting an `http` kind of test.
if kind == "http" && method != "" {
m["method"] = method
}
return []interface{}{m}
}
108 changes: 108 additions & 0 deletions internal/sdkv2provider/resource_cloudflare_device_dex_tests_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package sdkv2provider

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccCloudflareDeviceDexTests(t *testing.T) {
rnd := generateRandomResourceName()
name := fmt.Sprintf("cloudflare_device_dex_tests.%s", rnd)

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckAccount(t)
},
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccCloudflareDeviceDexTestsHttp(accountID, rnd),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "account_id", accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "description", rnd),
resource.TestCheckResourceAttr(name, "interval", "0h30m0s"),
resource.TestCheckResourceAttr(name, "enabled", "true"),
resource.TestCheckResourceAttr(name, "data.0.host", "https://dash.cloudflare.com/home"),
resource.TestCheckResourceAttr(name, "data.0.kind", "http"),
resource.TestCheckResourceAttr(name, "data.0.method", "GET"),
),
},
{
Config: testAccCloudflareDeviceDexTestsTraceroute(accountID, rnd),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "account_id", accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "description", rnd),
resource.TestCheckResourceAttr(name, "interval", "0h30m0s"),
resource.TestCheckResourceAttr(name, "enabled", "true"),
resource.TestCheckResourceAttr(name, "data.0.host", "dash.cloudflare.com"),
resource.TestCheckResourceAttr(name, "data.0.kind", "http"),
),
},
{
Config: testAccCloudflareDeviceDexTestsTracerouteIpv4(accountID, rnd),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "account_id", accountID),
resource.TestCheckResourceAttr(name, "name", rnd),
resource.TestCheckResourceAttr(name, "description", rnd),
resource.TestCheckResourceAttr(name, "interval", "0h30m0s"),
resource.TestCheckResourceAttr(name, "enabled", "true"),
resource.TestCheckResourceAttr(name, "data.0.host", "1.1.1.1"),
resource.TestCheckResourceAttr(name, "data.0.kind", "http"),
),
},
},
})
}

func testAccCloudflareDeviceDexTestsHttp(accountID, rnd string) string {
return fmt.Sprintf(`
resource "cloudflare_device_dex_tests" "%[1]s" {
test_id = "%[2]s"
name = "%[1]s"
description = "%[1]s"
interval = "0h30m0s"
enabled = true
data {
host = "https://dash.cloudflare.com/home"
kind = "http"
method = "GET"
}
}
`, rnd, accountID)
}

func testAccCloudflareDeviceDexTestsTraceroute(accountID, rnd string) string {
return fmt.Sprintf(`
resource "cloudflare_device_dex_tests" "%[1]s" {
test_id = "%[2]s"
name = "%[1]s"
description = "%[1]s"
interval = "0h30m0s"
enabled = true
data {
host = "dash.cloudflare.com"
kind = "traceroute"
}
}
`, rnd, accountID)
}

func testAccCloudflareDeviceDexTestsTracerouteIpv4(accountID, rnd string) string {
return fmt.Sprintf(`
resource "cloudflare_device_dex_tests" "%[1]s" {
test_id = "%[2]s"
name = "%[1]s"
description = "%[1]s"
interval = "0h30m0s"
enabled = true
data {
host = "1.1.1.1"
kind = "traceroute"
}
}
`, rnd, accountID)
}
Loading

0 comments on commit 908e9ff

Please sign in to comment.