Skip to content

Commit

Permalink
Merge pull request #1700 from orium/dsousa/FLPROD-397-redirect-list-s…
Browse files Browse the repository at this point in the history
…upport

Support redirect lists
  • Loading branch information
jacobbednarz authored Jun 23, 2022
2 parents b1747db + f508cbe commit efb815e
Show file tree
Hide file tree
Showing 11 changed files with 876 additions and 15 deletions.
7 changes: 7 additions & 0 deletions .changelog/1700.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:new-resource
resource/cloudflare_list: Added support for generic list types, including redirect lists.
```

```release-note:note
resource/cloudflare_ip_list: Deprecated cloudflare_ip_list in favor of cloudflare_list.
```
128 changes: 128 additions & 0 deletions docs/resources/list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
page_title: "cloudflare_list Resource - Cloudflare"
subcategory: ""
description: |-
Provides Lists (IPs, Redirects) to be used in Edge Rules Engine across all zones within the same account.
---

# cloudflare_list (Resource)

Provides Lists (IPs, Redirects) to be used in Edge Rules Engine across all zones within the same account.

## Example Usage

```terraform
# IP list
resource "cloudflare_list" "example" {
account_id = "919f297a62fdfb28844177128ed4d331"
name = "example list"
description = "example IPs for a list"
kind = "ip"
item {
value {
ip = "192.0.2.0"
}
comment = "one"
}
item {
value {
ip = "192.0.2.1"
}
comment = "two"
}
}
# Redirect list
resource "cloudflare_list" "example" {
account_id = "919f297a62fdfb28844177128ed4d331"
name = "example list"
description = "example redirects for a list"
kind = "redirect"
item {
value {
redirect {
source_url = "example.com/blog"
target_url = "https://blog.example.com"
}
}
comment = "one"
}
item {
value {
redirect {
source_url = "example.com/foo"
target_url = "https://foo.example.com"
include_subdomains = true
subpath_matching = true
status_code = 301
preserve_query_string = true
preserve_path_suffix = false
}
}
comment = "two"
}
}
```
<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `account_id` (String) The account identifier to target for the resource.
- `kind` (String) The type of items the list will contain.
- `name` (String) The name of the list.

### Optional

- `description` (String) An optional description of the list.
- `item` (Block List) (see [below for nested schema](#nestedblock--item))

### Read-Only

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

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

Required:

- `value` (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--item--value))

Optional:

- `comment` (String) An optional comment for the item.

<a id="nestedblock--item--value"></a>
### Nested Schema for `item.value`

Optional:

- `ip` (String)
- `redirect` (Block List) (see [below for nested schema](#nestedblock--item--value--redirect))

<a id="nestedblock--item--value--redirect"></a>
### Nested Schema for `item.value.redirect`

Required:

- `source_url` (String) The source url of the redirect.
- `target_url` (String) The target url of the redirect.

Optional:

- `include_subdomains` (Boolean) Whether the redirect also matches subdomains of the source url.
- `preserve_path_suffix` (Boolean) Whether to preserve the path suffix when doing subpath matching.
- `preserve_query_string` (Boolean) Whether the redirect target url should keep the query string of the request's url.
- `status_code` (Number) The status code to be used when redirecting a request.
- `subpath_matching` (Boolean) Whether the redirect also matches subpaths of the source url.

## Import

Import is supported using the following syntax:
```shell
$ terraform import cloudflare_list.example <account_id>/<list_id>
```
1 change: 1 addition & 0 deletions examples/resources/cloudflare_list/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$ terraform import cloudflare_list.example <account_id>/<list_id>
54 changes: 54 additions & 0 deletions examples/resources/cloudflare_list/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# IP list
resource "cloudflare_list" "example" {
account_id = "919f297a62fdfb28844177128ed4d331"
name = "example list"
description = "example IPs for a list"
kind = "ip"

item {
value {
ip = "192.0.2.0"
}
comment = "one"
}

item {
value {
ip = "192.0.2.1"
}
comment = "two"
}
}

# Redirect list
resource "cloudflare_list" "example" {
account_id = "919f297a62fdfb28844177128ed4d331"
name = "example list"
description = "example redirects for a list"
kind = "redirect"

item {
value {
redirect {
source_url = "example.com/blog"
target_url = "https://blog.example.com"
}
}
comment = "one"
}

item {
value {
redirect {
source_url = "example.com/foo"
target_url = "https://foo.example.com"
include_subdomains = true
subpath_matching = true
status_code = 301
preserve_query_string = true
preserve_path_suffix = false
}
}
comment = "two"
}
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func New(version string) func() *schema.Provider {
"cloudflare_healthcheck": resourceCloudflareHealthcheck(),
"cloudflare_ip_list": resourceCloudflareIPList(),
"cloudflare_ipsec_tunnel": resourceCloudflareIPsecTunnel(),
"cloudflare_list": resourceCloudflareList(),
"cloudflare_load_balancer_monitor": resourceCloudflareLoadBalancerMonitor(),
"cloudflare_load_balancer_pool": resourceCloudflareLoadBalancerPool(),
"cloudflare_load_balancer": resourceCloudflareLoadBalancer(),
Expand Down
52 changes: 41 additions & 11 deletions internal/provider/resource_cloudflare_ip_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
"github.com/pkg/errors"
)

// The resource in this file is deprecated and should be removed on the next major release.
// Use the more general `list` resource instead.

func resourceCloudflareIPList() *schema.Resource {
return &schema.Resource{
Schema: resourceCloudflareIPListSchema(),
Expand All @@ -22,14 +25,20 @@ func resourceCloudflareIPList() *schema.Resource {
Importer: &schema.ResourceImporter{
StateContext: resourceCloudflareIPListImport,
},
DeprecationMessage: "This resource is deprecated, use the `cloudflare_list` instead.",
}
}

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

list, err := client.CreateIPList(ctx, accountID, d.Get("name").(string), d.Get("description").(string), d.Get("kind").(string))
list, err := client.CreateList(ctx, cloudflare.ListCreateParams{
AccountID: accountID,
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Kind: d.Get("kind").(string),
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error creating IP List %s", d.Get("name").(string))))
}
Expand All @@ -38,7 +47,11 @@ func resourceCloudflareIPListCreate(ctx context.Context, d *schema.ResourceData,

if items, ok := d.GetOk("item"); ok {
IPListItems := buildIPListItemsCreateRequest(items.(*schema.Set).List())
_, err = client.CreateIPListItems(ctx, accountID, d.Id(), IPListItems)
_, err = client.CreateListItems(ctx, cloudflare.ListCreateItemsParams{
AccountID: accountID,
ID: d.Id(),
Items: IPListItems,
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error creating IP List Items")))
}
Expand Down Expand Up @@ -67,7 +80,10 @@ func resourceCloudflareIPListRead(ctx context.Context, d *schema.ResourceData, m
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)

list, err := client.GetIPList(ctx, accountID, d.Id())
list, err := client.GetList(ctx, cloudflare.ListGetParams{
AccountID: accountID,
ID: d.Id(),
})
if err != nil {
if strings.Contains(err.Error(), "could not find list") {
tflog.Info(ctx, fmt.Sprintf("IP List %s no longer exists", d.Id()))
Expand All @@ -81,7 +97,10 @@ func resourceCloudflareIPListRead(ctx context.Context, d *schema.ResourceData, m
d.Set("description", list.Description)
d.Set("kind", list.Kind)

items, err := client.ListIPListItems(ctx, accountID, d.Id())
items, err := client.ListListItems(ctx, cloudflare.ListListItemsParams{
AccountID: accountID,
ID: d.Id(),
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error reading IP List Items")))
}
Expand All @@ -106,14 +125,22 @@ func resourceCloudflareIPListUpdate(ctx context.Context, d *schema.ResourceData,
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)

_, err := client.UpdateIPList(ctx, accountID, d.Id(), d.Get("description").(string))
_, err := client.UpdateList(ctx, cloudflare.ListUpdateParams{
AccountID: accountID,
ID: d.Id(),
Description: d.Get("description").(string),
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error updating IP List description")))
}

if items, ok := d.GetOk("item"); ok {
IPListItems := buildIPListItemsCreateRequest(items.(*schema.Set).List())
_, err = client.ReplaceIPListItems(ctx, accountID, d.Id(), IPListItems)
_, err = client.ReplaceListItems(ctx, cloudflare.ListReplaceItemsParams{
AccountID: accountID,
ID: d.Id(),
Items: IPListItems,
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error creating IP List Items")))
}
Expand All @@ -126,20 +153,23 @@ func resourceCloudflareIPListDelete(ctx context.Context, d *schema.ResourceData,
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)

_, err := client.DeleteIPList(ctx, accountID, d.Id())
_, err := client.DeleteList(ctx, cloudflare.ListDeleteParams{
AccountID: accountID,
ID: d.Id(),
})
if err != nil {
return diag.FromErr(errors.Wrap(err, fmt.Sprintf("error deleting IP List with ID %q", d.Id())))
}

return nil
}

func buildIPListItemsCreateRequest(items []interface{}) []cloudflare.IPListItemCreateRequest {
var IPListItems []cloudflare.IPListItemCreateRequest
func buildIPListItemsCreateRequest(items []interface{}) []cloudflare.ListItemCreateRequest {
var IPListItems []cloudflare.ListItemCreateRequest

for _, item := range items {
IPListItems = append(IPListItems, cloudflare.IPListItemCreateRequest{
IP: item.(map[string]interface{})["value"].(string),
IPListItems = append(IPListItems, cloudflare.ListItemCreateRequest{
IP: cloudflare.StringPtr(item.(map[string]interface{})["value"].(string)),
Comment: item.(map[string]interface{})["comment"].(string),
})
}
Expand Down
10 changes: 8 additions & 2 deletions internal/provider/resource_cloudflare_ip_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ func TestAccCloudflareIPList_Exists(t *testing.T) {
var IPList cloudflare.IPList

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheckAccount(t) },
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAccount(t)
},
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Expand Down Expand Up @@ -61,7 +64,10 @@ func TestAccCloudflareIPList_UpdateDescription(t *testing.T) {
var initialID string

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheckAccount(t) },
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAccount(t)
},
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Expand Down
Loading

0 comments on commit efb815e

Please sign in to comment.