Skip to content

Commit

Permalink
Merge pull request #4724 from mgirouard/next-page-rules-standalone
Browse files Browse the repository at this point in the history
Add tests for all stand-alone actions
  • Loading branch information
mgirouard authored Dec 6, 2024
2 parents 2db239e + d0681f3 commit c2d2c8d
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 72 deletions.
79 changes: 33 additions & 46 deletions internal/services/page_rule/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package page_rule

import (
"encoding/json"
"errors"

"github.com/cloudflare/cloudflare-go/v3"
"github.com/cloudflare/cloudflare-go/v3/pagerules"
"github.com/cloudflare/terraform-provider-cloudflare/internal/apijson"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand All @@ -14,16 +12,23 @@ func (m PageRuleModel) marshalCustom() (data []byte, err error) {
if data, err = apijson.MarshalRoot(m); err != nil {
return
}
if data, err = m.marshalTargets(data); err != nil {
if data, err = m.marshalTargetsAndActions(data); err != nil {
return
}
if data, err = m.marshalActions(data); err != nil {
return
}

func (m PageRuleModel) marshalCustomForUpdate(state PageRuleModel) (data []byte, err error) {
if data, err = apijson.MarshalForUpdate(m, state); err != nil {
return
}
if data, err = m.marshalTargetsAndActions(data); err != nil {
return
}
return
}

func (m PageRuleModel) marshalTargets(b []byte) (data []byte, err error) {
func (m PageRuleModel) marshalTargetsAndActions(b []byte) (data []byte, err error) {
var T struct {
ID string `json:"id,omitempty"`
ZoneID string `json:"zone_id,omitempty"`
Expand All @@ -33,10 +38,12 @@ func (m PageRuleModel) marshalTargets(b []byte) (data []byte, err error) {
ModifiedOn string `json:"modified_on,omitempty"`
Target string `json:"target,omitempty"`
Targets []any `json:"targets,omitempty"`
Actions any `json:"actions,omitempty"`
}
if err = json.Unmarshal(b, &T); err != nil {
return nil, err
}

T.Targets = []any{
map[string]any{
"target": "url",
Expand All @@ -46,24 +53,7 @@ func (m PageRuleModel) marshalTargets(b []byte) (data []byte, err error) {
},
},
}
T.Target = ""
return json.Marshal(T)
}

func (m PageRuleModel) marshalActions(b []byte) (data []byte, err error) {
var T struct {
ID string `json:"id,omitempty"`
ZoneID string `json:"zone_id,omitempty"`
Priority int64 `json:"priority,omitempty"`
Status string `json:"status,omitempty"`
CreatedOn string `json:"created_on,omitempty"`
ModifiedOn string `json:"modified_on,omitempty"`
Targets []any `json:"targets,omitempty"`
Actions []map[string]any `json:"actions,omitempty"`
}
if err = json.Unmarshal(b, &T); err != nil {
return nil, err
}
T.Target = "" // omitempty

T.Actions, err = m.Actions.Encode()
if err != nil {
Expand All @@ -73,37 +63,34 @@ func (m PageRuleModel) marshalActions(b []byte) (data []byte, err error) {
return json.Marshal(T)
}

func (m PageRuleModel) PageruleNewParams() pagerules.PageruleNewParams {
return pagerules.PageruleNewParams{
ZoneID: cloudflare.F(m.ZoneID.ValueString()),
Targets: cloudflare.F([]pagerules.TargetParam{
{
Constraint: cloudflare.F(pagerules.TargetConstraintParam{
Operator: cloudflare.F(pagerules.TargetConstraintOperatorMatches),
Value: cloudflare.F(m.Target.String()),
}),
},
}),
Actions: cloudflare.F([]pagerules.PageruleNewParamsActionUnion{}),
}
}

type PageRuleActionsModel struct {
AutomaticHTTPSRewrites types.String `tfsdk:"automatic_https_rewrites" json:"automatic_https_rewrites,optional"`
AlwaysUseHTTPS types.Bool `tfsdk:"always_use_https" json:"always_use_https,optional"`
DisableApps types.Bool `tfsdk:"disable_apps" json:"disable_apps,optional"`
DisablePerformance types.Bool `tfsdk:"disable_performance" json:"disable_performance,optional"`
DisableSecurity types.Bool `tfsdk:"disable_security" json:"disable_security,optional"`
DisableZaraz types.Bool `tfsdk:"disable_zaraz" json:"disable_zaraz,optional"`
}

func (m *PageRuleActionsModel) Encode() (encoded []map[string]any, err error) {

switch {
case !m.AutomaticHTTPSRewrites.IsNull():
encoded = []map[string]any{}
if m.AlwaysUseHTTPS.ValueBool() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDAlwaysUseHTTPS})
}
if !m.AutomaticHTTPSRewrites.IsNull() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDAutomaticHTTPSRewrites, "value": m.AutomaticHTTPSRewrites.String()})
case !m.DisableApps.IsNull():
}
if m.DisableApps.ValueBool() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDDisableApps, "value": m.DisableApps.ValueBool()})
default:
// TODO: Throw error for unknown page rule
return nil, errors.New("missing or unknown page rule")
}

