diff --git a/.changelog/1246.txt b/.changelog/1246.txt new file mode 100644 index 00000000000..678b27fd5e3 --- /dev/null +++ b/.changelog/1246.txt @@ -0,0 +1,3 @@ +```release-note:note +dns_firewall: The `OriginIPs` field has been renamed to `UpstreamIPs`. +``` diff --git a/.changelog/1268.txt b/.changelog/1268.txt new file mode 100644 index 00000000000..586bac29d80 --- /dev/null +++ b/.changelog/1268.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +device_posture_rule: add input fields tanium, intune and kolide +``` \ No newline at end of file diff --git a/.changelog/1274.txt b/.changelog/1274.txt new file mode 100644 index 00000000000..51deac303d8 --- /dev/null +++ b/.changelog/1274.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.25.1 to 2.25.3 +``` diff --git a/.changelog/1275.txt b/.changelog/1275.txt new file mode 100644 index 00000000000..718b80065fd --- /dev/null +++ b/.changelog/1275.txt @@ -0,0 +1,3 @@ +```release-note:bug +rulesets: allow `PreserveQueryString` to be nullable +``` diff --git a/.changelog/1276.txt b/.changelog/1276.txt new file mode 100644 index 00000000000..713898c8dbb --- /dev/null +++ b/.changelog/1276.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +waiting_room: add support for zone-level settings +``` diff --git a/.changelog/1278.txt b/.changelog/1278.txt new file mode 100644 index 00000000000..64e605cf142 --- /dev/null +++ b/.changelog/1278.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +zone: Added `GetCacheReserve` and `UpdateacheReserve` to allow setting Cache Reserve for a zone. +``` diff --git a/.changelog/1279.txt b/.changelog/1279.txt new file mode 100644 index 00000000000..08cd4cab055 --- /dev/null +++ b/.changelog/1279.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +pages: add support for Smart Placement. Added `Placement` in `PagesProjectDeploymentConfigEnvironment`. +``` + +```release-note:enhancement +workers: add support for Smart Placement. Added `Placement` in `CreateWorkerParams`. +``` diff --git a/.changelog/1280.txt b/.changelog/1280.txt new file mode 100644 index 00000000000..7f690ce831d --- /dev/null +++ b/.changelog/1280.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.9.0 to 0.10.0 +``` diff --git a/.changelog/1284.txt b/.changelog/1284.txt new file mode 100644 index 00000000000..0da545211ae --- /dev/null +++ b/.changelog/1284.txt @@ -0,0 +1,3 @@ +```release-note:bug +turnstile: remove `SiteKey`/`Secret` being sent in update request body +``` diff --git a/.changelog/1285.txt b/.changelog/1285.txt new file mode 100644 index 00000000000..75140aed1be --- /dev/null +++ b/.changelog/1285.txt @@ -0,0 +1,3 @@ +```release-note:bug +turnstile: remove `SiteKey` being sent in rotate secret's request body +``` diff --git a/.changelog/1286.txt b/.changelog/1286.txt new file mode 100644 index 00000000000..380cc297303 --- /dev/null +++ b/.changelog/1286.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/stretchr/testify from 1.8.2 to 1.8.3 +``` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 13e93599b24..b71eecf0ee0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -34,6 +34,7 @@ What sort of change does your code introduce/modify? - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. -- [ ] This change is using publicly documented (api.cloudflare.com or developers.cloudflare.com) and stable APIs. +- [ ] This change is using publicly documented in [cloudflare/api-schemas](https://github.com/cloudflare/api-schemas) + and relies on stable APIs. [1]: https://help.github.com/articles/closing-issues-using-keywords/ diff --git a/.github/workflows/milestone-closed.yml b/.github/workflows/milestone-closed.yml index 112a514d72e..c29167a0d7e 100644 --- a/.github/workflows/milestone-closed.yml +++ b/.github/workflows/milestone-closed.yml @@ -11,6 +11,8 @@ permissions: jobs: comment-on-closed-milestone: runs-on: ubuntu-latest + outputs: + ids: ${{ steps.milestone-comment.outputs.ids }} steps: - uses: bflad/action-milestone-comment@v1 with: @@ -18,10 +20,12 @@ jobs: This functionality has been released in [${{ github.event.milestone.title }}](https://github.com/${{ github.repository }}/releases/tag/${{ github.event.milestone.title }}). For further feature requests or bug reports with this functionality, please create a [new GitHub issue](https://github.com/${{ github.repository }}/issues/new/choose) following the template. Thank you! + lock-closed-issues: runs-on: ubuntu-latest needs: comment-on-closed-milestone steps: + - uses: actions/checkout@v3 - run: | IFS=',' read -r -a issues <<< "$ISSUES" for element in "${issues[@]}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 6962e889e58..da71afec342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,39 @@ -## 0.67.0 (Unreleased) +## 0.68.0 (Unreleased) + +ENHANCEMENTS: + +* pages: add support for Smart Placement. Added `Placement` in `PagesProjectDeploymentConfigEnvironment`. ([#1279](https://github.com/cloudflare/cloudflare-go/issues/1279)) +* workers: add support for Smart Placement. Added `Placement` in `CreateWorkerParams`. ([#1279](https://github.com/cloudflare/cloudflare-go/issues/1279)) +* zone: Added `GetCacheReserve` and `UpdateacheReserve` to allow setting Cache Reserve for a zone. ([#1278](https://github.com/cloudflare/cloudflare-go/issues/1278)) + +BUG FIXES: + +* turnstile: remove `SiteKey` being sent in rotate secret's request body ([#1285](https://github.com/cloudflare/cloudflare-go/issues/1285)) +* turnstile: remove `SiteKey`/`Secret` being sent in update request body ([#1284](https://github.com/cloudflare/cloudflare-go/issues/1284)) + +DEPENDENCIES: + +* deps: bumps github.com/stretchr/testify from 1.8.2 to 1.8.3 ([#1286](https://github.com/cloudflare/cloudflare-go/issues/1286)) + +## 0.67.0 (May 10th, 2023) + +NOTES: + +* dns_firewall: The `OriginIPs` field has been renamed to `UpstreamIPs`. ([#1246](https://github.com/cloudflare/cloudflare-go/issues/1246)) + +ENHANCEMENTS: + +* device_posture_rule: add input fields tanium, intune and kolide ([#1268](https://github.com/cloudflare/cloudflare-go/issues/1268)) +* waiting_room: add support for zone-level settings ([#1276](https://github.com/cloudflare/cloudflare-go/issues/1276)) + +BUG FIXES: + +* rulesets: allow `PreserveQueryString` to be nullable ([#1275](https://github.com/cloudflare/cloudflare-go/issues/1275)) + +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.25.1 to 2.25.3 ([#1274](https://github.com/cloudflare/cloudflare-go/issues/1274)) +* deps: bumps golang.org/x/net from 0.9.0 to 0.10.0 ([#1280](https://github.com/cloudflare/cloudflare-go/issues/1280)) ## 0.66.0 (26th April, 2023) diff --git a/cache_reserve.go b/cache_reserve.go new file mode 100644 index 00000000000..a62a6144ab1 --- /dev/null +++ b/cache_reserve.go @@ -0,0 +1,82 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +// CacheReserve is the structure of the API object for the cache reserve +// setting. +type CacheReserve struct { + ID string `json:"id,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Value string `json:"value"` +} + +// CacheReserveDetailsResponse is the API response for the cache reserve +// setting. +type CacheReserveDetailsResponse struct { + Result CacheReserve `json:"result"` + Response +} + +type zoneCacheReserveSingleResponse struct { + Response + Result CacheReserve `json:"result"` +} + +type GetCacheReserveParams struct{} + +type UpdateCacheReserveParams struct { + Value string `json:"value"` +} + +// GetCacheReserve returns information about the current cache reserve settings. +// +// API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-get-cache-reserve-setting +func (api *API) GetCacheReserve(ctx context.Context, rc *ResourceContainer, params GetCacheReserveParams) (CacheReserve, error) { + if rc.Level != ZoneRouteLevel { + return CacheReserve{}, ErrRequiredZoneLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/cache/cache_reserve", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return CacheReserve{}, err + } + + var cacheReserveDetailsResponse CacheReserveDetailsResponse + err = json.Unmarshal(res, &cacheReserveDetailsResponse) + if err != nil { + return CacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return cacheReserveDetailsResponse.Result, nil +} + +// UpdateCacheReserve updates the cache reserve setting for a zone +// +// API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-change-cache-reserve-setting +func (api *API) UpdateCacheReserve(ctx context.Context, rc *ResourceContainer, params UpdateCacheReserveParams) (CacheReserve, error) { + if rc.Level != ZoneRouteLevel { + return CacheReserve{}, ErrRequiredZoneLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/cache/cache_reserve", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return CacheReserve{}, err + } + + response := &zoneCacheReserveSingleResponse{} + err = json.Unmarshal(res, &response) + if err != nil { + return CacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} diff --git a/cache_reserve_test.go b/cache_reserve_test.go new file mode 100644 index 00000000000..4434c9cf28b --- /dev/null +++ b/cache_reserve_test.go @@ -0,0 +1,82 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var cacheReserveTimestampString = "2019-02-20T22:37:07.107449Z" +var cacheReserveTimestamp, _ = time.Parse(time.RFC3339Nano, cacheReserveTimestampString) + +func TestCacheReserve(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "cache_reserve", + "value": "on", + "modified_on": "%s" + } + } + `, cacheReserveTimestampString) + } + + mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/cache_reserve", handler) + want := CacheReserve{ + ID: "cache_reserve", + Value: "on", + ModifiedOn: cacheReserveTimestamp, + } + + actual, err := client.GetCacheReserve(context.Background(), ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), GetCacheReserveParams{}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateCacheReserve(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "cache_reserve", + "value": "off", + "modified_on": "%s" + } + } + `, cacheReserveTimestampString) + } + + mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/cache_reserve", handler) + want := CacheReserve{ + ID: "cache_reserve", + Value: "off", + ModifiedOn: cacheReserveTimestamp, + } + + actual, err := client.UpdateCacheReserve(context.Background(), ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), UpdateCacheReserveParams{Value: "off"}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} diff --git a/device_posture_rule.go b/device_posture_rule.go index 83aedde75c4..5d04e270b56 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -182,6 +182,10 @@ type DevicePostureRuleInput struct { Domain string `json:"domain,omitempty"` ComplianceStatus string `json:"compliance_status,omitempty"` ConnectionID string `json:"connection_id,omitempty"` + IssueCount string `json:"issue_count,omitempty"` + CountOperator string `json:"countOperator,omitempty"` + TotalScore string `json:"total_score,omitempty"` + ScoreOperator string `json:"scoreOperator,omitempty"` } // DevicePostureRuleListResponse represents the response from the list diff --git a/dns_firewall.go b/dns_firewall.go index d426e8989e3..a6282aea209 100644 --- a/dns_firewall.go +++ b/dns_firewall.go @@ -14,7 +14,7 @@ import ( type DNSFirewallCluster struct { ID string `json:"id,omitempty"` Name string `json:"name"` - OriginIPs []string `json:"origin_ips"` + UpstreamIPs []string `json:"upstream_ips"` DNSFirewallIPs []string `json:"dns_firewall_ips,omitempty"` MinimumCacheTTL uint `json:"minimum_cache_ttl,omitempty"` MaximumCacheTTL uint `json:"maximum_cache_ttl,omitempty"` diff --git a/go.mod b/go.mod index 1d9563fd560..f434285b594 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( github.com/google/go-querystring v1.1.0 github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 - github.com/stretchr/testify v1.8.2 - github.com/urfave/cli/v2 v2.25.1 - golang.org/x/net v0.9.0 + github.com/stretchr/testify v1.8.3 + github.com/urfave/cli/v2 v2.25.3 + golang.org/x/net v0.10.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index 73c95cbd5d4..36dbcedcf49 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -51,27 +50,22 @@ github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XF github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= -github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= +github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= @@ -82,6 +76,5 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pages_project.go b/pages_project.go index 3177a8e0f81..4cbbb46497d 100644 --- a/pages_project.go +++ b/pages_project.go @@ -78,6 +78,7 @@ type PagesProjectDeploymentConfigEnvironment struct { FailOpen bool `json:"fail_open"` AlwaysUseLatestCompatibilityDate bool `json:"always_use_latest_compatibility_date"` UsageModel UsageModel `json:"usage_model,omitempty"` + Placement *Placement `json:"placement,omitempty"` } // PagesProjectDeployment represents a deployment to a Pages project. @@ -98,6 +99,7 @@ type PagesProjectDeployment struct { D1Databases D1BindingMap `json:"d1_databases,omitempty"` R2Bindings R2BindingMap `json:"r2_buckets,omitempty"` ServiceBindings ServiceBindingMap `json:"services,omitempty"` + Placement *Placement `json:"placement,omitempty"` DeploymentTrigger PagesProjectDeploymentTrigger `json:"deployment_trigger"` Stages []PagesProjectDeploymentStage `json:"stages"` BuildConfig PagesProjectBuildConfig `json:"build_config"` diff --git a/pages_project_test.go b/pages_project_test.go index 91671a5d5ca..32d09ab570e 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -110,7 +110,10 @@ const ( "compatibility_flags": ["production_flag"], "fail_open": false, "always_use_latest_compatibility_date": false, - "usage_model": "bundled" + "usage_model": "bundled", + "placement": { + "mode": "smart" + } } }, "latest_deployment": { @@ -144,6 +147,9 @@ const ( "type": "secret_text" } }, + "placement": { + "mode": "smart" + }, "compatibility_date": "2022-08-15", "compatibility_flags": ["deployment_flag"], "fail_open": false, @@ -231,6 +237,9 @@ const ( "type": "secret_text" } }, + "placement": { + "mode": "smart" + }, "compatibility_date": "2022-08-15", "compatibility_flags": ["deployment_flag"], "fail_open": false, @@ -339,6 +348,9 @@ var ( Type: SecretText, }, }, + Placement: &Placement{ + Mode: PlacementModeSmart, + }, CompatibilityFlags: []string{"deployment_flag"}, CompatibilityDate: "2022-08-15", UsageModel: Bundled, @@ -452,6 +464,9 @@ var ( FailOpen: false, AlwaysUseLatestCompatibilityDate: false, UsageModel: Bundled, + Placement: &Placement{ + Mode: PlacementModeSmart, + }, } expectedPagesProjectSource = &PagesProjectSource{ diff --git a/rulesets.go b/rulesets.go index 8110d0206a1..72a7a4f3bfc 100644 --- a/rulesets.go +++ b/rulesets.go @@ -275,7 +275,7 @@ type RulesetRuleActionParametersAutoMinify struct { type RulesetRuleActionParametersFromValue struct { StatusCode uint16 `json:"status_code,omitempty"` TargetURL RulesetRuleActionParametersTargetURL `json:"target_url"` - PreserveQueryString bool `json:"preserve_query_string,omitempty"` + PreserveQueryString *bool `json:"preserve_query_string,omitempty"` } type RulesetRuleActionParametersTargetURL struct { diff --git a/rulesets_test.go b/rulesets_test.go index c126c723948..52e9ed88ce4 100644 --- a/rulesets_test.go +++ b/rulesets_test.go @@ -523,7 +523,7 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { TargetURL: RulesetRuleActionParametersTargetURL{ Value: "some_host.com", }, - PreserveQueryString: true, + PreserveQueryString: BoolPtr(true), }, }, Description: "Set dynamic redirect from value", diff --git a/turnstile.go b/turnstile.go index 565a36e6ece..84c0bdca5d0 100644 --- a/turnstile.go +++ b/turnstile.go @@ -34,8 +34,7 @@ type CreateTurnstileWidgetParams struct { } type UpdateTurnstileWidgetParams struct { - SiteKey string `json:"sitekey,omitempty"` - Secret string `json:"secret,omitempty"` + SiteKey string `json:"-"` Name string `json:"name,omitempty"` Domains []string `json:"domains,omitempty"` Mode string `json:"mode,omitempty"` @@ -62,8 +61,8 @@ type ListTurnstileWidgetResponse struct { } type RotateTurnstileWidgetParams struct { - SiteKey string - InvalidateImmediately bool `json:"invalidate_immediately,omitempty"` + SiteKey string `json:"-"` + InvalidateImmediately bool `json:"invalidate_immediately,omitempty"` } // CreateTurnstileWidget creates a new challenge widgets. diff --git a/virtualdns.go b/virtualdns.go index ad4ed02575d..d4bc91bd96b 100644 --- a/virtualdns.go +++ b/virtualdns.go @@ -130,7 +130,7 @@ func (v VirtualDNS) vdnsUpgrade() DNSFirewallCluster { return DNSFirewallCluster{ ID: v.ID, Name: v.Name, - OriginIPs: v.OriginIPs, + UpstreamIPs: v.OriginIPs, DNSFirewallIPs: v.VirtualDNSIPs, MinimumCacheTTL: v.MinimumCacheTTL, MaximumCacheTTL: v.MaximumCacheTTL, @@ -147,7 +147,7 @@ func (v *DNSFirewallCluster) vdnsDowngrade() *VirtualDNS { return &VirtualDNS{ ID: v.ID, Name: v.Name, - OriginIPs: v.OriginIPs, + OriginIPs: v.UpstreamIPs, VirtualDNSIPs: v.DNSFirewallIPs, MinimumCacheTTL: v.MinimumCacheTTL, MaximumCacheTTL: v.MaximumCacheTTL, diff --git a/waiting_room.go b/waiting_room.go index a60b5028e34..737e49dc494 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -76,6 +76,12 @@ type WaitingRoomRule struct { Enabled *bool `json:"enabled"` } +// WaitingRoomSettings describes zone-level waiting room settings. +type WaitingRoomSettings struct { + // Whether to allow verified search engine crawlers to bypass all waiting rooms on this zone + SearchEngineCrawlerBypass bool `json:"search_engine_crawler_bypass"` +} + // WaitingRoomPagePreviewURL describes a WaitingRoomPagePreviewURL object. type WaitingRoomPagePreviewURL struct { PreviewURL string `json:"preview_url"` @@ -98,6 +104,12 @@ type WaitingRoomsResponse struct { Result []WaitingRoom `json:"result"` } +// WaitingRoomSettingsResponse is the API response, containing zone-level Waiting Room settings. +type WaitingRoomSettingsResponse struct { + Response + Result WaitingRoomSettings `json:"result"` +} + // WaitingRoomStatusResponse is the API response, containing the status of a waiting room. type WaitingRoomStatusResponse struct { Response @@ -532,3 +544,76 @@ func (api *API) DeleteWaitingRoomRule(ctx context.Context, rc *ResourceContainer return r.Result, nil } + +// GetWaitingRoomSettings fetches the Waiting Room zone-level settings for a zone. +// +// API reference: https://api.cloudflare.com/#waiting-room-get-zone-settings +func (api *API) GetWaitingRoomSettings(ctx context.Context, rc *ResourceContainer) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +type PatchWaitingRoomSettingsParams struct { + SearchEngineCrawlerBypass *bool `json:"search_engine_crawler_bypass,omitempty"` +} + +// PatchWaitingRoomSettings lets you change individual zone-level Waiting Room settings. This is +// in contrast to UpdateWaitingRoomSettings which replaces all settings. +// +// API reference: https://api.cloudflare.com/#waiting-room-patch-zone-settings +func (api *API) PatchWaitingRoomSettings(ctx context.Context, rc *ResourceContainer, params PatchWaitingRoomSettingsParams) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +type UpdateWaitingRoomSettingsParams struct { + SearchEngineCrawlerBypass *bool `json:"search_engine_crawler_bypass,omitempty"` +} + +// UpdateWaitingRoomSettings lets you replace all zone-level Waiting Room settings. This is in contrast to +// PatchWaitingRoomSettings which lets you change individual settings. +// +// API reference: https://api.cloudflare.com/#waiting-room-update-zone-settings +func (api *API) UpdateWaitingRoomSettings(ctx context.Context, rc *ResourceContainer, params UpdateWaitingRoomSettingsParams) (WaitingRoomSettings, error) { + if rc.Level != ZoneRouteLevel { + return WaitingRoomSettings{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + uri := fmt.Sprintf("/zones/%s/waiting_rooms/settings", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return WaitingRoomSettings{}, err + } + var r WaitingRoomSettingsResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WaitingRoomSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} diff --git a/waiting_room_test.go b/waiting_room_test.go index 902510305d5..057789906bf 100644 --- a/waiting_room_test.go +++ b/waiting_room_test.go @@ -97,6 +97,12 @@ var waitingRoomPagePreviewJSON = ` } ` +var waitingRoomSettingsJSON = ` + { + "search_engine_crawler_bypass": true + } + ` + var waitingRoom = WaitingRoom{ ID: waitingRoomID, CreatedOn: testTimestampWaitingRoom, @@ -160,6 +166,18 @@ var waitingRoomRule = WaitingRoomRule{ LastUpdated: &testTimestampWaitingRoom, } +var waitingRoomSettings = WaitingRoomSettings{ + SearchEngineCrawlerBypass: true, +} + +var waitingRoomSettingsUpdate = UpdateWaitingRoomSettingsParams{ + SearchEngineCrawlerBypass: BoolPtr(true), +} + +var waitingRoomSettingsPatch = PatchWaitingRoomSettingsParams{ + SearchEngineCrawlerBypass: BoolPtr(true), +} + func TestListWaitingRooms(t *testing.T) { setup() defer teardown() @@ -785,3 +803,78 @@ func TestReplaceWaitingRoomRules(t *testing.T) { assert.Equal(t, want, actual) } } + +func TestWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.GetWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID)) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.UpdateWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID), waitingRoomSettingsUpdate) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestChangeWaitingRoomSettings(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": %s + } + `, waitingRoomSettingsJSON) + } + + mux.HandleFunc("/zones/"+testZoneID+"/waiting_rooms/settings", handler) + want := waitingRoomSettings + + actual, err := client.PatchWaitingRoomSettings(context.Background(), ZoneIdentifier(testZoneID), waitingRoomSettingsPatch) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} diff --git a/workers.go b/workers.go index 0a983bdc3c4..b934218e693 100644 --- a/workers.go +++ b/workers.go @@ -45,6 +45,8 @@ type CreateWorkerParams struct { // usually used together with CompatibilityDate. // https://developers.cloudflare.com/workers/platform/compatibility-dates/#compatibility-flags CompatibilityFlags []string + + Placement *Placement } // WorkerScriptParams provides a worker script and the associated bindings. @@ -90,11 +92,15 @@ type WorkerScript struct { // WorkerMetaData contains worker script information such as size, creation & modification dates. type WorkerMetaData struct { - ID string `json:"id,omitempty"` - ETAG string `json:"etag,omitempty"` - Size int `json:"size,omitempty"` - CreatedOn time.Time `json:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty"` + ID string `json:"id,omitempty"` + ETAG string `json:"etag,omitempty"` + Size int `json:"size,omitempty"` + CreatedOn time.Time `json:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Logpush *bool `json:"logpush,omitempty"` + LastDeployedFrom *string `json:"last_deployed_from,omitempty"` + DeploymentId *string `json:"deployment_id,omitempty"` + PlacementMode *PlacementMode `json:"placement_mode,omitempty"` } // WorkerListResponse wrapper struct for API response to worker script list API call. @@ -117,6 +123,17 @@ type DeleteWorkerParams struct { ScriptName string } +type PlacementMode string + +const ( + PlacementModeOff PlacementMode = "" + PlacementModeSmart PlacementMode = "smart" +) + +type Placement struct { + Mode PlacementMode `json:"mode"` +} + // DeleteWorker deletes a single Worker. // // API reference: https://api.cloudflare.com/#worker-script-delete-worker @@ -234,7 +251,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params err error ) - if params.Module || params.Logpush != nil || len(params.Bindings) > 0 || params.CompatibilityDate != "" || len(params.CompatibilityFlags) > 0 { + if params.Module || params.Logpush != nil || params.Placement != nil || len(params.Bindings) > 0 || params.CompatibilityDate != "" || len(params.CompatibilityFlags) > 0 { contentType, body, err = formatMultipartBody(params) if err != nil { return WorkerScriptResponse{}, err @@ -274,11 +291,13 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) { Logpush *bool `json:"logpush,omitempty"` CompatibilityDate string `json:"compatibility_date,omitempty"` CompatibilityFlags []string `json:"compatibility_flags,omitempty"` + Placement *Placement `json:"placement,omitempty"` }{ Bindings: make([]workerBindingMeta, 0, len(params.Bindings)), Logpush: params.Logpush, CompatibilityDate: params.CompatibilityDate, CompatibilityFlags: params.CompatibilityFlags, + Placement: params.Placement, } if params.Module { diff --git a/workers_test.go b/workers_test.go index 348abed24a0..8492cdee06d 100644 --- a/workers_test.go +++ b/workers_test.go @@ -211,6 +211,18 @@ export default { } --workermodulescriptdownload-- ` + uploadModuleWorkerSmartPlacement = `{ + "result": { + "script": "export default {\n async fetch(request, env, event) {\n event.passThroughOnException()\n return fetch(request)\n }\n}", + "etag": "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + "size": 191, + "modified_on": "2018-06-09T15:17:01.989141Z", + "placement_mode": "smart" + }, + "success": true, + "errors": [], + "messages": [] +}` ) var ( @@ -280,6 +292,7 @@ type multipartUpload struct { Logpush *bool CompatibilityDate string CompatibilityFlags []string + Placement *Placement } func parseMultipartUpload(r *http.Request) (multipartUpload, error) { @@ -296,6 +309,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { Logpush *bool `json:"logpush,omitempty"` CompatibilityDate string `json:"compatibility_date,omitempty"` CompatibilityFlags []string `json:"compatibility_flags,omitempty"` + Placement *Placement `json:"placement,omitempty"` } err = json.Unmarshal(mdBytes, &metadata) if err != nil { @@ -327,6 +341,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { Logpush: metadata.Logpush, CompatibilityDate: metadata.CompatibilityDate, CompatibilityFlags: metadata.CompatibilityFlags, + Placement: metadata.Placement, }, nil } @@ -933,3 +948,51 @@ func TestUploadWorker_WithQueueBinding(t *testing.T) { }}) assert.NoError(t, err) } + +func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) { + setup() + defer teardown() + + placementMode := PlacementModeSmart + response := uploadModuleWorkerSmartPlacement + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) + + mpUpload, err := parseMultipartUpload(r) + assert.NoError(t, err) + + assert.Equal(t, workerScript, mpUpload.Script) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, response) + } + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) + + t.Run("Test enabling Smart Placement", func(t *testing.T) { + worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + ScriptName: "bar", + Script: workerScript, + Placement: &Placement{ + Mode: placementMode, + }, + }) + assert.NoError(t, err) + assert.Equal(t, placementMode, *worker.PlacementMode) + }) + + t.Run("Test disabling placement", func(t *testing.T) { + placementMode = PlacementModeOff + response = uploadWorkerModuleResponseData + + worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + ScriptName: "bar", + Script: workerScript, + Placement: &Placement{ + Mode: placementMode, + }, + }) + assert.NoError(t, err) + assert.Nil(t, worker.PlacementMode) + }) +}