-
Notifications
You must be signed in to change notification settings - Fork 630
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding support for fallback domains (#1356)
WDAPI-659 - Adding fallback domain terraform support Co-authored-by: Kayla Handy <khandy@cloudflare.com> Co-authored-by: Jacob Bednarz <jacob.bednarz@gmail.com>
- Loading branch information
1 parent
6abf3bf
commit fc76b4d
Showing
7 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-resource | ||
cloudflare_fallback_domain | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
cloudflare "github.com/cloudflare/cloudflare-go" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func resourceCloudflareFallbackDomain() *schema.Resource { | ||
return &schema.Resource{ | ||
Schema: resourceCloudflareFallbackDomainSchema(), | ||
Read: resourceCloudflareFallbackDomainRead, | ||
Create: resourceCloudflareFallbackDomainUpdate, // Intentionally identical to Update as the resource is always present | ||
Update: resourceCloudflareFallbackDomainUpdate, | ||
Delete: resourceCloudflareFallbackDomainDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: resourceCloudflareFallbackDomainImport, | ||
}, | ||
} | ||
} | ||
|
||
func resourceCloudflareFallbackDomainRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*cloudflare.API) | ||
accountID := d.Get("account_id").(string) | ||
|
||
domain, err := client.ListFallbackDomains(context.Background(), accountID) | ||
if err != nil { | ||
return fmt.Errorf("error finding Fallback Domains: %w", err) | ||
} | ||
|
||
if err := d.Set("domains", flattenFallbackDomains(domain)); err != nil { | ||
return fmt.Errorf("error setting domains attribute: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceCloudflareFallbackDomainUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*cloudflare.API) | ||
accountID := d.Get("account_id").(string) | ||
|
||
domainList := expandFallbackDomains(d.Get("domains").([]interface{})) | ||
|
||
newFallbackDomains, err := client.UpdateFallbackDomain(context.Background(), accountID, domainList) | ||
if err != nil { | ||
return fmt.Errorf("error updating Fallback Domains: %w", err) | ||
} | ||
|
||
if err := d.Set("domains", flattenFallbackDomains(newFallbackDomains)); err != nil { | ||
return fmt.Errorf("error setting domain attribute: %w", err) | ||
} | ||
|
||
d.SetId(accountID) | ||
|
||
return resourceCloudflareFallbackDomainRead(d, meta) | ||
} | ||
|
||
func resourceCloudflareFallbackDomainDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*cloudflare.API) | ||
accountID := d.Get("account_id").(string) | ||
|
||
_, err := client.UpdateFallbackDomain(context.Background(), accountID, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func resourceCloudflareFallbackDomainImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { | ||
accountID := d.Id() | ||
|
||
if accountID == "" { | ||
return nil, fmt.Errorf("must provide account ID") | ||
} | ||
|
||
d.Set("account_id", accountID) | ||
d.SetId(accountID) | ||
|
||
readErr := resourceCloudflareFallbackDomainRead(d, meta) | ||
|
||
return []*schema.ResourceData{d}, readErr | ||
} | ||
|
||
// flattenFallbackDomains accepts the cloudflare.FallbackDomain struct and returns the | ||
// schema representation for use in Terraform state. | ||
func flattenFallbackDomains(domains []cloudflare.FallbackDomain) []interface{} { | ||
schemaDomains := make([]interface{}, 0) | ||
|
||
for _, d := range domains { | ||
schemaDomains = append(schemaDomains, map[string]interface{}{ | ||
"suffix": d.Suffix, | ||
"description": d.Description, | ||
"dns_server": flattenStringList(d.DNSServer), | ||
}) | ||
} | ||
|
||
return schemaDomains | ||
} | ||
|
||
// expandFallbackDomains accepts the schema representation of Fallback Domains and | ||
// returns a fully qualified struct. | ||
func expandFallbackDomains(domains []interface{}) []cloudflare.FallbackDomain { | ||
domainList := make([]cloudflare.FallbackDomain, 0) | ||
|
||
for _, domain := range domains { | ||
domainList = append(domainList, cloudflare.FallbackDomain{ | ||
Suffix: domain.(map[string]interface{})["suffix"].(string), | ||
Description: domain.(map[string]interface{})["description"].(string), | ||
DNSServer: expandInterfaceToStringList(domain.(map[string]interface{})["dns_server"]), | ||
}) | ||
} | ||
|
||
return domainList | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
) | ||
|
||
func TestAccCloudflareFallbackDomain(t *testing.T) { | ||
// Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access | ||
// service does not yet support the API tokens and it results in | ||
// misleading state error messages. | ||
if os.Getenv("CLOUDFLARE_API_TOKEN") != "" { | ||
defer func(apiToken string) { | ||
os.Setenv("CLOUDFLARE_API_TOKEN", apiToken) | ||
}(os.Getenv("CLOUDFLARE_API_TOKEN")) | ||
os.Setenv("CLOUDFLARE_API_TOKEN", "") | ||
} | ||
|
||
rnd := generateRandomResourceName() | ||
name := fmt.Sprintf("cloudflare_fallback_domain.%s", rnd) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { | ||
testAccessAccPreCheck(t) | ||
}, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCloudflareFallbackDomain(rnd, accountID, "example domain", "example.com", "2.2.2.2"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(name, "account_id", accountID), | ||
resource.TestCheckResourceAttr(name, "domains.0.description", "example domain"), | ||
resource.TestCheckResourceAttr(name, "domains.0.suffix", "example.com"), | ||
resource.TestCheckResourceAttr(name, "domains.0.dns_server.0", "2.2.2.2"), | ||
), | ||
}, | ||
{ | ||
Config: testAccCloudflareFallbackDomain(rnd, accountID, "second example domain", "example_two.com", "1.1.1.1"), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(name, "account_id", accountID), | ||
resource.TestCheckResourceAttr(name, "domains.0.description", "second example domain"), | ||
resource.TestCheckResourceAttr(name, "domains.0.suffix", "example_two.com"), | ||
resource.TestCheckResourceAttr(name, "domains.0.dns_server.0", "1.1.1.1"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCloudflareFallbackDomain(rnd, accountID string, description string, suffix string, dns_server string) string { | ||
return fmt.Sprintf(` | ||
resource "cloudflare_fallback_domain" "%[1]s" { | ||
account_id = "%[2]s" | ||
domains { | ||
description = "%[3]s" | ||
suffix = "%[4]s" | ||
dns_server = ["%[5]s"] | ||
} | ||
} | ||
`, rnd, accountID, description, suffix, dns_server) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package cloudflare | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func resourceCloudflareFallbackDomainSchema() map[string]*schema.Schema { | ||
return map[string]*schema.Schema{ | ||
"account_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"domains": { | ||
Required: true, | ||
Type: schema.TypeList, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"suffix": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "The domain suffix to match when resolving locally.", | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "A description of the fallback domain, displayed in the client UI.", | ||
}, | ||
"dns_server": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Description: "A list of IP addresses to handle domain resolution.", | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- | ||
layout: "cloudflare" | ||
page_title: "Cloudflare: cloudflare_fallback_domain" | ||
sidebar_current: "docs-cloudflare-resource-fallback-domain" | ||
description: |- | ||
Provides a Cloudflare Fallback Domain resource. | ||
--- | ||
|
||
# cloudflare_fallback_domain | ||
|
||
Provides a Cloudflare Fallback Domain resource. Fallback domains are used to ignore DNS requests to a given list of domains. These DNS requests will be passed back to other DNS servers configured on existing network interfaces on the device. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
# Adding example.com to the fallback domain list | ||
resource "cloudflare_fallback_domain" "example_fallback_domain { | ||
account_id = "1d5fdc9e88c8a8c4518b068cd94331fe" | ||
domains { | ||
suffix = "example.com" | ||
description = "Example domain" | ||
dns_server = ["1.1.1.1", "2.2.2.2"] | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
- `account_id` - (Required) The account to which the device posture rule should be added. | ||
- `domains` - (Required) The value of the domain attributes (refer to the [nested schema](#nestedblock--domains)). | ||
|
||
<a id="nestedblock--domains"></a> | ||
**Nested schema for `domains`** | ||
|
||
- `suffix` - (Optional) The domain to ignore DNS requests. | ||
- `description` - (Optional) The description of the domain. | ||
- `dns_server` - (Optional) The DNS servers to receive the redirected request. | ||
|
||
## Import | ||
|
||
Fallback Domains can be imported using the account identifer. | ||
|
||
``` | ||
$ terraform import cloudflare_fallback_domain.example 1d5fdc9e88c8a8c4518b068cd94331fe | ||
``` |