if m.DisablePerformance.ValueBool() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDDisablePerformance})
}
if m.DisableSecurity.ValueBool() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDDisableSecurity})
}
if m.DisableZaraz.ValueBool() {
encoded = append(encoded, map[string]any{"id": pagerules.PageRuleActionsIDDisableZaraz})
}
return
}
3 changes: 1 addition & 2 deletions internal/services/page_rule/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
package page_rule

import (
"github.com/cloudflare/terraform-provider-cloudflare/internal/apijson"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework/types"
)
Expand All @@ -29,5 +28,5 @@ func (m PageRuleModel) MarshalJSON() (data []byte, err error) {
}

func (m PageRuleModel) MarshalJSONForUpdate(state PageRuleModel) (data []byte, err error) {
return apijson.MarshalForUpdate(m, state)
return m.marshalCustomForUpdate(state)
}
4 changes: 3 additions & 1 deletion internal/services/page_rule/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ func (r *PageRuleResource) Create(ctx context.Context, req resource.CreateReques
env := PageRuleResultEnvelope{*data}
_, err = r.client.Pagerules.New(
ctx,
data.PageruleNewParams(),
pagerules.PageruleNewParams{
ZoneID: cloudflare.F(data.ZoneID.ValueString()),
},
option.WithRequestBody("application/json", dataBytes),
option.WithResponseBodyInto(&res),
option.WithMiddleware(logging.Middleware(ctx)),
Expand Down
159 changes: 144 additions & 15 deletions internal/services/page_rule/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ func TestAccCloudflarePageRule_FullySpecified(t *testing.T) {
})
}

func TestAccCloudflarePageRule_ForwardingOnly(t *testing.T) {
func TestAccCloudflarePageRule_AlwaysUseHTTPS(t *testing.T) {
t.Skip("unable to set always_use_https")
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
Expand All @@ -135,19 +136,18 @@ func TestAccCloudflarePageRule_ForwardingOnly(t *testing.T) {
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflarePageRuleConfigForwardingOnly(zoneID, target, rnd, rnd+"."+domain),
Config: buildPageRuleConfig(rnd, zoneID, `always_use_https = true`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "target", fmt.Sprintf("%s/", target)),
resource.TestCheckResourceAttr(resourceName, "actions.0.forwarding_url.0.url", fmt.Sprintf("http://%s/forward", rnd+"."+domain)),
resource.TestCheckResourceAttr(resourceName, "actions.always_use_https", "true"),
),
},
},
})
}

