-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new resource for dex tests #2250
Changes from 7 commits
e4cb938
6e29702
908e9ff
7e32ab3
ac54388
3b50160
f5db8c5
e75c5eb
5bed437
beaa774
f035b15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-resource | ||
cloudflare_device_dex_tests | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
--- | ||
page_title: "cloudflare_device_dex_tests Resource - Cloudflare" | ||
subcategory: "" | ||
description: |- | ||
Provides a Cloudflare Device Digital Experience Monitoring (DEX) test configuration resource. | ||
--- | ||
|
||
# cloudflare_device_dex_tests (Resource) | ||
|
||
Provides a Cloudflare Device Digital Experience Monitoring (DEX) test configuration resource. | ||
|
||
## Example Usage | ||
|
||
```terraform | ||
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" | ||
} | ||
} | ||
``` | ||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `test_id` (String) The account identifier to target for the resource. | ||
- `name` (String) The name of the DEX test. Must be unique. | ||
- `interval` (String) How often the test will run. An interval of 2 hours, 45 minutes, and 30 seconds would be "2h45m30s". | ||
- `enabled` (Boolean) `true` if test is enabled to run. | ||
- `data` (Block List, Min: 1, Max: 1) The configuration object which contains the details for the WARP client to conduct the test. (see [below for nested schema](#nestedblock--config)) | ||
|
||
### Optional | ||
|
||
- `description` (String) Additional details about the test. | ||
|
||
### Read-Only | ||
|
||
- `test_id` (String) The ID of this resource. | ||
|
||
<a id="nestedblock--config"></a> | ||
### Nested Schema for `config` | ||
|
||
Required: | ||
- `kind` (String) The type of request the WARP client will make to the specified host. Available values: `http`, `traceroute`. | ||
|
||
`http` kind required fields: | ||
- `host` (String) A valid URL. | ||
- `method` (String) HTTP request method. Available values: `GET`. | ||
|
||
`traceroute` kind required fields: | ||
- `host` (String) A valid hostname or IP address. | ||
|
||
## Import | ||
|
||
Import is supported using the following syntax: | ||
|
||
```shell | ||
$ terraform import cloudflare_device_dex_tests.example <account_id>/<device_dex_tests_test_id> | ||
``` |
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> |
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" | ||
} | ||
} |
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, ¬FoundError) { | ||
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} | ||
} |
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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes for this resource we used |
||
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) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these tests are all missing the required
account_id
field.