Skip to content

Commit

Permalink
Merge pull request #412 from jacobbednarz/non-unicode-domain-support
Browse files Browse the repository at this point in the history
resource/cloudflare_zone: Add unicode support
  • Loading branch information
jacobbednarz authored Jul 16, 2019
2 parents 7659275 + 068eefb commit c34d3d9
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 15 deletions.
24 changes: 19 additions & 5 deletions cloudflare/resource_cloudflare_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package cloudflare
import (
"fmt"
"log"
"regexp"
"strconv"
"strings"

"golang.org/x/net/idna"

cloudflare "github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
Expand Down Expand Up @@ -40,10 +41,10 @@ func resourceCloudflareZone() *schema.Resource {

Schema: map[string]*schema.Schema{
"zone": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringMatch(regexp.MustCompile("^([a-zA-Z0-9][\\-a-zA-Z0-9]*\\.)+[\\-a-zA-Z0-9]{2,20}$"), ""),
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: zoneDiffFunc,
},
"jump_start": {
Type: schema.TypeBool,
Expand Down Expand Up @@ -264,3 +265,16 @@ func planNameForID(id string) string {
}
return ""
}

// zoneDiffFunc is a DiffSuppressFunc that accepts two strings and then converts
// them to unicode before performing the comparison whether or not the value has
// changed. This ensures that zones which could be either are evaluated
// consistently and align with what the Cloudflare API returns.
func zoneDiffFunc(k, old, new string, d *schema.ResourceData) bool {
var p *idna.Profile
p = idna.New()
unicodeOld, _ := p.ToUnicode(old)
unicodeNew, _ := p.ToUnicode(new)

return unicodeOld == unicodeNew
}
82 changes: 78 additions & 4 deletions cloudflare/resource_cloudflare_zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,84 @@ func TestAccCloudflareZone(t *testing.T) {
})
}

func TestAccZoneWithUnicodeIsStoredAsUnicode(t *testing.T) {
name := "cloudflare_zone.tf-acc-unicode-test-1"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testZoneConfig("tf-acc-unicode-test-1", "żółw.cfapi.net", "true", "false"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "zone", "żółw.cfapi.net"),
resource.TestCheckResourceAttr(name, "paused", "true"),
resource.TestCheckResourceAttr(name, "name_servers.#", "2"),
resource.TestCheckResourceAttr(name, "plan", planIDFree),
resource.TestCheckResourceAttr(name, "type", "full"),
),
},
},
})
}

func TestAccZoneWithoutUnicodeIsStoredAsUnicode(t *testing.T) {
name := "cloudflare_zone.tf-acc-unicode-test-2"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testZoneConfig("tf-acc-unicode-test-2", "xn--w-uga1v8h.cfapi.net", "true", "false"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "zone", "żółw.cfapi.net"),
resource.TestCheckResourceAttr(name, "paused", "true"),
resource.TestCheckResourceAttr(name, "name_servers.#", "2"),
resource.TestCheckResourceAttr(name, "plan", planIDFree),
resource.TestCheckResourceAttr(name, "type", "full"),
),
},
},
})
}

func TestAccZonePerformsUnicodeComparison(t *testing.T) {
name := "cloudflare_zone.tf-acc-unicode-test-3"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testZoneConfig("tf-acc-unicode-test-3", "żółw.cfapi.net", "true", "false"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "zone", "żółw.cfapi.net"),
resource.TestCheckResourceAttr(name, "paused", "true"),
resource.TestCheckResourceAttr(name, "name_servers.#", "2"),
resource.TestCheckResourceAttr(name, "plan", planIDFree),
resource.TestCheckResourceAttr(name, "type", "full"),
),
},
{
Config: testZoneConfig("tf-acc-unicode-test-3", "xn--w-uga1v8h.cfapi.net", "true", "false"),
PlanOnly: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "zone", "żółw.cfapi.net"),
resource.TestCheckResourceAttr(name, "paused", "true"),
resource.TestCheckResourceAttr(name, "name_servers.#", "2"),
resource.TestCheckResourceAttr(name, "plan", planIDFree),
resource.TestCheckResourceAttr(name, "type", "full"),
),
},
},
})
}

func testZoneConfig(resourceID, zoneName, paused, jumpStart string) string {
return fmt.Sprintf(`
resource "cloudflare_zone" "%[1]s" {
zone = "%[2]s"
zone = "%[2]s"
paused = %[3]s
jump_start = %[4]s
}`, resourceID, zoneName, paused, jumpStart)
Expand All @@ -70,7 +144,7 @@ func testZoneConfig(resourceID, zoneName, paused, jumpStart string) string {
func testZoneConfigWithPlan(resourceID, zoneName, paused, jumpStart, plan string) string {
return fmt.Sprintf(`
resource "cloudflare_zone" "%[1]s" {
zone = "%[2]s"
zone = "%[2]s"
paused = %[3]s
jump_start = %[4]s
plan = "%[5]s"
Expand Down Expand Up @@ -130,7 +204,7 @@ func TestPlanIDFallsBackToEmptyIfUnknown(t *testing.T) {
func testZoneConfigWithPartialSetup(resourceID, zoneName, paused, jumpStart, plan string) string {
return fmt.Sprintf(`
resource "cloudflare_zone" "%[1]s" {
zone = "%[2]s"
zone = "%[2]s"
paused = %[3]s
jump_start = %[4]s
plan = "%[5]s"
Expand All @@ -141,7 +215,7 @@ func testZoneConfigWithPartialSetup(resourceID, zoneName, paused, jumpStart, pla
func testZoneConfigWithExplicitFullSetup(resourceID, zoneName, paused, jumpStart, plan string) string {
return fmt.Sprintf(`
resource "cloudflare_zone" "%[1]s" {
zone = "%[2]s"
zone = "%[2]s"
paused = %[3]s
jump_start = %[4]s
plan = "%[5]s"
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ require (
github.com/hashicorp/terraform v0.12.4
github.com/pkg/errors v0.8.1
google.golang.org/genproto v0.0.0-20190716165318-c506a9f90610 // indirect
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190502183928-7f726cade0ab h1:9RfW3ktsOZxgo9YNbBAjq1FWzc/igwEcUzZz8IXgSbk=
golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down
26 changes: 25 additions & 1 deletion vendor/golang.org/x/net/http2/server.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions vendor/golang.org/x/net/http2/transport.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ golang.org/x/crypto/cast5
golang.org/x/crypto/openpgp/elgamal
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/internal/subtle
# golang.org/x/net v0.0.0-20190502183928-7f726cade0ab
# golang.org/x/net v0.0.0-20190628185345-da137c7871d7
golang.org/x/net/context
golang.org/x/net/trace
golang.org/x/net/internal/timeseries
Expand Down

0 comments on commit c34d3d9

Please sign in to comment.