func TestAccCloudflarePageRule_ForwardingAndOthers(t *testing.T) {
func TestAccCloudflarePageRule_DisableApps(t *testing.T) {
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
Expand All @@ -161,15 +161,86 @@ func TestAccCloudflarePageRule_ForwardingAndOthers(t *testing.T) {
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflarePageRuleConfigForwardingAndOthers(zoneID, target, rnd),
Config: buildPageRuleConfig(rnd, zoneID, `disable_apps = true`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "target", target),
resource.TestCheckResourceAttr(resourceName, "target", fmt.Sprintf("%s/", target)),
resource.TestCheckResourceAttr(resourceName, "actions.disable_apps", "true"),
),
},
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_apps = false`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_apps", "false"),
),
},
},
})
}

ExpectError: regexp.MustCompile("\"forwarding_url\" cannot be set with any other actions"),
func TestAccCloudflarePageRule_DisablePerformance(t *testing.T) {
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
rnd := utils.GenerateRandomResourceName()
resourceName := "cloudflare_page_rule." + rnd
target := fmt.Sprintf("%s.%s", rnd, domain)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_performance = true`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_performance", "true"),
),
},
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_performance = false`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_performance", "false"),
),
},
},
})
}

func TestAccCloudflarePageRule_DisableSecurity(t *testing.T) {
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
rnd := utils.GenerateRandomResourceName()
resourceName := "cloudflare_page_rule." + rnd
target := fmt.Sprintf("%s.%s", rnd, domain)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_security = true`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_security", "true"),
),
},
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_security = false`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_security", "false"),
),
},
},
})
Expand All @@ -189,18 +260,79 @@ func TestAccCloudflarePageRule_DisableZaraz(t *testing.T) {
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflarePageRuleConfigDisableZaraz(zoneID, target, rnd),
Config: buildPageRuleConfig(rnd, zoneID, `disable_zaraz = true`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_zaraz", "true"),
),
},
{
Config: buildPageRuleConfig(rnd, zoneID, `disable_zaraz = false`, target),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "actions.disable_zaraz", "false"),
),
},
},
})
}

func TestAccCloudflarePageRule_ForwardingOnly(t *testing.T) {
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
rnd := utils.GenerateRandomResourceName()
resourceName := "cloudflare_page_rule." + rnd
target := fmt.Sprintf("%s.%s", rnd, domain)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflarePageRuleConfigForwardingOnly(zoneID, target, rnd, rnd+"."+domain),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "target", fmt.Sprintf("%s/", target)),
resource.TestCheckResourceAttr(resourceName, "actions.0.disable_zaraz", "true"),
resource.TestCheckResourceAttr(resourceName, "actions.0.forwarding_url.0.url", fmt.Sprintf("http://%s/forward", rnd+"."+domain)),
),
},
},
})
}

func TestAccCloudflarePageRule_ForwardingAndOthers(t *testing.T) {
var pageRule cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
rnd := utils.GenerateRandomResourceName()
resourceName := "cloudflare_page_rule." + rnd
target := fmt.Sprintf("%s.%s", rnd, domain)

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckCloudflarePageRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflarePageRuleConfigForwardingAndOthers(zoneID, target, rnd),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudflarePageRuleExists(resourceName, &pageRule),
resource.TestCheckResourceAttr(resourceName, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceName, "target", target),
resource.TestCheckResourceAttr(resourceName, "target", fmt.Sprintf("%s/", target)),
),

ExpectError: regexp.MustCompile("\"forwarding_url\" cannot be set with any other actions"),
},
},
})
}

func TestAccCloudflarePageRule_Updated(t *testing.T) {
var before, after cloudflare.PageRule
domain := os.Getenv("CLOUDFLARE_DOMAIN")
Expand Down Expand Up @@ -1032,10 +1164,6 @@ func testAccCheckCloudflarePageRuleConfigForwardingAndOthers(zoneID, target, rnd
return acctest.LoadTestCase("pageruleconfigforwardingandothers.tf", zoneID, target, rnd)
}

func testAccCheckCloudflarePageRuleConfigDisableZaraz(zoneID, target, rnd string) string {
return acctest.LoadTestCase("pageruleconfigdisablezaraz.tf", zoneID, target, rnd)
}

func testAccCheckCloudflarePageRuleConfigWithEdgeCacheTtl(zoneID, target, rnd string) string {
return acctest.LoadTestCase("pageruleconfigwithedgecachettl.tf", zoneID, target, rnd)
}
Expand Down Expand Up @@ -1083,6 +1211,7 @@ func testAccCheckCloudflarePageRuleConfigCacheKeyFieldsIncludeMultipleValuesQuer
func testAccCheckCloudflarePageRuleConfigCacheTTLByStatus(zoneID, target, rnd string) string {
return acctest.LoadTestCase("pageruleconfigcachettlbystatus.tf", zoneID, target, rnd)
}

func buildPageRuleConfig(rnd, zoneID, actions, target string) string {
return acctest.LoadTestCase("buildpageruleconfig.tf",
rnd,
Expand Down
Loading

0 comments on commit c2d2c8d

Please sign in to comment.