From 0ed26113c22270838210166a800ef06a00853597 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Fri, 11 Nov 2022 22:13:54 -0500 Subject: [PATCH 001/370] Add support for challenge widget API --- challenge_widgets.go | 210 ++++++++++++++++++++++++++ challenge_widgets_test.go | 307 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 517 insertions(+) create mode 100644 challenge_widgets.go create mode 100644 challenge_widgets_test.go diff --git a/challenge_widgets.go b/challenge_widgets.go new file mode 100644 index 0000000000..8527c78d88 --- /dev/null +++ b/challenge_widgets.go @@ -0,0 +1,210 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "time" +) + +var ErrMissingSiteKey = errors.New("required site key missing") + +type ChallengeWidget struct { + SiteKey string `json:"sitekey"` + Secret string `json:"secret,omitempty"` + CreatedOn *time.Time `json:"created_on,omitempty"` + ModifiedOn *time.Time `json:"modified_on,omitempty"` + Name string `json:"name"` + Domains []string `json:"domains"` + Type string `json:"type"` +} + +type ChallengeWidgetResponse struct { + Response + Result ChallengeWidget `json:"result"` +} + +type ListChallengeWidgetRequest struct { + ResultInfo + Direction string `url:"direction,omitempty"` + Order string `url:"order,omitempty"` +} + +type ListChallengeWidgetResponse struct { + Response + ResultInfo `json:"result_info"` + Result []ChallengeWidget `json:"result"` +} + +type RotateChallengeWidgetRequest struct { + SiteKey string + InvalidateImmediately bool `json:"invalidate_immediately,omitempty"` +} + +// CreateChallengeWidget creates a new challenge widgets. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-properties +func (api *API) CreateChallengeWidget(ctx context.Context, rc *ResourceContainer, params ChallengeWidget) (ChallengeWidget, error) { + if rc.Identifier == "" { + return ChallengeWidget{}, ErrMissingAccountID + } + uri := fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier) + res, err := api.makeRequestContext(ctx, "POST", uri, params) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + var r ChallengeWidgetResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// ListChallengeWidget lists challenge widgets. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-list-challenge-widgets +func (api *API) ListChallengeWidget(ctx context.Context, rc *ResourceContainer, params ListChallengeWidgetRequest) ([]ChallengeWidget, *ResultInfo, error) { + if rc.Identifier == "" { + return []ChallengeWidget{}, &ResultInfo{}, ErrMissingAccountID + } + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } + + if params.PerPage < 1 { + params.PerPage = 50 + } + + if params.Page < 1 { + params.Page = 1 + } + + var widgets []ChallengeWidget + var r ListChallengeWidgetResponse + for { + uri := buildURI(fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier), params) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []ChallengeWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + err = json.Unmarshal(res, &r) + if err != nil { + return []ChallengeWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + widgets = append(widgets, r.Result...) + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } + } + + return widgets, &r.ResultInfo, nil +} + +// GetChallengeWidget shows a single challenge widget configuration.. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-challenge-widget-details +func (api *API) GetChallengeWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) (ChallengeWidget, error) { + if rc.Identifier == "" { + return ChallengeWidget{}, ErrMissingAccountID + } + + if SiteKey == "" { + return ChallengeWidget{}, ErrMissingSiteKey + } + + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, SiteKey) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + var r ChallengeWidgetResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return r.Result, nil +} + +// UpdateChallengeWidget update the configuration of a widget. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-update-a-challenge-widget +func (api *API) UpdateChallengeWidget(ctx context.Context, rc *ResourceContainer, widget ChallengeWidget) (ChallengeWidget, error) { + if rc.Identifier == "" { + return ChallengeWidget{}, ErrMissingAccountID + } + if widget.SiteKey == "" { + return ChallengeWidget{}, ErrMissingSiteKey + } + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, widget.SiteKey) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, widget) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + var r ChallengeWidgetResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// RotateChallengeWidget generates a new secret key for this widget. If invalidate_immediately is set to false, the previous secret remains valid for 2 hours. +// +// Note that secrets cannot be rotated again during the grace period. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-rotate-secret-for-a-challenge-widget +func (api *API) RotateChallengeWidget(ctx context.Context, rc *ResourceContainer, param RotateChallengeWidgetRequest) (ChallengeWidget, error) { + if rc.Identifier == "" { + return ChallengeWidget{}, ErrMissingAccountID + } + if param.SiteKey == "" { + return ChallengeWidget{}, ErrMissingSiteKey + } + + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s/rotate_secret", rc.Identifier, param.SiteKey) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, param) + + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + var r ChallengeWidgetResponse + err = json.Unmarshal(res, &r) + if err != nil { + return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// DeleteChallengeWidget delete a challenge widget. +// +// API reference: https://api.cloudflare.com/#challenge-widgets-delete-a-challenge-widget +func (api *API) DeleteChallengeWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) error { + if rc.Identifier == "" { + return ErrMissingAccountID + } + + if SiteKey == "" { + return ErrMissingSiteKey + } + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, SiteKey) + + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + var r ChallengeWidgetResponse + err = json.Unmarshal(res, &r) + if err != nil { + return fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return nil +} diff --git a/challenge_widgets_test.go b/challenge_widgets_test.go new file mode 100644 index 0000000000..bdc19a8c05 --- /dev/null +++ b/challenge_widgets_test.go @@ -0,0 +1,307 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +const testChallengeWidgetSiteKey = "0x4AAF00AAAABn0R22HWm-YUc" + +var ( + challengeWidgetCreatedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") + challengeWidgetModifiedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") + expectedChallengeWidget = ChallengeWidget{ + SiteKey: "0x4AAF00AAAABn0R22HWm-YUc", + Secret: "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + CreatedOn: &challengeWidgetCreatedOn, + ModifiedOn: &challengeWidgetModifiedOn, + Name: "blog.cloudflare.com login form", + Domains: []string{ + "203.0.113.1", + "cloudflare.com", + "blog.example.com", + }, + Type: "invisible", + } +) + +func TestChallengeWidgets_Create(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } +}`) + }) + + // Make sure missing account ID is thrown + _, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(""), ChallengeWidget{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + out, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{ + Name: "blog.cloudflare.com login form", + Type: "invisible", + Domains: []string{ + "203.0.113.1", + "cloudflare.com", + "blog.example.com", + }, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedChallengeWidget, out, "create challenge_widgets structs not equal") + } +} + +func TestChallengeWidgets_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets", 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.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } + ], + "result_info": { + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 2000 + } +}`) + }) + + _, _, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(""), ListChallengeWidgetRequest{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + out, results, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ListChallengeWidgetRequest{}) + if assert.NoError(t, err) { + assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") + assert.Equal(t, 20, results.PerPage, "expected 20 per page") + assert.Equal(t, expectedChallengeWidget, out[0], "list challenge_widgets structs not equal") + } +} + +func TestChallengeWidgets_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, 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.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } +}`) + }) + + _, err := client.GetChallengeWidget(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.GetChallengeWidget(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingSiteKey, err) + } + + out, err := client.GetChallengeWidget(context.Background(), AccountIdentifier(testAccountID), testChallengeWidgetSiteKey) + + if assert.NoError(t, err) { + assert.Equal(t, expectedChallengeWidget, out, "get challenge_widgets structs not equal") + } +} + +func TestChallengeWidgets_Update(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, 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.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } +}`) + }) + + _, err := client.UpdateChallengeWidget(context.Background(), AccountIdentifier(""), ChallengeWidget{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.UpdateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingSiteKey, err) + } + + out, err := client.UpdateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{ + SiteKey: testChallengeWidgetSiteKey, + }) + if assert.NoError(t, err) { + assert.Equal(t, expectedChallengeWidget, out, "update challenge_widgets structs not equal") + } +} + +func TestChallengeWidgets_RotateSecret(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey+"/rotate_secret", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } +}`) + }) + + // Make sure missing account ID is thrown + _, err := client.RotateChallengeWidget(context.Background(), AccountIdentifier(""), RotateChallengeWidgetRequest{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.RotateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), RotateChallengeWidgetRequest{}) + if assert.Error(t, err) { + assert.Equal(t, ErrMissingSiteKey, err) + } + + out, err := client.RotateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), RotateChallengeWidgetRequest{SiteKey: testChallengeWidgetSiteKey}) + if assert.NoError(t, err) { + assert.Equal(t, expectedChallengeWidget, out, "rotate challenge_widgets structs not equal") + } +} + +func TestChallengeWidgets_Delete(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, ` +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } +}`) + }) + + // Make sure missing account ID is thrown + err := client.DeleteChallengeWidget(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + err = client.DeleteChallengeWidget(context.Background(), AccountIdentifier(testAccountID), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingSiteKey, err) + } + + err = client.DeleteChallengeWidget(context.Background(), AccountIdentifier(testAccountID), testChallengeWidgetSiteKey) + assert.NoError(t, err) +} From 45e1f93e372e4a31ba050e7a73c4aba69cf1973d Mon Sep 17 00:00:00 2001 From: Jacob White Date: Fri, 11 Nov 2022 22:19:25 -0500 Subject: [PATCH 002/370] Add goimports to internal/tools/tools.go and update golangci-lint to latest to include reassign linter --- internal/tools/go.mod | 2 +- internal/tools/tools.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 1dfd729e85..7c9d09a222 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -8,7 +8,7 @@ require ( github.com/curioswitch/go-reassign v0.2.0 github.com/cweill/gotests v1.6.0 github.com/go-delve/delve v1.9.0 - github.com/golangci/golangci-lint v1.48.0 + github.com/golangci/golangci-lint v1.50.1 github.com/google/go-github v17.0.0+incompatible github.com/hashicorp/go-changelog v0.0.0-20220419201213-5edfc0d651d8 github.com/jgautheron/goconst v1.5.1 diff --git a/internal/tools/tools.go b/internal/tools/tools.go index 336d01f4f9..4a0baee4de 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -19,6 +19,7 @@ package tools //go:generate go install golang.org/x/lint/golint //go:generate go install golang.org/x/oauth2 //go:generate go install golang.org/x/tools/gopls@latest +//go:generate go install golang.org/x/tools/cmd/goimports@latest import ( // local development tooling for linting and debugging. @@ -35,6 +36,7 @@ import ( _ "github.com/securego/gosec/v2/cmd/gosec" _ "github.com/uudashr/gopkgs/v2/cmd/gopkgs" _ "golang.org/x/lint/golint" + _ "golang.org/x/tools/cmd/goimports" _ "golang.org/x/tools/gopls" // used for changelog-check tooling From 376aee74a724c56074e59a7754078f5a24ea3584 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Sat, 12 Nov 2022 18:51:52 -0500 Subject: [PATCH 003/370] Add omitempty to SiteKey --- challenge_widgets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge_widgets.go b/challenge_widgets.go index 8527c78d88..77978618fc 100644 --- a/challenge_widgets.go +++ b/challenge_widgets.go @@ -12,7 +12,7 @@ import ( var ErrMissingSiteKey = errors.New("required site key missing") type ChallengeWidget struct { - SiteKey string `json:"sitekey"` + SiteKey string `json:"sitekey,omitempty"` Secret string `json:"secret,omitempty"` CreatedOn *time.Time `json:"created_on,omitempty"` ModifiedOn *time.Time `json:"modified_on,omitempty"` From e8e9f5e104f5e00ea2e5291c54bd1773e19ee6be Mon Sep 17 00:00:00 2001 From: Jacob White Date: Sat, 12 Nov 2022 18:54:40 -0500 Subject: [PATCH 004/370] Add changelog --- .changelog/XXXX.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/XXXX.txt diff --git a/.changelog/XXXX.txt b/.changelog/XXXX.txt new file mode 100644 index 0000000000..24d83ff734 --- /dev/null +++ b/.changelog/XXXX.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +challenge_widget: add support for the challenge widget API +``` From 3d6d7611efecdcd6d3d8d6f78262f7bdeee585d9 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 30 Nov 2022 02:30:48 +0000 Subject: [PATCH 005/370] Update for Functions GA --- pages_deployment_test.go | 65 ++--------------------------- pages_project.go | 61 +++++++++++++++++++++------ pages_project_test.go | 90 ++++++++++++++++++++++++++++++++-------- 3 files changed, 123 insertions(+), 93 deletions(-) diff --git a/pages_deployment_test.go b/pages_deployment_test.go index 9696d74382..282710a0cf 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -91,54 +91,6 @@ const ( "aliases": null }` - testPagesDeploymentStageLogsResponse = ` - { - "name": "build", - "started_on": "2021-01-01T00:00:00Z", - "ended_on": "2021-01-01T00:00:00Z", - "status": "success", - "start": 0, - "end": 5, - "total": 6, - "data": [ - { - "id": 0, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Installing dependencies" - }, - { - "id": 1, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Verify run directory" - }, - { - "id": 2, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Executing user command: bash test.sh" - }, - { - "id": 3, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Finished" - }, - { - "id": 4, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Building functions..." - }, - { - "id": 5, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Validating asset output directory" - }, - { - "id": 6, - "timestamp": "2021-01-01T00:00:00Z", - "message": "Parsed 2 valid header rules." - } - ] - }` - testPagesDeploymentLogsResponse = ` { "total": 6, @@ -190,9 +142,9 @@ var ( ModifiedOn: &pagesDeploymentDummyTime, Aliases: nil, LatestStage: *expectedPagesDeploymentLatestStage, - EnvVars: map[string]map[string]string{ - "NODE_VERSION": { - "value": "16", + EnvVars: EnvironmentVariableMap{ + "NODE_VERSION": &EnvironmentVariable{ + Value: "16", }, }, DeploymentTrigger: PagesProjectDeploymentTrigger{ @@ -255,17 +207,6 @@ var ( Status: "success", } - expectedPagesDeploymentStageLogs = &PagesDeploymentStageLogs{ - Name: "build", - StartedOn: &pagesDeploymentDummyTime, - EndedOn: &pagesDeploymentDummyTime, - Status: "success", - Start: 0, - End: 5, - Total: 6, - Data: expectedPagesDeploymentStageLogEntries, - } - expectedPagesDeploymentStageLogEntries = []PagesDeploymentStageLogEntry{ { ID: 0, diff --git a/pages_project.go b/pages_project.go index 753c1eb8d8..3177a8e0f8 100644 --- a/pages_project.go +++ b/pages_project.go @@ -67,18 +67,17 @@ type PagesProjectDeploymentConfigs struct { // PagesProjectDeploymentConfigEnvironment represents the configuration for preview or production deploys. type PagesProjectDeploymentConfigEnvironment struct { - EnvVars map[string]PagesProjectDeploymentVar `json:"env_vars"` - CompatibilityDate string `json:"compatibility_date,omitempty"` - CompatibilityFlags []string `json:"compatibility_flags,omitempty"` - KvNamespaces NamespaceBindingMap `json:"kv_namespaces,omitempty"` - DoNamespaces NamespaceBindingMap `json:"durable_object_namespaces,omitempty"` - D1Databases D1BindingMap `json:"d1_databases,omitempty"` - R2Bindings R2BindingMap `json:"r2_buckets,omitempty"` -} - -// PagesProjectDeploymentVar represents a deployment environment variable. -type PagesProjectDeploymentVar struct { - Value string `json:"value"` + EnvVars EnvironmentVariableMap `json:"env_vars,omitempty"` + KvNamespaces NamespaceBindingMap `json:"kv_namespaces,omitempty"` + DoNamespaces NamespaceBindingMap `json:"durable_object_namespaces,omitempty"` + D1Databases D1BindingMap `json:"d1_databases,omitempty"` + R2Bindings R2BindingMap `json:"r2_buckets,omitempty"` + ServiceBindings ServiceBindingMap `json:"services,omitempty"` + CompatibilityDate string `json:"compatibility_date,omitempty"` + CompatibilityFlags []string `json:"compatibility_flags,omitempty"` + FailOpen bool `json:"fail_open"` + AlwaysUseLatestCompatibilityDate bool `json:"always_use_latest_compatibility_date"` + UsageModel UsageModel `json:"usage_model,omitempty"` } // PagesProjectDeployment represents a deployment to a Pages project. @@ -93,13 +92,20 @@ type PagesProjectDeployment struct { ModifiedOn *time.Time `json:"modified_on"` Aliases []string `json:"aliases,omitempty"` LatestStage PagesProjectDeploymentStage `json:"latest_stage"` - EnvVars map[string]map[string]string `json:"env_vars"` + EnvVars EnvironmentVariableMap `json:"env_vars"` + KvNamespaces NamespaceBindingMap `json:"kv_namespaces,omitempty"` + DoNamespaces NamespaceBindingMap `json:"durable_object_namespaces,omitempty"` + D1Databases D1BindingMap `json:"d1_databases,omitempty"` + R2Bindings R2BindingMap `json:"r2_buckets,omitempty"` + ServiceBindings ServiceBindingMap `json:"services,omitempty"` DeploymentTrigger PagesProjectDeploymentTrigger `json:"deployment_trigger"` Stages []PagesProjectDeploymentStage `json:"stages"` BuildConfig PagesProjectBuildConfig `json:"build_config"` Source PagesProjectSource `json:"source"` CompatibilityDate string `json:"compatibility_date,omitempty"` CompatibilityFlags []string `json:"compatibility_flags,omitempty"` + UsageModel UsageModel `json:"usage_model,omitempty"` + IsSkipped bool `json:"is_skipped"` ProductionBranch string `json:"production_branch,omitempty"` } @@ -135,6 +141,21 @@ type pagesProjectListResponse struct { ResultInfo `json:"result_info"` } +type EnvironmentVariableMap map[string]*EnvironmentVariable + +// PagesProjectDeploymentVar represents a deployment environment variable. +type EnvironmentVariable struct { + Value string `json:"value"` + Type EnvVarType `json:"type"` +} + +type EnvVarType string + +const ( + PlainText EnvVarType = "plain_text" + SecretText EnvVarType = "secret_text" +) + type NamespaceBindingMap map[string]*NamespaceBindingValue type NamespaceBindingValue struct { @@ -153,6 +174,20 @@ type D1Binding struct { ID string `json:"id"` } +type ServiceBindingMap map[string]*ServiceBinding + +type ServiceBinding struct { + Service string `json:"service"` + Environment string `json:"environment"` +} + +type UsageModel string + +const ( + Bundled UsageModel = "bundled" + Unbound UsageModel = "unbound" +) + // ListPagesProjects returns all Pages projects for an account. // // API reference: https://api.cloudflare.com/#pages-project-get-projects diff --git a/pages_project_test.go b/pages_project_test.go index 0dffd3c30a..91671a5d5c 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -58,7 +58,11 @@ const ( }, "ENV": { "value": "preview" - } + }, + "API_KEY": { + "value": "", + "type": "secret_text" + } }, "compatibility_date": "2022-08-15", "compatibility_flags": ["preview_flag"] @@ -70,7 +74,11 @@ const ( }, "ENV": { "value": "production" - } + }, + "API_KEY": { + "value": "", + "type": "secret_text" + } }, "d1_databases": { "D1_BINDING": { @@ -92,8 +100,17 @@ const ( "name": "some-bucket" } }, + "services": { + "SERVICE_BINDING": { + "service": "some-worker", + "environment": "production" + } + }, "compatibility_date": "2022-08-15", - "compatibility_flags": ["production_flag"] + "compatibility_flags": ["production_flag"], + "fail_open": false, + "always_use_latest_compatibility_date": false, + "usage_model": "bundled" } }, "latest_deployment": { @@ -121,10 +138,17 @@ const ( }, "ENV": { "value": "STAGING" - } + }, + "API_KEY": { + "value": "", + "type": "secret_text" + } }, "compatibility_date": "2022-08-15", "compatibility_flags": ["deployment_flag"], + "fail_open": false, + "always_use_latest_compatibility_date": false, + "usage_model": "bundled", "deployment_trigger": { "type": "ad_hoc", "metadata": { @@ -201,10 +225,18 @@ const ( }, "ENV": { "value": "STAGING" - } + }, + "API_KEY": { + "value": "", + "type": "secret_text" + } }, "compatibility_date": "2022-08-15", "compatibility_flags": ["deployment_flag"], + "fail_open": false, + "always_use_latest_compatibility_date": false, + "build_image_major_version": 1, + "usage_model": "bundled", "deployment_trigger": { "type": "ad_hoc", "metadata": { @@ -295,16 +327,21 @@ var ( "https://branchname.pages-test.pages.dev", }, LatestStage: *expectedPagesProjectLatestDeploymentStage, - EnvVars: map[string]map[string]string{ - "BUILD_VERSION": { - "value": "1.2", + EnvVars: EnvironmentVariableMap{ + "BUILD_VERSION": &EnvironmentVariable{ + Value: "1.2", + }, + "ENV": &EnvironmentVariable{ + Value: "STAGING", }, - "ENV": { - "value": "STAGING", + "API_KEY": &EnvironmentVariable{ + Value: "", + Type: SecretText, }, }, CompatibilityFlags: []string{"deployment_flag"}, CompatibilityDate: "2022-08-15", + UsageModel: Bundled, DeploymentTrigger: *expectedPagesProjectDeploymentTrigger, Stages: expectedStages, BuildConfig: *expectedPagesProjectBuildConfig, @@ -363,29 +400,35 @@ var ( } expectedPagesProjectDeploymentConfigPreview = &PagesProjectDeploymentConfigEnvironment{ - EnvVars: map[string]PagesProjectDeploymentVar{ - "BUILD_VERSION": { + EnvVars: EnvironmentVariableMap{ + "BUILD_VERSION": &EnvironmentVariable{ Value: "1.2", }, - "ENV": { + "ENV": &EnvironmentVariable{ Value: "preview", }, + "API_KEY": &EnvironmentVariable{ + Value: "", + Type: SecretText, + }, }, CompatibilityDate: "2022-08-15", CompatibilityFlags: []string{"preview_flag"}, } expectedPagesProjectDeploymentConfigProduction = &PagesProjectDeploymentConfigEnvironment{ - EnvVars: map[string]PagesProjectDeploymentVar{ - "BUILD_VERSION": { + EnvVars: EnvironmentVariableMap{ + "BUILD_VERSION": &EnvironmentVariable{ Value: "1.2", }, - "ENV": { + "ENV": &EnvironmentVariable{ Value: "production", }, + "API_KEY": &EnvironmentVariable{ + Value: "", + Type: SecretText, + }, }, - CompatibilityDate: "2022-08-15", - CompatibilityFlags: []string{"production_flag"}, KvNamespaces: NamespaceBindingMap{ "KV_BINDING": &NamespaceBindingValue{Value: "5eb63bbbe01eeed093cb22bb8f5acdc3"}, }, @@ -398,6 +441,17 @@ var ( R2Bindings: R2BindingMap{ "R2_BINDING": &R2BindingValue{Name: "some-bucket"}, }, + ServiceBindings: ServiceBindingMap{ + "SERVICE_BINDING": &ServiceBinding{ + Service: "some-worker", + Environment: "production", + }, + }, + CompatibilityDate: "2022-08-15", + CompatibilityFlags: []string{"production_flag"}, + FailOpen: false, + AlwaysUseLatestCompatibilityDate: false, + UsageModel: Bundled, } expectedPagesProjectSource = &PagesProjectSource{ From 3c5cdcc66798bebc7c606537a7e8345d97ba2821 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 30 Nov 2022 02:37:44 +0000 Subject: [PATCH 006/370] Changelog --- .changelog/1136.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/1136.txt diff --git a/.changelog/1136.txt b/.changelog/1136.txt new file mode 100644 index 0000000000..976f76ea7c --- /dev/null +++ b/.changelog/1136.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +pages: Updates bindings and other Functions related propreties. Service bindings, secrets, fail open/close and usage model are all now supported. +``` + +```release-note:breaking-change +pages: Changed the type of EnvVars in PagesProjectDeploymentConfigEnvironment & PagesProjectDeployment in order to properly support secrets. +``` From b22e823308236f8d44b60fa70ab04dfec336a94f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 25 Nov 2022 16:01:41 +1100 Subject: [PATCH 007/370] workers: split into separate files and modernise standard Worker methods --- workers.go | 767 ++++------------------------------------ workers_bindings.go | 455 ++++++++++++++++++++++++ workers_domains.go | 48 +++ workers_example_test.go | 400 ++++++++++----------- workers_routes.go | 154 ++++++++ workers_routes_test.go | 348 ++++++++++++++++++ workers_test.go | 697 +++++------------------------------- 7 files changed, 1361 insertions(+), 1508 deletions(-) create mode 100644 workers_bindings.go create mode 100644 workers_domains.go create mode 100644 workers_routes.go create mode 100644 workers_routes_test.go diff --git a/workers.go b/workers.go index 7bc6e9a42d..b762acad8f 100644 --- a/workers.go +++ b/workers.go @@ -3,10 +3,7 @@ package cloudflare import ( "bytes" "context" - rand "crypto/rand" - "encoding/hex" "encoding/json" - "errors" "fmt" "io" "mime" @@ -23,6 +20,19 @@ type WorkerRequestParams struct { ScriptName string } +type CreateWorkerParams struct { + Name string + Script string + + // Module changes the Content-Type header to specify the script is an + // ES Module syntax script. + Module bool + + // Bindings should be a map where the keys are the binding name, and the + // values are the binding content + Bindings map[string]WorkerBinding +} + // WorkerScriptParams provides a worker script and the associated bindings. type WorkerScriptParams struct { Script string @@ -40,9 +50,7 @@ type WorkerScriptParams struct { // // API reference: https://api.cloudflare.com/#worker-routes-properties type WorkerRoute struct { - ID string `json:"id,omitempty"` Pattern string `json:"pattern"` - Enabled bool `json:"enabled"` // this is deprecated: https://api.cloudflare.com/#worker-filters-deprecated--properties Script string `json:"script,omitempty"` } @@ -87,375 +95,46 @@ type WorkerScriptResponse struct { WorkerScript `json:"result"` } -// WorkerBindingType represents a particular type of binding. -type WorkerBindingType string - -func (b WorkerBindingType) String() string { - return string(b) -} - -const ( - // WorkerDurableObjectBindingType is the type for Durable Object bindings. - WorkerDurableObjectBindingType WorkerBindingType = "durable_object_namespace" - // WorkerInheritBindingType is the type for inherited bindings. - WorkerInheritBindingType WorkerBindingType = "inherit" - // WorkerKvNamespaceBindingType is the type for KV Namespace bindings. - WorkerKvNamespaceBindingType WorkerBindingType = "kv_namespace" - // WorkerWebAssemblyBindingType is the type for Web Assembly module bindings. - WorkerWebAssemblyBindingType WorkerBindingType = "wasm_module" - // WorkerSecretTextBindingType is the type for secret text bindings. - WorkerSecretTextBindingType WorkerBindingType = "secret_text" - // WorkerPlainTextBindingType is the type for plain text bindings. - WorkerPlainTextBindingType WorkerBindingType = "plain_text" - // WorkerServiceBindingType is the type for service bindings. - WorkerServiceBindingType WorkerBindingType = "service" - // WorkerR2BucketBindingType is the type for R2 bucket bindings. - WorkerR2BucketBindingType WorkerBindingType = "r2_bucket" - // WorkerAnalyticsEngineBindingType is the type for Analytics Engine dataset bindings. - WorkerAnalyticsEngineBindingType WorkerBindingType = "analytics_engine" -) - -// WorkerBindingListItem a struct representing an individual binding in a list of bindings. -type WorkerBindingListItem struct { - Name string `json:"name"` - Binding WorkerBinding -} - -// WorkerBindingListResponse wrapper struct for API response to worker binding list API call. -type WorkerBindingListResponse struct { - Response - BindingList []WorkerBindingListItem -} - -// Workers supports multiple types of bindings, e.g. KV namespaces or WebAssembly modules, and each type -// of binding will be represented differently in the upload request body. At a high-level, every binding -// will specify metadata, which is a JSON object with the properties "name" and "type". Some types of bindings -// will also have additional metadata properties. For example, KV bindings also specify the KV namespace. -// In addition to the metadata, some binding types may need to include additional data as part of the -// multipart form. For example, WebAssembly bindings will include the contents of the WebAssembly module. - -// WorkerBinding is the generic interface implemented by all of -// the various binding types. -type WorkerBinding interface { - Type() WorkerBindingType - - // serialize is responsible for returning the binding metadata as well as an optionally - // returning a function that can modify the multipart form body. For example, this is used - // by WebAssembly bindings to add a new part containing the WebAssembly module contents. - serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) -} - -// workerBindingMeta is the metadata portion of the binding. -type workerBindingMeta = map[string]interface{} - -// workerBindingBodyWriter allows for a binding to add additional parts to the multipart body. -type workerBindingBodyWriter func(*multipart.Writer) error - -// WorkerInheritBinding will just persist whatever binding content was previously uploaded. -type WorkerInheritBinding struct { - // Optional parameter that allows for renaming a binding without changing - // its contents. If `OldName` is empty, the binding name will not be changed. - OldName string -} - -// Type returns the type of the binding. -func (b WorkerInheritBinding) Type() WorkerBindingType { - return WorkerInheritBindingType -} - -func (b WorkerInheritBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - meta := workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - } - - if b.OldName != "" { - meta["old_name"] = b.OldName - } - - return meta, nil, nil -} - -// WorkerKvNamespaceBinding is a binding to a Workers KV Namespace -// -// https://developers.cloudflare.com/workers/archive/api/resource-bindings/kv-namespaces/ -type WorkerKvNamespaceBinding struct { - NamespaceID string -} +type ListWorkersParams struct{} -// Type returns the type of the binding. -func (b WorkerKvNamespaceBinding) Type() WorkerBindingType { - return WorkerKvNamespaceBindingType -} - -func (b WorkerKvNamespaceBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.NamespaceID == "" { - return nil, nil, fmt.Errorf(`NamespaceID for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "namespace_id": b.NamespaceID, - }, nil, nil -} - -// WorkerDurableObjectBinding is a binding to a Workers Durable Object -// -// https://api.cloudflare.com/#durable-objects-namespace-properties -type WorkerDurableObjectBinding struct { - ClassName string +type DeleteWorkerParams struct { ScriptName string } -// Type returns the type of the binding. -func (b WorkerDurableObjectBinding) Type() WorkerBindingType { - return WorkerDurableObjectBindingType -} - -func (b WorkerDurableObjectBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.ClassName == "" { - return nil, nil, fmt.Errorf(`ClassName for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "class_name": b.ClassName, - "script_name": b.ScriptName, - }, nil, nil -} - -// WorkerWebAssemblyBinding is a binding to a WebAssembly module -// -// https://developers.cloudflare.com/workers/archive/api/resource-bindings/webassembly-modules/ -type WorkerWebAssemblyBinding struct { - Module io.Reader -} - -// Type returns the type of the binding. -func (b WorkerWebAssemblyBinding) Type() WorkerBindingType { - return WorkerWebAssemblyBindingType -} - -func (b WorkerWebAssemblyBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - partName := getRandomPartName() - - bodyWriter := func(mpw *multipart.Writer) error { - var hdr = textproto.MIMEHeader{} - hdr.Set("content-disposition", fmt.Sprintf(`form-data; name="%s"`, partName)) - hdr.Set("content-type", "application/wasm") - pw, err := mpw.CreatePart(hdr) - if err != nil { - return err - } - _, err = io.Copy(pw, b.Module) - return err - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "part": partName, - }, bodyWriter, nil -} - -// WorkerPlainTextBinding is a binding to plain text -// -// https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-plain-text-binding -type WorkerPlainTextBinding struct { - Text string -} - -// Type returns the type of the binding. -func (b WorkerPlainTextBinding) Type() WorkerBindingType { - return WorkerPlainTextBindingType -} - -func (b WorkerPlainTextBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.Text == "" { - return nil, nil, fmt.Errorf(`Text for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "text": b.Text, - }, nil, nil -} - -// WorkerSecretTextBinding is a binding to secret text -// -// https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-secret-text-binding -type WorkerSecretTextBinding struct { - Text string -} - -// Type returns the type of the binding. -func (b WorkerSecretTextBinding) Type() WorkerBindingType { - return WorkerSecretTextBindingType -} - -func (b WorkerSecretTextBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.Text == "" { - return nil, nil, fmt.Errorf(`Text for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "text": b.Text, - }, nil, nil -} - -type WorkerServiceBinding struct { - Service string - Environment *string -} - -func (b WorkerServiceBinding) Type() WorkerBindingType { - return WorkerServiceBindingType -} - -func (b WorkerServiceBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.Service == "" { - return nil, nil, fmt.Errorf(`Service for binding "%s" cannot be empty`, bindingName) - } - - meta := workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "service": b.Service, - } - - if b.Environment != nil { - meta["environment"] = *b.Environment - } - - return meta, nil, nil -} - -// WorkerR2BucketBinding is a binding to an R2 bucket. -type WorkerR2BucketBinding struct { - BucketName string -} - -// Type returns the type of the binding. -func (b WorkerR2BucketBinding) Type() WorkerBindingType { - return WorkerR2BucketBindingType -} - -func (b WorkerR2BucketBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.BucketName == "" { - return nil, nil, fmt.Errorf(`BucketName for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "bucket_name": b.BucketName, - }, nil, nil -} - -// WorkerAnalyticsEngineBinding is a binding to an Analytics Engine dataset. -type WorkerAnalyticsEngineBinding struct { - Dataset string -} - -// Type returns the type of the binding. -func (b WorkerAnalyticsEngineBinding) Type() WorkerBindingType { - return WorkerAnalyticsEngineBindingType -} - -func (b WorkerAnalyticsEngineBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { - if b.Dataset == "" { - return nil, nil, fmt.Errorf(`Dataset for binding "%s" cannot be empty`, bindingName) - } - - return workerBindingMeta{ - "name": bindingName, - "type": b.Type(), - "dataset": b.Dataset, - }, nil, nil -} - -// Each binding that adds a part to the multipart form body will need -// a unique part name so we just generate a random 128bit hex string. -func getRandomPartName() string { - randBytes := make([]byte, 16) - rand.Read(randBytes) //nolint:errcheck - return hex.EncodeToString(randBytes) -} - // DeleteWorker deletes worker for a zone. // // API reference: https://api.cloudflare.com/#worker-script-delete-worker -func (api *API) DeleteWorker(ctx context.Context, requestParams *WorkerRequestParams) (WorkerScriptResponse, error) { - // if ScriptName is provided we will treat as org request - if requestParams.ScriptName != "" { - return api.deleteWorkerWithName(ctx, requestParams.ScriptName) - } - uri := fmt.Sprintf("/zones/%s/workers/script", requestParams.ZoneID) +func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params DeleteWorkerParams) error { + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, params.ScriptName) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + var r WorkerScriptResponse if err != nil { - return r, err + return err } + err = json.Unmarshal(res, &r) if err != nil { - return r, fmt.Errorf("%s: %w", errUnmarshalError, err) + return fmt.Errorf("%s: %w", errUnmarshalError, err) } - return r, nil + + return nil } -// DeleteWorkerWithName deletes worker for a zone. -// Sccount must be specified as api option https://godoc.org/github.com/cloudflare/cloudflare-go#UsingAccount +// GetWorker fetch raw script content for your worker returns string containing +// worker code js. // // API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/ -func (api *API) deleteWorkerWithName(ctx context.Context, scriptName string) (WorkerScriptResponse, error) { - if api.AccountID == "" { - return WorkerScriptResponse{}, errors.New("account ID required") - } - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", api.AccountID, scriptName) - res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) - var r WorkerScriptResponse - if err != nil { - return r, err - } - err = json.Unmarshal(res, &r) - if err != nil { - return r, fmt.Errorf("%s: %w", errUnmarshalError, err) +func (api *API) GetWorker(ctx context.Context, rc *ResourceContainer, scriptName string) (WorkerScriptResponse, error) { + if rc.Level != AccountRouteLevel { + return WorkerScriptResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) } - return r, nil -} -// DownloadWorker fetch raw script content for your worker returns []byte containing worker code js -// -// API reference: https://api.cloudflare.com/#worker-script-download-worker -func (api *API) DownloadWorker(ctx context.Context, requestParams *WorkerRequestParams) (WorkerScriptResponse, error) { - if requestParams.ScriptName != "" { - return api.downloadWorkerWithName(ctx, requestParams.ScriptName) - } - uri := fmt.Sprintf("/zones/%s/workers/script", requestParams.ZoneID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - var r WorkerScriptResponse - if err != nil { - return r, err + if rc.Identifier == "" { + return WorkerScriptResponse{}, ErrMissingIdentifier } - r.Script = string(res) - r.Module = false - r.Success = true - return r, nil -} -// DownloadWorkerWithName fetch raw script content for your worker returns string containing worker code js -// -// API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/ -func (api *API) downloadWorkerWithName(ctx context.Context, scriptName string) (WorkerScriptResponse, error) { - if api.AccountID == "" { - return WorkerScriptResponse{}, errors.New("account ID required") - } - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", api.AccountID, scriptName) + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, scriptName) res, err := api.makeRequestContextWithHeadersComplete(ctx, http.MethodGet, uri, nil, nil) var r WorkerScriptResponse if err != nil { @@ -486,233 +165,96 @@ func (api *API) downloadWorkerWithName(ctx context.Context, scriptName string) ( return r, nil } -// ListWorkerBindings returns all the bindings for a particular worker. -func (api *API) ListWorkerBindings(ctx context.Context, requestParams *WorkerRequestParams) (WorkerBindingListResponse, error) { - if requestParams.ScriptName == "" { - return WorkerBindingListResponse{}, errors.New("ScriptName is required") - } - if api.AccountID == "" { - return WorkerBindingListResponse{}, errors.New("account ID required") - } - - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings", api.AccountID, requestParams.ScriptName) - - var jsonRes struct { - Response - Bindings []workerBindingMeta `json:"result"` - } - var r WorkerBindingListResponse - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return r, err - } - err = json.Unmarshal(res, &jsonRes) - if err != nil { - return r, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - r = WorkerBindingListResponse{ - Response: jsonRes.Response, - BindingList: make([]WorkerBindingListItem, 0, len(jsonRes.Bindings)), - } - for _, jsonBinding := range jsonRes.Bindings { - name, ok := jsonBinding["name"].(string) - if !ok { - return r, fmt.Errorf("Binding missing name %v", jsonBinding) - } - bType, ok := jsonBinding["type"].(string) - if !ok { - return r, fmt.Errorf("Binding missing type %v", jsonBinding) - } - bindingListItem := WorkerBindingListItem{ - Name: name, - } - - switch WorkerBindingType(bType) { - case WorkerDurableObjectBindingType: - class_name := jsonBinding["class_name"].(string) - script_name := jsonBinding["script_name"].(string) - bindingListItem.Binding = WorkerDurableObjectBinding{ - ClassName: class_name, - ScriptName: script_name, - } - case WorkerKvNamespaceBindingType: - namespaceID := jsonBinding["namespace_id"].(string) - bindingListItem.Binding = WorkerKvNamespaceBinding{ - NamespaceID: namespaceID, - } - case WorkerWebAssemblyBindingType: - bindingListItem.Binding = WorkerWebAssemblyBinding{ - Module: &bindingContentReader{ - ctx: ctx, - api: api, - requestParams: requestParams, - bindingName: name, - }, - } - case WorkerPlainTextBindingType: - text := jsonBinding["text"].(string) - bindingListItem.Binding = WorkerPlainTextBinding{ - Text: text, - } - case WorkerServiceBindingType: - service := jsonBinding["service"].(string) - environment := jsonBinding["environment"].(string) - bindingListItem.Binding = WorkerServiceBinding{ - Service: service, - Environment: &environment, - } - case WorkerSecretTextBindingType: - bindingListItem.Binding = WorkerSecretTextBinding{} - case WorkerR2BucketBindingType: - bucketName := jsonBinding["bucket_name"].(string) - bindingListItem.Binding = WorkerR2BucketBinding{ - BucketName: bucketName, - } - case WorkerAnalyticsEngineBindingType: - dataset := jsonBinding["dataset"].(string) - bindingListItem.Binding = WorkerAnalyticsEngineBinding{ - Dataset: dataset, - } - default: - bindingListItem.Binding = WorkerInheritBinding{} - } - r.BindingList = append(r.BindingList, bindingListItem) - } - - return r, nil -} - -// bindingContentReader is an io.Reader that will lazily load the -// raw bytes for a binding from the API when the Read() method -// is first called. This is only useful for binding types -// that store raw bytes, like WebAssembly modules. -type bindingContentReader struct { - api *API - requestParams *WorkerRequestParams - ctx context.Context - bindingName string - content []byte - position int -} - -func (b *bindingContentReader) Read(p []byte) (n int, err error) { - // Lazily load the content when Read() is first called - if b.content == nil { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings/%s/content", b.api.AccountID, b.requestParams.ScriptName, b.bindingName) - res, err := b.api.makeRequestContext(b.ctx, http.MethodGet, uri, nil) - if err != nil { - return 0, err - } - b.content = res - } - - if b.position >= len(b.content) { - return 0, io.EOF - } - - bytesRemaining := len(b.content) - b.position - bytesToProcess := 0 - if len(p) < bytesRemaining { - bytesToProcess = len(p) - } else { - bytesToProcess = bytesRemaining - } - - for i := 0; i < bytesToProcess; i++ { - p[i] = b.content[b.position] - b.position = b.position + 1 - } - - return bytesToProcess, nil -} - -// ListWorkerScripts returns list of worker scripts for given account. +// ListWorkers returns list of Workers for given account. // // API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/ -func (api *API) ListWorkerScripts(ctx context.Context) (WorkerListResponse, error) { - if api.AccountID == "" { - return WorkerListResponse{}, errors.New("account ID required") +func (api *API) ListWorkers(ctx context.Context, rc *ResourceContainer, params ListWorkersParams) (WorkerListResponse, error) { + if rc.Identifier == "" { + return WorkerListResponse{}, ErrMissingAccountID } - uri := fmt.Sprintf("/accounts/%s/workers/scripts", api.AccountID) + + uri := fmt.Sprintf("/accounts/%s/workers/scripts", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return WorkerListResponse{}, err } + var r WorkerListResponse err = json.Unmarshal(res, &r) if err != nil { return WorkerListResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } + return r, nil } -// UploadWorker push raw script content for your worker. +// UploadWorker pushes raw script content for your Worker. // // API reference: https://api.cloudflare.com/#worker-script-upload-worker -func (api *API) UploadWorker(ctx context.Context, requestParams *WorkerRequestParams, params *WorkerScriptParams) (WorkerScriptResponse, error) { - if params.Module { - return api.UploadWorkerWithBindings(ctx, requestParams, params) - } - - contentType := "application/javascript" - if requestParams.ScriptName != "" { - return api.uploadWorkerWithName(ctx, requestParams.ScriptName, contentType, []byte(params.Script)) +func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params CreateWorkerParams) (WorkerScriptResponse, error) { + var ( + contentType = "application/javascript" + err error + body []byte + ) + + if params.Module || len(params.Bindings) > 0 { + contentType, body, err = formatMultipartBody(params) + if err != nil { + return WorkerScriptResponse{}, err + } } - return api.uploadWorkerForZone(ctx, requestParams.ZoneID, contentType, []byte(params.Script)) -} -// UploadWorkerWithBindings push raw script content and bindings for your worker -// -// API reference: https://api.cloudflare.com/#worker-script-upload-worker -func (api *API) UploadWorkerWithBindings(ctx context.Context, requestParams *WorkerRequestParams, data *WorkerScriptParams) (WorkerScriptResponse, error) { - contentType, body, err := formatMultipartBody(data) - if err != nil { - return WorkerScriptResponse{}, err - } - if requestParams.ScriptName != "" { - return api.uploadWorkerWithName(ctx, requestParams.ScriptName, contentType, body) + if rc.Level == AccountRouteLevel { + return api.uploadWorkerWithName(ctx, rc, params.Name, contentType, []byte(body)) + } else { + return api.uploadWorkerForZone(ctx, rc, contentType, []byte(body)) } - return api.uploadWorkerForZone(ctx, requestParams.ZoneID, contentType, body) } -func (api *API) uploadWorkerForZone(ctx context.Context, zoneID, contentType string, body []byte) (WorkerScriptResponse, error) { - uri := fmt.Sprintf("/zones/%s/workers/script", zoneID) +func (api *API) uploadWorkerForZone(ctx context.Context, rc *ResourceContainer, contentType string, body []byte) (WorkerScriptResponse, error) { + uri := fmt.Sprintf("/zones/%s/workers/script", rc.Identifier) headers := make(http.Header) headers.Set("Content-Type", contentType) + res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, headers) var r WorkerScriptResponse if err != nil { return r, err } + err = json.Unmarshal(res, &r) if err != nil { return r, fmt.Errorf("%s: %w", errUnmarshalError, err) } + return r, nil } -func (api *API) uploadWorkerWithName(ctx context.Context, scriptName, contentType string, body []byte) (WorkerScriptResponse, error) { - if api.AccountID == "" { - return WorkerScriptResponse{}, errors.New("account ID required") +func (api *API) uploadWorkerWithName(ctx context.Context, rc *ResourceContainer, scriptName, contentType string, body []byte) (WorkerScriptResponse, error) { + if rc.Identifier == "" { + return WorkerScriptResponse{}, ErrMissingAccountID } - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", api.AccountID, scriptName) + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, scriptName) headers := make(http.Header) headers.Set("Content-Type", contentType) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, headers) + var r WorkerScriptResponse if err != nil { return r, err } + err = json.Unmarshal(res, &r) if err != nil { return r, fmt.Errorf("%s: %w", errUnmarshalError, err) } + return r, nil } // Returns content-type, body, error. -func formatMultipartBody(params *WorkerScriptParams) (string, []byte, error) { +func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) { var buf = &bytes.Buffer{} var mpw = multipart.NewWriter(buf) defer mpw.Close() @@ -797,174 +339,3 @@ func formatMultipartBody(params *WorkerScriptParams) (string, []byte, error) { return mpw.FormDataContentType(), buf.Bytes(), nil } - -// CreateWorkerRoute creates worker route for a zone -// -// API reference: https://api.cloudflare.com/#worker-filters-create-filter, https://api.cloudflare.com/#worker-routes-create-route -func (api *API) CreateWorkerRoute(ctx context.Context, zoneID string, route WorkerRoute) (WorkerRouteResponse, error) { - pathComponent, err := getRouteEndpoint(route) - if err != nil { - return WorkerRouteResponse{}, err - } - - uri := fmt.Sprintf("/zones/%s/workers/%s", zoneID, pathComponent) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, route) - if err != nil { - return WorkerRouteResponse{}, err - } - var r WorkerRouteResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r, nil -} - -// DeleteWorkerRoute deletes worker route for a zone -// -// API reference: https://api.cloudflare.com/#worker-routes-delete-route -func (api *API) DeleteWorkerRoute(ctx context.Context, zoneID string, routeID string) (WorkerRouteResponse, error) { - uri := fmt.Sprintf("/zones/%s/workers/routes/%s", zoneID, routeID) - res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) - if err != nil { - return WorkerRouteResponse{}, err - } - var r WorkerRouteResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r, nil -} - -// ListWorkerRoutes returns list of worker routes -// -// API reference: https://api.cloudflare.com/#worker-filters-list-filters, https://api.cloudflare.com/#worker-routes-list-routes -func (api *API) ListWorkerRoutes(ctx context.Context, zoneID string) (WorkerRoutesResponse, error) { - pathComponent := "filters" - // Unfortunately we don't have a good signal of whether the user is wanting - // to use the deprecated filters endpoint (https://api.cloudflare.com/#worker-filters-list-filters) - // or the multi-script routes endpoint (https://api.cloudflare.com/#worker-script-list-workers) - // - // The filters endpoint does not support API tokens, so if an API token is specified we need to use - // the routes endpoint. Otherwise, since the multi-script API endpoints that operate on a script - // require an AccountID, we assume that anyone specifying an AccountID is using the routes endpoint. - // This is likely too presumptuous. In the next major version, we should just remove the deprecated - // filter endpoints entirely to avoid this ambiguity. - if api.AccountID != "" || api.APIToken != "" { - pathComponent = "routes" - } - uri := fmt.Sprintf("/zones/%s/workers/%s", zoneID, pathComponent) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return WorkerRoutesResponse{}, err - } - var r WorkerRoutesResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerRoutesResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - for i := range r.Routes { - route := &r.Routes[i] - // The Enabled flag will not be set in the multi-script API response - // so we manually set it to true if the script name is not empty - // in case any multi-script customers rely on the Enabled field - if route.Script != "" { - route.Enabled = true - } - } - return r, nil -} - -// GetWorkerRoute returns a worker route. -// -// API reference: https://api.cloudflare.com/#worker-routes-get-route -func (api *API) GetWorkerRoute(ctx context.Context, zoneID string, routeID string) (WorkerRouteResponse, error) { - uri := fmt.Sprintf("/zones/%s/workers/routes/%s", zoneID, routeID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return WorkerRouteResponse{}, err - } - var r WorkerRouteResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r, nil -} - -// UpdateWorkerRoute updates worker route for a zone. -// -// API reference: https://api.cloudflare.com/#worker-filters-update-filter, https://api.cloudflare.com/#worker-routes-update-route -func (api *API) UpdateWorkerRoute(ctx context.Context, zoneID string, routeID string, route WorkerRoute) (WorkerRouteResponse, error) { - pathComponent, err := getRouteEndpoint(route) - if err != nil { - return WorkerRouteResponse{}, err - } - uri := fmt.Sprintf("/zones/%s/workers/%s/%s", zoneID, pathComponent, routeID) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, route) - if err != nil { - return WorkerRouteResponse{}, err - } - var r WorkerRouteResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r, nil -} - -func getRouteEndpoint(route WorkerRoute) (string, error) { - if route.Script != "" && route.Enabled { - return "", errors.New("Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") - } - - // For backwards-compatibility, fallback to the deprecated filter - // endpoint if Enabled == true - // https://api.cloudflare.com/#worker-filters-deprecated--properties - if route.Enabled { - return "filters", nil - } - - return "routes", nil -} - -type WorkerDomainParams struct { - ZoneID string `json:"zone_id"` - Hostname string `json:"hostname"` - Service string `json:"service"` - Environment string `json:"environment,omitempty"` -} - -type WorkerDomainResult struct { - ID string `json:"id"` - ZoneID string `json:"zone_id"` - ZoneName string `json:"zone_name"` - Hostname string `json:"hostname"` - Service string `json:"service"` - Environment string `json:"environment"` -} - -type WorkerDomainResponse struct { - Response - WorkerDomainResult `json:"result"` -} - -// AttachWorkerToDomain attaches a worker to a zone and hostname -// -// API reference: https://api.cloudflare.com/#worker-domain-attach-to-domain -func (api *API) AttachWorkerToDomain(ctx context.Context, rc *ResourceContainer, params *WorkerDomainParams) (WorkerDomainResponse, error) { - uri := fmt.Sprintf("/accounts/%s/workers/domains", rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) - if err != nil { - return WorkerDomainResponse{}, err - } - - var r WorkerDomainResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerDomainResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return r, nil -} diff --git a/workers_bindings.go b/workers_bindings.go new file mode 100644 index 0000000000..7ba01a4519 --- /dev/null +++ b/workers_bindings.go @@ -0,0 +1,455 @@ +package cloudflare + +import ( + "context" + rand "crypto/rand" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "net/textproto" +) + +// WorkerBindingType represents a particular type of binding. +type WorkerBindingType string + +func (b WorkerBindingType) String() string { + return string(b) +} + +const ( + // WorkerDurableObjectBindingType is the type for Durable Object bindings. + WorkerDurableObjectBindingType WorkerBindingType = "durable_object_namespace" + // WorkerInheritBindingType is the type for inherited bindings. + WorkerInheritBindingType WorkerBindingType = "inherit" + // WorkerKvNamespaceBindingType is the type for KV Namespace bindings. + WorkerKvNamespaceBindingType WorkerBindingType = "kv_namespace" + // WorkerWebAssemblyBindingType is the type for Web Assembly module bindings. + WorkerWebAssemblyBindingType WorkerBindingType = "wasm_module" + // WorkerSecretTextBindingType is the type for secret text bindings. + WorkerSecretTextBindingType WorkerBindingType = "secret_text" + // WorkerPlainTextBindingType is the type for plain text bindings. + WorkerPlainTextBindingType WorkerBindingType = "plain_text" + // WorkerServiceBindingType is the type for service bindings. + WorkerServiceBindingType WorkerBindingType = "service" + // WorkerR2BucketBindingType is the type for R2 bucket bindings. + WorkerR2BucketBindingType WorkerBindingType = "r2_bucket" + // WorkerAnalyticsEngineBindingType is the type for Analytics Engine dataset bindings. + WorkerAnalyticsEngineBindingType WorkerBindingType = "analytics_engine" +) + +// WorkerBindingListItem a struct representing an individual binding in a list of bindings. +type WorkerBindingListItem struct { + Name string `json:"name"` + Binding WorkerBinding +} + +// WorkerBindingListResponse wrapper struct for API response to worker binding list API call. +type WorkerBindingListResponse struct { + Response + BindingList []WorkerBindingListItem +} + +// Workers supports multiple types of bindings, e.g. KV namespaces or WebAssembly modules, and each type +// of binding will be represented differently in the upload request body. At a high-level, every binding +// will specify metadata, which is a JSON object with the properties "name" and "type". Some types of bindings +// will also have additional metadata properties. For example, KV bindings also specify the KV namespace. +// In addition to the metadata, some binding types may need to include additional data as part of the +// multipart form. For example, WebAssembly bindings will include the contents of the WebAssembly module. + +// WorkerBinding is the generic interface implemented by all of +// the various binding types. +type WorkerBinding interface { + Type() WorkerBindingType + + // serialize is responsible for returning the binding metadata as well as an optionally + // returning a function that can modify the multipart form body. For example, this is used + // by WebAssembly bindings to add a new part containing the WebAssembly module contents. + serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) +} + +// workerBindingMeta is the metadata portion of the binding. +type workerBindingMeta = map[string]interface{} + +// workerBindingBodyWriter allows for a binding to add additional parts to the multipart body. +type workerBindingBodyWriter func(*multipart.Writer) error + +// WorkerInheritBinding will just persist whatever binding content was previously uploaded. +type WorkerInheritBinding struct { + // Optional parameter that allows for renaming a binding without changing + // its contents. If `OldName` is empty, the binding name will not be changed. + OldName string +} + +// Type returns the type of the binding. +func (b WorkerInheritBinding) Type() WorkerBindingType { + return WorkerInheritBindingType +} + +func (b WorkerInheritBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + meta := workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + } + + if b.OldName != "" { + meta["old_name"] = b.OldName + } + + return meta, nil, nil +} + +// WorkerKvNamespaceBinding is a binding to a Workers KV Namespace +// +// https://developers.cloudflare.com/workers/archive/api/resource-bindings/kv-namespaces/ +type WorkerKvNamespaceBinding struct { + NamespaceID string +} + +// Type returns the type of the binding. +func (b WorkerKvNamespaceBinding) Type() WorkerBindingType { + return WorkerKvNamespaceBindingType +} + +func (b WorkerKvNamespaceBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.NamespaceID == "" { + return nil, nil, fmt.Errorf(`NamespaceID for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "namespace_id": b.NamespaceID, + }, nil, nil +} + +// WorkerDurableObjectBinding is a binding to a Workers Durable Object +// +// https://api.cloudflare.com/#durable-objects-namespace-properties +type WorkerDurableObjectBinding struct { + ClassName string + ScriptName string +} + +// Type returns the type of the binding. +func (b WorkerDurableObjectBinding) Type() WorkerBindingType { + return WorkerDurableObjectBindingType +} + +func (b WorkerDurableObjectBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.ClassName == "" { + return nil, nil, fmt.Errorf(`ClassName for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "class_name": b.ClassName, + "script_name": b.ScriptName, + }, nil, nil +} + +// WorkerWebAssemblyBinding is a binding to a WebAssembly module +// +// https://developers.cloudflare.com/workers/archive/api/resource-bindings/webassembly-modules/ +type WorkerWebAssemblyBinding struct { + Module io.Reader +} + +// Type returns the type of the binding. +func (b WorkerWebAssemblyBinding) Type() WorkerBindingType { + return WorkerWebAssemblyBindingType +} + +func (b WorkerWebAssemblyBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + partName := getRandomPartName() + + bodyWriter := func(mpw *multipart.Writer) error { + var hdr = textproto.MIMEHeader{} + hdr.Set("content-disposition", fmt.Sprintf(`form-data; name="%s"`, partName)) + hdr.Set("content-type", "application/wasm") + pw, err := mpw.CreatePart(hdr) + if err != nil { + return err + } + _, err = io.Copy(pw, b.Module) + return err + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "part": partName, + }, bodyWriter, nil +} + +// WorkerPlainTextBinding is a binding to plain text +// +// https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-plain-text-binding +type WorkerPlainTextBinding struct { + Text string +} + +// Type returns the type of the binding. +func (b WorkerPlainTextBinding) Type() WorkerBindingType { + return WorkerPlainTextBindingType +} + +func (b WorkerPlainTextBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Text == "" { + return nil, nil, fmt.Errorf(`Text for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "text": b.Text, + }, nil, nil +} + +// WorkerSecretTextBinding is a binding to secret text +// +// https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-secret-text-binding +type WorkerSecretTextBinding struct { + Text string +} + +// Type returns the type of the binding. +func (b WorkerSecretTextBinding) Type() WorkerBindingType { + return WorkerSecretTextBindingType +} + +func (b WorkerSecretTextBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Text == "" { + return nil, nil, fmt.Errorf(`Text for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "text": b.Text, + }, nil, nil +} + +type WorkerServiceBinding struct { + Service string + Environment *string +} + +func (b WorkerServiceBinding) Type() WorkerBindingType { + return WorkerServiceBindingType +} + +func (b WorkerServiceBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Service == "" { + return nil, nil, fmt.Errorf(`Service for binding "%s" cannot be empty`, bindingName) + } + + meta := workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "service": b.Service, + } + + if b.Environment != nil { + meta["environment"] = *b.Environment + } + + return meta, nil, nil +} + +// WorkerR2BucketBinding is a binding to an R2 bucket. +type WorkerR2BucketBinding struct { + BucketName string +} + +// Type returns the type of the binding. +func (b WorkerR2BucketBinding) Type() WorkerBindingType { + return WorkerR2BucketBindingType +} + +func (b WorkerR2BucketBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.BucketName == "" { + return nil, nil, fmt.Errorf(`BucketName for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "bucket_name": b.BucketName, + }, nil, nil +} + +// WorkerAnalyticsEngineBinding is a binding to an Analytics Engine dataset. +type WorkerAnalyticsEngineBinding struct { + Dataset string +} + +// Type returns the type of the binding. +func (b WorkerAnalyticsEngineBinding) Type() WorkerBindingType { + return WorkerAnalyticsEngineBindingType +} + +func (b WorkerAnalyticsEngineBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Dataset == "" { + return nil, nil, fmt.Errorf(`Dataset for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "name": bindingName, + "type": b.Type(), + "dataset": b.Dataset, + }, nil, nil +} + +// Each binding that adds a part to the multipart form body will need +// a unique part name so we just generate a random 128bit hex string. +func getRandomPartName() string { + randBytes := make([]byte, 16) + rand.Read(randBytes) //nolint:errcheck + return hex.EncodeToString(randBytes) +} + +// ListWorkerBindings returns all the bindings for a particular worker. +func (api *API) ListWorkerBindings(ctx context.Context, requestParams *WorkerRequestParams) (WorkerBindingListResponse, error) { + if requestParams.ScriptName == "" { + return WorkerBindingListResponse{}, errors.New("ScriptName is required") + } + if api.AccountID == "" { + return WorkerBindingListResponse{}, errors.New("account ID required") + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings", api.AccountID, requestParams.ScriptName) + + var jsonRes struct { + Response + Bindings []workerBindingMeta `json:"result"` + } + var r WorkerBindingListResponse + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return r, err + } + err = json.Unmarshal(res, &jsonRes) + if err != nil { + return r, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + r = WorkerBindingListResponse{ + Response: jsonRes.Response, + BindingList: make([]WorkerBindingListItem, 0, len(jsonRes.Bindings)), + } + for _, jsonBinding := range jsonRes.Bindings { + name, ok := jsonBinding["name"].(string) + if !ok { + return r, fmt.Errorf("Binding missing name %v", jsonBinding) + } + bType, ok := jsonBinding["type"].(string) + if !ok { + return r, fmt.Errorf("Binding missing type %v", jsonBinding) + } + bindingListItem := WorkerBindingListItem{ + Name: name, + } + + switch WorkerBindingType(bType) { + case WorkerDurableObjectBindingType: + class_name := jsonBinding["class_name"].(string) + script_name := jsonBinding["script_name"].(string) + bindingListItem.Binding = WorkerDurableObjectBinding{ + ClassName: class_name, + ScriptName: script_name, + } + case WorkerKvNamespaceBindingType: + namespaceID := jsonBinding["namespace_id"].(string) + bindingListItem.Binding = WorkerKvNamespaceBinding{ + NamespaceID: namespaceID, + } + case WorkerWebAssemblyBindingType: + bindingListItem.Binding = WorkerWebAssemblyBinding{ + Module: &bindingContentReader{ + ctx: ctx, + api: api, + requestParams: requestParams, + bindingName: name, + }, + } + case WorkerPlainTextBindingType: + text := jsonBinding["text"].(string) + bindingListItem.Binding = WorkerPlainTextBinding{ + Text: text, + } + case WorkerServiceBindingType: + service := jsonBinding["service"].(string) + environment := jsonBinding["environment"].(string) + bindingListItem.Binding = WorkerServiceBinding{ + Service: service, + Environment: &environment, + } + case WorkerSecretTextBindingType: + bindingListItem.Binding = WorkerSecretTextBinding{} + case WorkerR2BucketBindingType: + bucketName := jsonBinding["bucket_name"].(string) + bindingListItem.Binding = WorkerR2BucketBinding{ + BucketName: bucketName, + } + case WorkerAnalyticsEngineBindingType: + dataset := jsonBinding["dataset"].(string) + bindingListItem.Binding = WorkerAnalyticsEngineBinding{ + Dataset: dataset, + } + default: + bindingListItem.Binding = WorkerInheritBinding{} + } + r.BindingList = append(r.BindingList, bindingListItem) + } + + return r, nil +} + +// bindingContentReader is an io.Reader that will lazily load the +// raw bytes for a binding from the API when the Read() method +// is first called. This is only useful for binding types +// that store raw bytes, like WebAssembly modules. +type bindingContentReader struct { + api *API + requestParams *WorkerRequestParams + ctx context.Context + bindingName string + content []byte + position int +} + +func (b *bindingContentReader) Read(p []byte) (n int, err error) { + // Lazily load the content when Read() is first called + if b.content == nil { + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings/%s/content", b.api.AccountID, b.requestParams.ScriptName, b.bindingName) + res, err := b.api.makeRequestContext(b.ctx, http.MethodGet, uri, nil) + if err != nil { + return 0, err + } + b.content = res + } + + if b.position >= len(b.content) { + return 0, io.EOF + } + + bytesRemaining := len(b.content) - b.position + bytesToProcess := 0 + if len(p) < bytesRemaining { + bytesToProcess = len(p) + } else { + bytesToProcess = bytesRemaining + } + + for i := 0; i < bytesToProcess; i++ { + p[i] = b.content[b.position] + b.position = b.position + 1 + } + + return bytesToProcess, nil +} diff --git a/workers_domains.go b/workers_domains.go new file mode 100644 index 0000000000..e8caea9793 --- /dev/null +++ b/workers_domains.go @@ -0,0 +1,48 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +type WorkerDomainParams struct { + ZoneID string `json:"zone_id"` + Hostname string `json:"hostname"` + Service string `json:"service"` + Environment string `json:"environment,omitempty"` +} + +type WorkerDomainResult struct { + ID string `json:"id"` + ZoneID string `json:"zone_id"` + ZoneName string `json:"zone_name"` + Hostname string `json:"hostname"` + Service string `json:"service"` + Environment string `json:"environment"` +} + +type WorkerDomainResponse struct { + Response + WorkerDomainResult `json:"result"` +} + +// AttachWorkerToDomain attaches a worker to a zone and hostname +// +// API reference: https://api.cloudflare.com/#worker-domain-attach-to-domain +func (api *API) AttachWorkerToDomain(ctx context.Context, rc *ResourceContainer, params *WorkerDomainParams) (WorkerDomainResponse, error) { + uri := fmt.Sprintf("/accounts/%s/workers/domains", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return WorkerDomainResponse{}, err + } + + var r WorkerDomainResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerDomainResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return r, nil +} diff --git a/workers_example_test.go b/workers_example_test.go index 2206a35045..f70c7b93a7 100644 --- a/workers_example_test.go +++ b/workers_example_test.go @@ -1,206 +1,198 @@ package cloudflare_test -import ( - "context" - "fmt" - "log" - - cloudflare "github.com/cloudflare/cloudflare-go" -) - -var ( - workerScript = "addEventListener('fetch', event => {\n event.passThroughOnException()\nevent.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n return fetch(request)\n}" -) - -func ExampleAPI_UploadWorker() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - - res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}, &cloudflare.WorkerScriptParams{Script: workerScript}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) - - UploadWorkerWithName() -} - -func UploadWorkerWithName() { - api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) - if err != nil { - log.Fatal(err) - } - - res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}, &cloudflare.WorkerScriptParams{Script: workerScript}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_DownloadWorker() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - - res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) - - DownloadWorkerWithName() -} - -func DownloadWorkerWithName() { - api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) - if err != nil { - log.Fatal(err) - } - - res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_DeleteWorker() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) - - DeleteWorkerWithName() -} - -func DeleteWorkerWithName() { - api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) - if err != nil { - log.Fatal(err) - } - - res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_ListWorkerScripts() { - api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) - if err != nil { - log.Fatal(err) - } - - res, err := api.ListWorkerScripts(context.Background()) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res.WorkerList) -} - -func ExampleAPI_CreateWorkerRoute() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - route := cloudflare.WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} - res, err := api.CreateWorkerRoute(context.Background(), zoneID, route) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_UpdateWorkerRoute() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - // pull from existing list of routes to perform update on - routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) - if err != nil { - log.Fatal(err) - } - route := cloudflare.WorkerRoute{Pattern: "app2.example.com/*", Enabled: true} - // update first route retrieved from the listWorkerRoutes call with details above - res, err := api.UpdateWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID, route) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_ListWorkerRoutes() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - res, err := api.ListWorkerRoutes(context.Background(), zoneID) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} - -func ExampleAPI_DeleteWorkerRoute() { - api, err := cloudflare.New(apiKey, user) - if err != nil { - log.Fatal(err) - } - - zoneID, err := api.ZoneIDByName(domain) - if err != nil { - log.Fatal(err) - } - // pull from existing list of routes to perform delete on - routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) - if err != nil { - log.Fatal(err) - } - // delete first route retrieved from the listWorkerRoutes call - res, err := api.DeleteWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID) - if err != nil { - log.Fatal(err) - } - fmt.Printf("%+v", res) -} +// var ( +// workerScript = "addEventListener('fetch', event => {\n event.passThroughOnException()\nevent.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n return fetch(request)\n}" +// ) + +// func ExampleAPI_UploadWorker() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}, &cloudflare.WorkerScriptParams{Script: workerScript}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) + +// UploadWorkerWithName() +// } + +// func UploadWorkerWithName() { +// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}, &cloudflare.WorkerScriptParams{Script: workerScript}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_DownloadWorker() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) + +// DownloadWorkerWithName() +// } + +// func DownloadWorkerWithName() { +// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_DeleteWorker() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } +// res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) + +// DeleteWorkerWithName() +// } + +// func DeleteWorkerWithName() { +// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_ListWorkerScripts() { +// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) +// if err != nil { +// log.Fatal(err) +// } + +// res, err := api.ListWorkerScripts(context.Background()) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res.WorkerList) +// } + +// func ExampleAPI_CreateWorkerRoute() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } +// route := cloudflare.WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} +// res, err := api.CreateWorkerRoute(context.Background(), zoneID, route) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_UpdateWorkerRoute() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } +// // pull from existing list of routes to perform update on +// routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) +// if err != nil { +// log.Fatal(err) +// } +// route := cloudflare.WorkerRoute{Pattern: "app2.example.com/*", Enabled: true} +// // update first route retrieved from the listWorkerRoutes call with details above +// res, err := api.UpdateWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID, route) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_ListWorkerRoutes() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } +// res, err := api.ListWorkerRoutes(context.Background(), zoneID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } + +// func ExampleAPI_DeleteWorkerRoute() { +// api, err := cloudflare.New(apiKey, user) +// if err != nil { +// log.Fatal(err) +// } + +// zoneID, err := api.ZoneIDByName(domain) +// if err != nil { +// log.Fatal(err) +// } +// // pull from existing list of routes to perform delete on +// routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) +// if err != nil { +// log.Fatal(err) +// } +// // delete first route retrieved from the listWorkerRoutes call +// res, err := api.DeleteWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Printf("%+v", res) +// } diff --git a/workers_routes.go b/workers_routes.go new file mode 100644 index 0000000000..31ec7937bf --- /dev/null +++ b/workers_routes.go @@ -0,0 +1,154 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" +) + +type ListWorkerRoutes struct{} + +type CreateWorkerRouteParams struct { + Pattern string `json:"pattern"` + Script string `json:"script,omitempty"` +} + +type ListWorkerRoutesParams struct{} + +type UpdateWorkerRouteParams struct { + Pattern string `json:"pattern"` + Script string `json:"script,omitempty"` +} + +// CreateWorkerRoute creates worker route for a zone +// +// API reference: https://api.cloudflare.com/#worker-routes-create-route +func (api *API) CreateWorkerRoute(ctx context.Context, rc *ResourceContainer, params CreateWorkerRouteParams) (WorkerRouteResponse, error) { + if rc.Level != ZoneRouteLevel { + return WorkerRouteResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + } + + if rc.Identifier == "" { + return WorkerRouteResponse{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/zones/%s/workers/routes", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return WorkerRouteResponse{}, err + } + + var r WorkerRouteResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r, nil +} + +// DeleteWorkerRoute deletes worker route for a zone +// +// API reference: https://api.cloudflare.com/#worker-routes-delete-route +func (api *API) DeleteWorkerRoute(ctx context.Context, rc *ResourceContainer, routeID string) (WorkerRouteResponse, error) { + if rc.Level != ZoneRouteLevel { + return WorkerRouteResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + } + + if rc.Identifier == "" { + return WorkerRouteResponse{}, ErrMissingIdentifier + } + + if routeID == "" { + return WorkerRouteResponse{}, errors.New("missing required route ID") + } + + uri := fmt.Sprintf("/zones/%s/workers/routes/%s", rc.Identifier, routeID) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return WorkerRouteResponse{}, err + } + var r WorkerRouteResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r, nil +} + +// ListWorkerRoutes returns list of Worker routes +// +// API reference: https://api.cloudflare.com/#worker-routes-list-routes +func (api *API) ListWorkerRoutes(ctx context.Context, rc *ResourceContainer, params ListWorkerRoutesParams) (WorkerRoutesResponse, error) { + if rc.Level != ZoneRouteLevel { + return WorkerRoutesResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + } + + if rc.Identifier == "" { + return WorkerRoutesResponse{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/zones/%s/workers/routes", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return WorkerRoutesResponse{}, err + } + var r WorkerRoutesResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerRoutesResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return r, nil +} + +// GetWorkerRoute returns a Workers route. +// +// API reference: https://api.cloudflare.com/#worker-routes-get-route +func (api *API) GetWorkerRoute(ctx context.Context, rc *ResourceContainer, routeID string) (WorkerRouteResponse, error) { + if rc.Level != ZoneRouteLevel { + return WorkerRouteResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + } + + if rc.Identifier == "" { + return WorkerRouteResponse{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/zones/%s/workers/routes/%s", rc.Identifier, routeID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return WorkerRouteResponse{}, err + } + var r WorkerRouteResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r, nil +} + +// UpdateWorkerRoute updates worker route for a zone. +// +// API reference: https://api.cloudflare.com/#worker-routes-update-route +func (api *API) UpdateWorkerRoute(ctx context.Context, rc *ResourceContainer, params UpdateWorkerRouteParams) (WorkerRouteResponse, error) { + if rc.Level != ZoneRouteLevel { + return WorkerRouteResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + } + + if rc.Identifier == "" { + return WorkerRouteResponse{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/zones/%s/workers/routes/%s", rc.Identifier, params.Script) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return WorkerRouteResponse{}, err + } + var r WorkerRouteResponse + err = json.Unmarshal(res, &r) + if err != nil { + return WorkerRouteResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r, nil +} diff --git a/workers_routes_test.go b/workers_routes_test.go new file mode 100644 index 0000000000..7182c1571a --- /dev/null +++ b/workers_routes_test.go @@ -0,0 +1,348 @@ +package cloudflare + +// func TestWorkers_CreateWorkerRoute(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, createWorkerRouteResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} +// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) +// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_CreateWorkerRouteEnt(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, createWorkerRouteResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script"} +// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) +// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_CreateWorkerRouteSingleScriptWithAccount(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, createWorkerRouteResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} +// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) +// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_CreateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { +// setup() +// defer teardown() + +// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} +// _, err := client.CreateWorkerRoute(context.Background(), "foo", route) +// assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") +// } + +// func TestWorkers_CreateWorkerRouteWithNoScript(t *testing.T) { +// setup() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, createWorkerRouteResponse) //nolint +// }) + +// route := WorkerRoute{Pattern: "app1.example.com/*"} +// _, err := client.CreateWorkerRoute(context.Background(), "foo", route) +// assert.NoError(t, err) +// } + +// func TestWorkers_DeleteWorkerRoute(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint +// }) +// res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// }} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_DeleteWorkerRouteEnt(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { +// assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) +// w.Header().Set("content-type", "application/json") +// fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint +// }) +// res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// }} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_ListWorkerRoutes(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", 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, listRouteResponseData) //nolint +// }) + +// res, err := client.ListWorkerRoutes(context.Background(), "foo") +// want := WorkerRoutesResponse{successResponse, +// []WorkerRoute{ +// {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Enabled: true}, +// {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Enabled: false}, +// }, +// } +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_ListWorkerRoutesEnt(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", 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, listRouteEntResponseData) //nolint +// }) + +// res, err := client.ListWorkerRoutes(context.Background(), "foo") +// want := WorkerRoutesResponse{successResponse, +// []WorkerRoute{ +// {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Script: "test_script_1", Enabled: true}, +// {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Script: "test_script_2", Enabled: true}, +// {ID: "2b5bf4240cd34c77852fac70b1bf745a", Pattern: "app3.example.com/*", Script: "", Enabled: false}, +// }, +// } +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_GetWorkerRoute(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/1234", 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, getRouteResponseData) //nolint +// }) + +// res, err := client.GetWorkerRoute(context.Background(), "foo", "1234") +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// Pattern: "app1.example.com/*", +// Script: "script-name"}, +// } +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_UpdateWorkerRoute(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} +// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// Pattern: "app3.example.com/*", +// Enabled: true, +// }} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_UpdateWorkerRouteEnt(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app3.example.com/*", Script: "test_script_1"} +// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// Pattern: "app3.example.com/*", +// Script: "test_script_1", +// }} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_UpdateWorkerRouteSingleScriptWithAccount(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint +// }) +// route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} +// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) +// want := WorkerRouteResponse{successResponse, +// WorkerRoute{ +// ID: "e7a57d8746e74ae49c25994dadb421b1", +// Pattern: "app3.example.com/*", +// Script: "test_script_1", +// }} +// if assert.NoError(t, err) { +// assert.Equal(t, want, res) +// } +// } + +// func TestWorkers_ListWorkerBindingsMultiScript(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings", 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, listBindingsResponseData) //nolint +// }) + +// mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings/MY_WASM/content", 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/wasm") +// _, _ = w.Write([]byte("mock multi-script wasm")) +// }) + +// res, err := client.ListWorkerBindings(context.Background(), &WorkerRequestParams{ +// ScriptName: "my-script", +// }) +// assert.NoError(t, err) + +// assert.Equal(t, successResponse, res.Response) +// assert.Equal(t, 7, len(res.BindingList)) + +// assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ +// Name: "MY_KV", +// Binding: WorkerKvNamespaceBinding{ +// NamespaceID: "89f5f8fd93f94cb98473f6f421aa3b65", +// }, +// }) +// assert.Equal(t, WorkerKvNamespaceBindingType, res.BindingList[0].Binding.Type()) + +// assert.Equal(t, "MY_WASM", res.BindingList[1].Name) +// wasmBinding := res.BindingList[1].Binding.(WorkerWebAssemblyBinding) +// wasmModuleContent, err := io.ReadAll(wasmBinding.Module) +// assert.NoError(t, err) +// assert.Equal(t, []byte("mock multi-script wasm"), wasmModuleContent) +// assert.Equal(t, WorkerWebAssemblyBindingType, res.BindingList[1].Binding.Type()) + +// assert.Equal(t, res.BindingList[2], WorkerBindingListItem{ +// Name: "MY_PLAIN_TEXT", +// Binding: WorkerPlainTextBinding{ +// Text: "text", +// }, +// }) +// assert.Equal(t, WorkerPlainTextBindingType, res.BindingList[2].Binding.Type()) + +// assert.Equal(t, res.BindingList[3], WorkerBindingListItem{ +// Name: "MY_SECRET_TEXT", +// Binding: WorkerSecretTextBinding{}, +// }) +// assert.Equal(t, WorkerSecretTextBindingType, res.BindingList[3].Binding.Type()) + +// environment := "MY_ENVIRONMENT" +// assert.Equal(t, res.BindingList[4], WorkerBindingListItem{ +// Name: "MY_SERVICE_BINDING", +// Binding: WorkerServiceBinding{ +// Service: "MY_SERVICE", +// Environment: &environment, +// }, +// }) +// assert.Equal(t, WorkerServiceBindingType, res.BindingList[4].Binding.Type()) + +// assert.Equal(t, res.BindingList[5], WorkerBindingListItem{ +// Name: "MY_NEW_BINDING", +// Binding: WorkerInheritBinding{}, +// }) +// assert.Equal(t, WorkerInheritBindingType, res.BindingList[5].Binding.Type()) + +// assert.Equal(t, res.BindingList[6], WorkerBindingListItem{ +// Name: "MY_BUCKET", +// Binding: WorkerR2BucketBinding{ +// BucketName: "bucket", +// }, +// }) +// assert.Equal(t, WorkerR2BucketBindingType, res.BindingList[6].Binding.Type()) +// } + +// func TestWorkers_UpdateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { +// setup() +// defer teardown() + +// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} +// _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) +// assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") +// } + +// func TestWorkers_UpdateWorkerRouteWithNoScript(t *testing.T) { +// setup() +// defer teardown() + +// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint +// }) + +// route := WorkerRoute{Pattern: "app1.example.com/*"} +// _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) +// assert.NoError(t, err) +// } diff --git a/workers_test.go b/workers_test.go index 1f5dbfbc08..d3a44d7f4e 100644 --- a/workers_test.go +++ b/workers_test.go @@ -320,61 +320,30 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { }, nil } -func TestWorkers_DeleteWorker(t *testing.T) { +func TestDeleteWorker(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, deleteWorkerResponseData) //nolint + fmt.Fprintf(w, deleteWorkerResponseData) }) - res, err := client.DeleteWorker(context.Background(), &WorkerRequestParams{ZoneID: "foo"}) - want := WorkerScriptResponse{ - Response: successResponse, - } - - if assert.NoError(t, err) { - assert.Equal(t, want.Response, res.Response) - } -} - -func TestWorkers_DeleteWorkerWithName(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, deleteWorkerResponseData) //nolint - }) - res, err := client.DeleteWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}) - want := WorkerScriptResponse{ - Response: successResponse, - } - if assert.NoError(t, err) { - assert.Equal(t, want.Response, res.Response) - } -} -func TestWorkers_DeleteWorkerWithNameErrorsWithoutAccountId(t *testing.T) { - setup() - defer teardown() - - _, err := client.DeleteWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}) - assert.Error(t, err) + err := client.DeleteWorker(context.Background(), AccountIdentifier(testAccountID), DeleteWorkerParams{ScriptName: "bar"}) + assert.NoError(t, err) } -func TestWorkers_DownloadWorker(t *testing.T) { +func TestGetWorker(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", 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/javascript") - fmt.Fprintf(w, workerScript) //nolint + fmt.Fprintf(w, workerScript) }) - res, err := client.DownloadWorker(context.Background(), &WorkerRequestParams{ZoneID: "foo"}) + res, err := client.GetWorker(context.Background(), AccountIdentifier(testAccountID), "foo") want := WorkerScriptResponse{ successResponse, false, @@ -386,67 +355,41 @@ func TestWorkers_DownloadWorker(t *testing.T) { } } -func TestWorkers_DownloadWorkerWithName(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/accounts/foo/workers/scripts/bar", 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/javascript") - fmt.Fprintf(w, workerScript) //nolint - }) - res, err := client.DownloadWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}) - want := WorkerScriptResponse{ - successResponse, - false, - WorkerScript{ - Script: workerScript, - }} - if assert.NoError(t, err) { - assert.Equal(t, want.Script, res.Script) - } -} - -func TestWorkers_DownloadWorkerWithNameErrorsWithoutAccountId(t *testing.T) { +func TestGetWorker_Module(t *testing.T) { setup() defer teardown() - _, err := client.DownloadWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}) - assert.Error(t, err) -} - -func TestWorkers_DownloadWorkerModule(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", 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", "multipart/form-data; boundary=workermodulescriptdownload") - fmt.Fprintf(w, workerModuleScriptDownloadResponse) //nolint + fmt.Fprintf(w, workerModuleScriptDownloadResponse) }) - res, err := client.DownloadWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}) + + res, err := client.GetWorker(context.Background(), AccountIdentifier(testAccountID), "foo") want := WorkerScriptResponse{ successResponse, true, WorkerScript{ Script: workerModuleScript, - }} + }, + } + if assert.NoError(t, err) { assert.Equal(t, want.Script, res.Script) } } -func TestWorkers_ListWorkerScripts(t *testing.T) { - setup(UsingAccount("foo")) +func TestListWorkers(t *testing.T) { + setup() defer teardown() - mux.HandleFunc("/accounts/foo/workers/scripts", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts", 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, listWorkersResponseData) //nolint + fmt.Fprintf(w, listWorkersResponseData) }) - res, err := client.ListWorkerScripts(context.Background()) + res, err := client.ListWorkers(context.Background(), AccountIdentifier(testAccountID), ListWorkersParams{}) sampleDate, _ := time.Parse(time.RFC3339Nano, "2018-04-22T17:10:48.938097Z") want := []WorkerMetaData{ { @@ -467,18 +410,18 @@ func TestWorkers_ListWorkerScripts(t *testing.T) { } } -func TestWorkers_UploadWorker(t *testing.T) { +func TestUploadWorker_Basic(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) contentTypeHeader := r.Header.Get("content-type") assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) //nolint }) - res, err := client.UploadWorker(context.Background(), &WorkerRequestParams{ZoneID: "foo"}, &WorkerScriptParams{Script: workerScript}) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{Name: "foo", Script: workerScript}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ successResponse, @@ -496,11 +439,11 @@ func TestWorkers_UploadWorker(t *testing.T) { } } -func TestWorkers_UploadWorkerAsModule(t *testing.T) { +func TestUploadWorker_Module(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", func(w http.ResponseWriter, r *http.Request) { mpUpload, err := parseMultipartUpload(r) assert.NoError(t, err) @@ -515,9 +458,9 @@ func TestWorkers_UploadWorkerAsModule(t *testing.T) { assert.Equal(t, expectedContentType, contentTypeHeader, "Expected content-type request header to be %s, got %s", expectedContentType, contentTypeHeader) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerModuleResponseData) //nolint + fmt.Fprintf(w, uploadWorkerModuleResponseData) }) - res, err := client.UploadWorker(context.Background(), &WorkerRequestParams{ZoneID: "foo"}, &WorkerScriptParams{Script: workerModuleScript, Module: true}) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{Name: "foo", Script: workerModuleScript, Module: true}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ successResponse, @@ -535,76 +478,10 @@ func TestWorkers_UploadWorkerAsModule(t *testing.T) { } } -func TestWorkers_UploadWorkerWithName(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) - contentTypeHeader := r.Header.Get("content-type") - assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint - }) - res, err := client.UploadWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &WorkerScriptParams{Script: workerScript}) - formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") - want := WorkerScriptResponse{ - successResponse, - false, - WorkerScript{ - Script: workerScript, - WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, - }, - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_UploadWorkerSingleScriptWithAccount(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) - contentTypeHeader := r.Header.Get("content-type") - assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint - }) - res, err := client.UploadWorker(context.Background(), &WorkerRequestParams{ZoneID: "foo"}, &WorkerScriptParams{Script: workerScript}) - formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") - want := WorkerScriptResponse{ - successResponse, - false, - WorkerScript{ - Script: workerScript, - WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, - }, - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_UploadWorkerWithNameErrorsWithoutAccountId(t *testing.T) { +func TestUploadWorker_WithDurableObjectBinding(t *testing.T) { setup() defer teardown() - _, err := client.UploadWorker(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &WorkerScriptParams{Script: workerScript}) - assert.Error(t, err) -} - -func TestWorkers_UploadWorkerWithDurableObjectBinding(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) @@ -623,11 +500,13 @@ func TestWorkers_UploadWorkerWithDurableObjectBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprintf(w, uploadWorkerResponseData) } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) + + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerDurableObjectBinding{ @@ -635,13 +514,13 @@ func TestWorkers_UploadWorkerWithDurableObjectBinding(t *testing.T) { ScriptName: "the_script", }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }) + assert.NoError(t, err) } -func TestWorkers_UploadWorkerWithInheritBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithInheritBinding(t *testing.T) { + setup() defer teardown() // Setup route handler for both single-script and multi-script @@ -666,22 +545,10 @@ func TestWorkers_UploadWorkerWithInheritBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprintf(w, uploadWorkerResponseData) } - mux.HandleFunc("/zones/foo/workers/script", handler) - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ - Script: workerScript, - Bindings: map[string]WorkerBinding{ - "b1": WorkerInheritBinding{}, - "b2": WorkerInheritBinding{ - OldName: "old_binding_name", - }, - }, - } - - // Expected response formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ successResponse, @@ -695,21 +562,22 @@ func TestWorkers_UploadWorkerWithInheritBinding(t *testing.T) { }, }} - // Test single-script - res, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ZoneID: "foo"}, &scriptParams) - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } - - // Test multi-script - res, err = client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", + Script: workerScript, + Bindings: map[string]WorkerBinding{ + "b1": WorkerInheritBinding{}, + "b2": WorkerInheritBinding{ + OldName: "old_binding_name", + }, + }}) if assert.NoError(t, err) { assert.Equal(t, want, res) } } -func TestWorkers_UploadWorkerWithKVBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithKVBinding(t *testing.T) { + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -729,24 +597,23 @@ func TestWorkers_UploadWorkerWithKVBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprintf(w, uploadWorkerResponseData) } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerKvNamespaceBinding{ NamespaceID: "test-namespace", }, - }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }}) assert.NoError(t, err) } -func TestWorkers_UploadWorkerWithWasmBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithWasmBinding(t *testing.T) { + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -771,24 +638,25 @@ func TestWorkers_UploadWorkerWithWasmBinding(t *testing.T) { assert.Equal(t, []byte("fake-wasm"), wasmContent) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprintf(w, uploadWorkerResponseData) } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerWebAssemblyBinding{ Module: strings.NewReader("fake-wasm"), }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }) + assert.NoError(t, err) } -func TestWorkers_UploadWorkerWithPlainTextBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithPlainTextBinding(t *testing.T) { + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -810,25 +678,26 @@ func TestWorkers_UploadWorkerWithPlainTextBinding(t *testing.T) { w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) //nolint } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerPlainTextBinding{ Text: "plain text value", }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }) + assert.NoError(t, err) } -func TestWorkers_UploadWorkerAsModuleWithPlainTextBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_ModuleWithPlainTextBinding(t *testing.T) { + setup() defer teardown() - mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", 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) @@ -856,7 +725,8 @@ func TestWorkers_UploadWorkerAsModuleWithPlainTextBinding(t *testing.T) { fmt.Fprintf(w, uploadWorkerModuleResponseData) //nolint }) - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerModuleScript, Module: true, Bindings: map[string]WorkerBinding{ @@ -864,13 +734,13 @@ func TestWorkers_UploadWorkerAsModuleWithPlainTextBinding(t *testing.T) { Text: "plain text value", }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }) + assert.NoError(t, err) } -func TestWorkers_UploadWorkerWithSecretTextBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithSecretTextBinding(t *testing.T) { + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -892,22 +762,22 @@ func TestWorkers_UploadWorkerWithSecretTextBinding(t *testing.T) { w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) //nolint } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerSecretTextBinding{ Text: "secret text value", }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) + }) assert.NoError(t, err) } -func TestWorkers_UploadWorkerWithServiceBinding(t *testing.T) { - setup(UsingAccount("foo")) +func TestUploadWorker_WithServiceBinding(t *testing.T) { + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -935,10 +805,10 @@ func TestWorkers_UploadWorkerWithServiceBinding(t *testing.T) { w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) //nolint } - mux.HandleFunc("/accounts/foo/workers/scripts/bar", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - environment := "the_environment" - scriptParams := WorkerScriptParams{ + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + Name: "bar", Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerServiceBinding{ @@ -946,394 +816,9 @@ func TestWorkers_UploadWorkerWithServiceBinding(t *testing.T) { }, "b2": WorkerServiceBinding{ Service: "the_service", - Environment: &environment, + Environment: StringPtr("the_environment"), }, }, - } - _, err := client.UploadWorkerWithBindings(context.Background(), &WorkerRequestParams{ScriptName: "bar"}, &scriptParams) - assert.NoError(t, err) -} - -func TestWorkers_CreateWorkerRoute(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/zones/foo/workers/filters", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, createWorkerRouteResponse) //nolint - }) - route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} - res, err := client.CreateWorkerRoute(context.Background(), "foo", route) - want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_CreateWorkerRouteEnt(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, createWorkerRouteResponse) //nolint - }) - route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script"} - res, err := client.CreateWorkerRoute(context.Background(), "foo", route) - want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_CreateWorkerRouteSingleScriptWithAccount(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/filters", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, createWorkerRouteResponse) //nolint - }) - route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} - res, err := client.CreateWorkerRoute(context.Background(), "foo", route) - want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_CreateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} - _, err := client.CreateWorkerRoute(context.Background(), "foo", route) - assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") -} - -func TestWorkers_CreateWorkerRouteWithNoScript(t *testing.T) { - setup(UsingAccount("foo")) - - mux.HandleFunc("/zones/foo/workers/routes", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, createWorkerRouteResponse) //nolint - }) - - route := WorkerRoute{Pattern: "app1.example.com/*"} - _, err := client.CreateWorkerRoute(context.Background(), "foo", route) - assert.NoError(t, err) -} - -func TestWorkers_DeleteWorkerRoute(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint - }) - res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_DeleteWorkerRouteEnt(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint - }) - res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_ListWorkerRoutes(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/zones/foo/workers/filters", 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, listRouteResponseData) //nolint - }) - - res, err := client.ListWorkerRoutes(context.Background(), "foo") - want := WorkerRoutesResponse{successResponse, - []WorkerRoute{ - {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Enabled: true}, - {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Enabled: false}, - }, - } - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_ListWorkerRoutesEnt(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes", 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, listRouteEntResponseData) //nolint - }) - - res, err := client.ListWorkerRoutes(context.Background(), "foo") - want := WorkerRoutesResponse{successResponse, - []WorkerRoute{ - {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Script: "test_script_1", Enabled: true}, - {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Script: "test_script_2", Enabled: true}, - {ID: "2b5bf4240cd34c77852fac70b1bf745a", Pattern: "app3.example.com/*", Script: "", Enabled: false}, - }, - } - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_GetWorkerRoute(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes/1234", 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, getRouteResponseData) //nolint - }) - - res, err := client.GetWorkerRoute(context.Background(), "foo", "1234") - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - Pattern: "app1.example.com/*", - Script: "script-name"}, - } - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_UpdateWorkerRoute(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteResponse) //nolint - }) - route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} - res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - Pattern: "app3.example.com/*", - Enabled: true, - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_UpdateWorkerRouteEnt(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint - }) - route := WorkerRoute{Pattern: "app3.example.com/*", Script: "test_script_1"} - res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - Pattern: "app3.example.com/*", - Script: "test_script_1", - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_UpdateWorkerRouteSingleScriptWithAccount(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint - }) - route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} - res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) - want := WorkerRouteResponse{successResponse, - WorkerRoute{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - Pattern: "app3.example.com/*", - Script: "test_script_1", - }} - if assert.NoError(t, err) { - assert.Equal(t, want, res) - } -} - -func TestWorkers_ListWorkerBindingsMultiScript(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/accounts/foo/workers/scripts/my-script/bindings", 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, listBindingsResponseData) //nolint - }) - - mux.HandleFunc("/accounts/foo/workers/scripts/my-script/bindings/MY_WASM/content", 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/wasm") - _, _ = w.Write([]byte("mock multi-script wasm")) - }) - - res, err := client.ListWorkerBindings(context.Background(), &WorkerRequestParams{ - ScriptName: "my-script", - }) - assert.NoError(t, err) - - assert.Equal(t, successResponse, res.Response) - assert.Equal(t, 8, len(res.BindingList)) - - assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ - Name: "MY_KV", - Binding: WorkerKvNamespaceBinding{ - NamespaceID: "89f5f8fd93f94cb98473f6f421aa3b65", - }, }) - assert.Equal(t, WorkerKvNamespaceBindingType, res.BindingList[0].Binding.Type()) - - assert.Equal(t, "MY_WASM", res.BindingList[1].Name) - wasmBinding := res.BindingList[1].Binding.(WorkerWebAssemblyBinding) - wasmModuleContent, err := io.ReadAll(wasmBinding.Module) assert.NoError(t, err) - assert.Equal(t, []byte("mock multi-script wasm"), wasmModuleContent) - assert.Equal(t, WorkerWebAssemblyBindingType, res.BindingList[1].Binding.Type()) - - assert.Equal(t, res.BindingList[2], WorkerBindingListItem{ - Name: "MY_PLAIN_TEXT", - Binding: WorkerPlainTextBinding{ - Text: "text", - }, - }) - assert.Equal(t, WorkerPlainTextBindingType, res.BindingList[2].Binding.Type()) - - assert.Equal(t, res.BindingList[3], WorkerBindingListItem{ - Name: "MY_SECRET_TEXT", - Binding: WorkerSecretTextBinding{}, - }) - assert.Equal(t, WorkerSecretTextBindingType, res.BindingList[3].Binding.Type()) - - environment := "MY_ENVIRONMENT" - assert.Equal(t, res.BindingList[4], WorkerBindingListItem{ - Name: "MY_SERVICE_BINDING", - Binding: WorkerServiceBinding{ - Service: "MY_SERVICE", - Environment: &environment, - }, - }) - assert.Equal(t, WorkerServiceBindingType, res.BindingList[4].Binding.Type()) - - assert.Equal(t, res.BindingList[5], WorkerBindingListItem{ - Name: "MY_NEW_BINDING", - Binding: WorkerInheritBinding{}, - }) - assert.Equal(t, WorkerInheritBindingType, res.BindingList[5].Binding.Type()) - - assert.Equal(t, res.BindingList[6], WorkerBindingListItem{ - Name: "MY_BUCKET", - Binding: WorkerR2BucketBinding{ - BucketName: "bucket", - }, - }) - assert.Equal(t, WorkerR2BucketBindingType, res.BindingList[6].Binding.Type()) - - assert.Equal(t, res.BindingList[7], WorkerBindingListItem{ - Name: "MY_DATASET", - Binding: WorkerAnalyticsEngineBinding{ - Dataset: "my_dataset", - }, - }) - assert.Equal(t, WorkerAnalyticsEngineBindingType, res.BindingList[7].Binding.Type()) -} - -func TestWorkers_UpdateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} - _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) - assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") -} - -func TestWorkers_UpdateWorkerRouteWithNoScript(t *testing.T) { - setup(UsingAccount("foo")) - defer teardown() - - mux.HandleFunc("/zones/foo/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint - }) - - route := WorkerRoute{Pattern: "app1.example.com/*"} - _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) - assert.NoError(t, err) -} - -func TestWorkers_AttachWorkerToDomain(t *testing.T) { - setup(UsingAccount(testAccountID)) - defer teardown() - - mux.HandleFunc("/accounts/"+testAccountID+"/workers/domains", 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, attachWorkerToDomainResponse) //nolint - }) - res, err := client.AttachWorkerToDomain(context.Background(), AccountIdentifier(testAccountID), &WorkerDomainParams{ - ZoneID: testZoneID, - Hostname: "app4.example.com", - Service: "test_script_1", - Environment: "production", - }) - want := WorkerDomainResponse{ - successResponse, - WorkerDomainResult{ - ID: "e7a57d8746e74ae49c25994dadb421b1", - ZoneID: testZoneID, - Service: "test_script_1", - Hostname: "api4.example.com", - Environment: "production", - }} - if assert.NoError(t, err) { - assert.Equal(t, want.Response, res.Response) - } } From 8b05a9db49126304e2a0f89ab9df402e029771f5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 30 Nov 2022 14:57:21 +1100 Subject: [PATCH 008/370] workers: modernise all method signatures and conventions Updates all the available Workers endpoints to follow the new method signatures and conventions for calling the API. --- workers_bindings_test.go | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 workers_bindings_test.go diff --git a/workers_bindings_test.go b/workers_bindings_test.go new file mode 100644 index 0000000000..a21aec3419 --- /dev/null +++ b/workers_bindings_test.go @@ -0,0 +1,97 @@ +package cloudflare + +import ( + "context" + "fmt" + "io" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestListWorkerBindings(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings", 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, listBindingsResponseData) + }) + + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings/MY_WASM/content", 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/wasm") + _, _ = w.Write([]byte("mock multi-script wasm")) + }) + + res, err := client.ListWorkerBindings(context.Background(), AccountIdentifier(testAccountID), ListWorkerBindingsParams{ + ScriptName: "my-script", + }) + assert.NoError(t, err) + + assert.Equal(t, successResponse, res.Response) + assert.Equal(t, 8, len(res.BindingList)) + + assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ + Name: "MY_KV", + Binding: WorkerKvNamespaceBinding{ + NamespaceID: "89f5f8fd93f94cb98473f6f421aa3b65", + }, + }) + assert.Equal(t, WorkerKvNamespaceBindingType, res.BindingList[0].Binding.Type()) + + assert.Equal(t, "MY_WASM", res.BindingList[1].Name) + wasmBinding := res.BindingList[1].Binding.(WorkerWebAssemblyBinding) + wasmModuleContent, err := io.ReadAll(wasmBinding.Module) + assert.NoError(t, err) + assert.Equal(t, []byte("mock multi-script wasm"), wasmModuleContent) + assert.Equal(t, WorkerWebAssemblyBindingType, res.BindingList[1].Binding.Type()) + + assert.Equal(t, res.BindingList[2], WorkerBindingListItem{ + Name: "MY_PLAIN_TEXT", + Binding: WorkerPlainTextBinding{ + Text: "text", + }, + }) + assert.Equal(t, WorkerPlainTextBindingType, res.BindingList[2].Binding.Type()) + + assert.Equal(t, res.BindingList[3], WorkerBindingListItem{ + Name: "MY_SECRET_TEXT", + Binding: WorkerSecretTextBinding{}, + }) + assert.Equal(t, WorkerSecretTextBindingType, res.BindingList[3].Binding.Type()) + + environment := "MY_ENVIRONMENT" + assert.Equal(t, res.BindingList[4], WorkerBindingListItem{ + Name: "MY_SERVICE_BINDING", + Binding: WorkerServiceBinding{ + Service: "MY_SERVICE", + Environment: &environment, + }, + }) + assert.Equal(t, WorkerServiceBindingType, res.BindingList[4].Binding.Type()) + + assert.Equal(t, res.BindingList[5], WorkerBindingListItem{ + Name: "MY_NEW_BINDING", + Binding: WorkerInheritBinding{}, + }) + assert.Equal(t, WorkerInheritBindingType, res.BindingList[5].Binding.Type()) + + assert.Equal(t, res.BindingList[6], WorkerBindingListItem{ + Name: "MY_BUCKET", + Binding: WorkerR2BucketBinding{ + BucketName: "bucket", + }, + }) + assert.Equal(t, WorkerR2BucketBindingType, res.BindingList[6].Binding.Type()) + + assert.Equal(t, res.BindingList[7], WorkerBindingListItem{ + Name: "MY_DATASET", + Binding: WorkerAnalyticsEngineBinding{ + Dataset: "my_dataset", + }, + }) + assert.Equal(t, WorkerAnalyticsEngineBindingType, res.BindingList[7].Binding.Type()) +} From 1c2393c43a33e4268d1e43ec624db5dba5862464 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 30 Nov 2022 14:57:21 +1100 Subject: [PATCH 009/370] workers: modernise all method signatures and conventions Updates all the available Workers endpoints to follow the new method signatures and conventions for calling the API. --- errors.go | 5 +- workers.go | 78 +++--- workers_account_settings.go | 8 + workers_bindings.go | 43 ++-- workers_cron_triggers.go | 35 ++- workers_cron_triggers_test.go | 8 +- workers_domains.go | 48 ---- workers_example_test.go | 198 --------------- workers_kv.go | 68 +++++ workers_routes.go | 9 +- workers_routes_test.go | 465 +++++++++------------------------- workers_secrets.go | 52 +++- workers_secrets_test.go | 24 +- workers_tail.go | 1 + workers_test.go | 45 ++-- 15 files changed, 384 insertions(+), 703 deletions(-) delete mode 100644 workers_domains.go delete mode 100644 workers_example_test.go diff --git a/errors.go b/errors.go index 994707978e..723c18bae3 100644 --- a/errors.go +++ b/errors.go @@ -29,7 +29,8 @@ const ( errAPIKeysAndTokensAreMutuallyExclusive = "API keys and tokens are mutually exclusive" //nolint:gosec errMissingCredentials = "no credentials provided" - errInvalidResourceContainerAccess = "requested resource container (%q) is not supported for this endpoint" + errInvalidResourceContainerAccess = "requested resource container (%q) is not supported for this endpoint" + errRequiredAccountLevelResourceContainer = "this endpoint requires using an account level resource container and identifiers" ) var ( @@ -40,6 +41,8 @@ var ( ErrAccountIDOrZoneIDAreRequired = errors.New(errMissingAccountOrZoneID) ErrAccountIDAndZoneIDAreMutuallyExclusive = errors.New(errAccountIDAndZoneIDAreMutuallyExclusive) ErrMissingResourceIdentifier = errors.New(errMissingResourceIdentifier) + + ErrRequiredAccountLevelResourceContainer = errors.New(errRequiredAccountLevelResourceContainer) ) type ErrorType string diff --git a/workers.go b/workers.go index b762acad8f..ae2bf7c5df 100644 --- a/workers.go +++ b/workers.go @@ -21,8 +21,8 @@ type WorkerRequestParams struct { } type CreateWorkerParams struct { - Name string - Script string + ScriptName string + Script string // Module changes the Content-Type header to specify the script is an // ES Module syntax script. @@ -35,7 +35,7 @@ type CreateWorkerParams struct { // WorkerScriptParams provides a worker script and the associated bindings. type WorkerScriptParams struct { - Script string + ScriptName string // Module changes the Content-Type header to specify the script is an // ES Module syntax script. @@ -50,8 +50,9 @@ type WorkerScriptParams struct { // // API reference: https://api.cloudflare.com/#worker-routes-properties type WorkerRoute struct { - Pattern string `json:"pattern"` - Script string `json:"script,omitempty"` + ID string `json:"id,omitempty"` + Pattern string `json:"pattern"` + ScriptName string `json:"script,omitempty"` } // WorkerRoutesResponse embeds Response struct and slice of WorkerRoutes. @@ -85,6 +86,7 @@ type WorkerMetaData struct { // WorkerListResponse wrapper struct for API response to worker script list API call. type WorkerListResponse struct { Response + ResultInfo WorkerList []WorkerMetaData `json:"result"` } @@ -105,6 +107,14 @@ type DeleteWorkerParams struct { // // API reference: https://api.cloudflare.com/#worker-script-delete-worker func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params DeleteWorkerParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return ErrMissingAccountID + } + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, params.ScriptName) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) @@ -127,11 +137,11 @@ func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params // API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/ func (api *API) GetWorker(ctx context.Context, rc *ResourceContainer, scriptName string) (WorkerScriptResponse, error) { if rc.Level != AccountRouteLevel { - return WorkerScriptResponse{}, fmt.Errorf(errInvalidResourceContainerAccess, ZoneRouteLevel) + return WorkerScriptResponse{}, ErrRequiredAccountLevelResourceContainer } if rc.Identifier == "" { - return WorkerScriptResponse{}, ErrMissingIdentifier + return WorkerScriptResponse{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, scriptName) @@ -168,30 +178,42 @@ func (api *API) GetWorker(ctx context.Context, rc *ResourceContainer, scriptName // ListWorkers returns list of Workers for given account. // // API reference: https://developers.cloudflare.com/workers/tooling/api/scripts/ -func (api *API) ListWorkers(ctx context.Context, rc *ResourceContainer, params ListWorkersParams) (WorkerListResponse, error) { +func (api *API) ListWorkers(ctx context.Context, rc *ResourceContainer, params ListWorkersParams) (WorkerListResponse, *ResultInfo, error) { + if rc.Level != AccountRouteLevel { + return WorkerListResponse{}, &ResultInfo{}, ErrRequiredAccountLevelResourceContainer + } + if rc.Identifier == "" { - return WorkerListResponse{}, ErrMissingAccountID + return WorkerListResponse{}, &ResultInfo{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/workers/scripts", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return WorkerListResponse{}, err + return WorkerListResponse{}, &ResultInfo{}, err } var r WorkerListResponse err = json.Unmarshal(res, &r) if err != nil { - return WorkerListResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return WorkerListResponse{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return r, nil + return r, &r.ResultInfo, nil } // UploadWorker pushes raw script content for your Worker. // // API reference: https://api.cloudflare.com/#worker-script-upload-worker func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params CreateWorkerParams) (WorkerScriptResponse, error) { + if rc.Level != AccountRouteLevel { + return WorkerScriptResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return WorkerScriptResponse{}, ErrMissingAccountID + } + var ( contentType = "application/javascript" err error @@ -205,37 +227,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params } } - if rc.Level == AccountRouteLevel { - return api.uploadWorkerWithName(ctx, rc, params.Name, contentType, []byte(body)) - } else { - return api.uploadWorkerForZone(ctx, rc, contentType, []byte(body)) - } -} - -func (api *API) uploadWorkerForZone(ctx context.Context, rc *ResourceContainer, contentType string, body []byte) (WorkerScriptResponse, error) { - uri := fmt.Sprintf("/zones/%s/workers/script", rc.Identifier) - headers := make(http.Header) - headers.Set("Content-Type", contentType) - - res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, headers) - var r WorkerScriptResponse - if err != nil { - return r, err - } - - err = json.Unmarshal(res, &r) - if err != nil { - return r, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return r, nil -} - -func (api *API) uploadWorkerWithName(ctx context.Context, rc *ResourceContainer, scriptName, contentType string, body []byte) (WorkerScriptResponse, error) { - if rc.Identifier == "" { - return WorkerScriptResponse{}, ErrMissingAccountID - } - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, scriptName) + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s", rc.Identifier, params.ScriptName) headers := make(http.Header) headers.Set("Content-Type", contentType) res, err := api.makeRequestContextWithHeaders(ctx, http.MethodPut, uri, body, headers) diff --git a/workers_account_settings.go b/workers_account_settings.go index d8e58516a0..6b3b65d6df 100644 --- a/workers_account_settings.go +++ b/workers_account_settings.go @@ -37,6 +37,10 @@ func (api *API) CreateWorkersAccountSettings(ctx context.Context, rc *ResourceCo return WorkersAccountSettings{}, ErrMissingAccountID } + if rc.Level != AccountRouteLevel { + return WorkersAccountSettings{}, ErrRequiredAccountLevelResourceContainer + } + uri := fmt.Sprintf("/accounts/%s/workers/account-settings", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { @@ -59,6 +63,10 @@ func (api *API) WorkersAccountSettings(ctx context.Context, rc *ResourceContaine return WorkersAccountSettings{}, ErrMissingAccountID } + if rc.Level != AccountRouteLevel { + return WorkersAccountSettings{}, ErrRequiredAccountLevelResourceContainer + } + uri := fmt.Sprintf("/accounts/%s/workers/account-settings", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) if err != nil { diff --git a/workers_bindings.go b/workers_bindings.go index 7ba01a4519..d2ac3ee96a 100644 --- a/workers_bindings.go +++ b/workers_bindings.go @@ -41,6 +41,10 @@ const ( WorkerAnalyticsEngineBindingType WorkerBindingType = "analytics_engine" ) +type ListWorkerBindingsParams struct { + ScriptName string +} + // WorkerBindingListItem a struct representing an individual binding in a list of bindings. type WorkerBindingListItem struct { Name string `json:"name"` @@ -314,15 +318,20 @@ func getRandomPartName() string { } // ListWorkerBindings returns all the bindings for a particular worker. -func (api *API) ListWorkerBindings(ctx context.Context, requestParams *WorkerRequestParams) (WorkerBindingListResponse, error) { - if requestParams.ScriptName == "" { +func (api *API) ListWorkerBindings(ctx context.Context, rc *ResourceContainer, params ListWorkerBindingsParams) (WorkerBindingListResponse, error) { + if params.ScriptName == "" { return WorkerBindingListResponse{}, errors.New("ScriptName is required") } - if api.AccountID == "" { - return WorkerBindingListResponse{}, errors.New("account ID required") + + if rc.Level != AccountRouteLevel { + return WorkerBindingListResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return WorkerBindingListResponse{}, ErrMissingAccountID } - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings", api.AccountID, requestParams.ScriptName) + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings", rc.Identifier, params.ScriptName) var jsonRes struct { Response @@ -371,10 +380,11 @@ func (api *API) ListWorkerBindings(ctx context.Context, requestParams *WorkerReq case WorkerWebAssemblyBindingType: bindingListItem.Binding = WorkerWebAssemblyBinding{ Module: &bindingContentReader{ - ctx: ctx, - api: api, - requestParams: requestParams, - bindingName: name, + api: api, + ctx: ctx, + accountID: rc.Identifier, + params: ¶ms, + bindingName: name, }, } case WorkerPlainTextBindingType: @@ -415,18 +425,19 @@ func (api *API) ListWorkerBindings(ctx context.Context, requestParams *WorkerReq // is first called. This is only useful for binding types // that store raw bytes, like WebAssembly modules. type bindingContentReader struct { - api *API - requestParams *WorkerRequestParams - ctx context.Context - bindingName string - content []byte - position int + api *API + accountID string + params *ListWorkerBindingsParams + ctx context.Context + bindingName string + content []byte + position int } func (b *bindingContentReader) Read(p []byte) (n int, err error) { // Lazily load the content when Read() is first called if b.content == nil { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings/%s/content", b.api.AccountID, b.requestParams.ScriptName, b.bindingName) + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/bindings/%s/content", b.accountID, b.params.ScriptName, b.bindingName) res, err := b.api.makeRequestContext(b.ctx, http.MethodGet, uri, nil) if err != nil { return 0, err diff --git a/workers_cron_triggers.go b/workers_cron_triggers.go index 8938862aef..2322a5d682 100644 --- a/workers_cron_triggers.go +++ b/workers_cron_triggers.go @@ -27,12 +27,29 @@ type WorkerCronTrigger struct { ModifiedOn *time.Time `json:"modified_on,omitempty"` } +type ListWorkerCronTriggersParams struct { + ScriptName string +} + +type UpdateWorkerCronTriggersParams struct { + ScriptName string + Crons []WorkerCronTrigger +} + // ListWorkerCronTriggers fetches all available cron triggers for a single Worker // script. // // API reference: https://api.cloudflare.com/#worker-cron-trigger-get-cron-triggers -func (api *API) ListWorkerCronTriggers(ctx context.Context, accountID, scriptName string) ([]WorkerCronTrigger, error) { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/schedules", accountID, scriptName) +func (api *API) ListWorkerCronTriggers(ctx context.Context, rc *ResourceContainer, params ListWorkerCronTriggersParams) ([]WorkerCronTrigger, error) { + if rc.Level != AccountRouteLevel { + return []WorkerCronTrigger{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []WorkerCronTrigger{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/schedules", rc.Identifier, params.ScriptName) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []WorkerCronTrigger{}, err @@ -49,9 +66,17 @@ func (api *API) ListWorkerCronTriggers(ctx context.Context, accountID, scriptNam // UpdateWorkerCronTriggers updates a single schedule for a Worker cron trigger. // // API reference: https://api.cloudflare.com/#worker-cron-trigger-update-cron-triggers -func (api *API) UpdateWorkerCronTriggers(ctx context.Context, accountID, scriptName string, crons []WorkerCronTrigger) ([]WorkerCronTrigger, error) { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/schedules", accountID, scriptName) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, crons) +func (api *API) UpdateWorkerCronTriggers(ctx context.Context, rc *ResourceContainer, params UpdateWorkerCronTriggersParams) ([]WorkerCronTrigger, error) { + if rc.Level != AccountRouteLevel { + return []WorkerCronTrigger{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []WorkerCronTrigger{}, ErrMissingIdentifier + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/schedules", rc.Identifier, params.ScriptName) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.Crons) if err != nil { return []WorkerCronTrigger{}, err } diff --git a/workers_cron_triggers_test.go b/workers_cron_triggers_test.go index d2acba1e25..0194d75ef3 100644 --- a/workers_cron_triggers_test.go +++ b/workers_cron_triggers_test.go @@ -11,7 +11,7 @@ import ( ) func TestListWorkerCronTriggers(t *testing.T) { - setup(UsingAccount("9a7806061c88ada191ed06f989cc3dac")) + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -42,14 +42,14 @@ func TestListWorkerCronTriggers(t *testing.T) { CreatedOn: &createdOn, }} - actual, err := client.ListWorkerCronTriggers(context.Background(), testAccountID, "example-script") + actual, err := client.ListWorkerCronTriggers(context.Background(), AccountIdentifier(testAccountID), ListWorkerCronTriggersParams{ScriptName: "example-script"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } func TestUpdateWorkerCronTriggers(t *testing.T) { - setup(UsingAccount("9a7806061c88ada191ed06f989cc3dac")) + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { @@ -80,7 +80,7 @@ func TestUpdateWorkerCronTriggers(t *testing.T) { CreatedOn: &createdOn, }} - actual, err := client.UpdateWorkerCronTriggers(context.Background(), testAccountID, "example-script", want) + actual, err := client.UpdateWorkerCronTriggers(context.Background(), AccountIdentifier(testAccountID), UpdateWorkerCronTriggersParams{ScriptName: "example-script", Crons: want}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } diff --git a/workers_domains.go b/workers_domains.go deleted file mode 100644 index e8caea9793..0000000000 --- a/workers_domains.go +++ /dev/null @@ -1,48 +0,0 @@ -package cloudflare - -import ( - "context" - "encoding/json" - "fmt" - "net/http" -) - -type WorkerDomainParams struct { - ZoneID string `json:"zone_id"` - Hostname string `json:"hostname"` - Service string `json:"service"` - Environment string `json:"environment,omitempty"` -} - -type WorkerDomainResult struct { - ID string `json:"id"` - ZoneID string `json:"zone_id"` - ZoneName string `json:"zone_name"` - Hostname string `json:"hostname"` - Service string `json:"service"` - Environment string `json:"environment"` -} - -type WorkerDomainResponse struct { - Response - WorkerDomainResult `json:"result"` -} - -// AttachWorkerToDomain attaches a worker to a zone and hostname -// -// API reference: https://api.cloudflare.com/#worker-domain-attach-to-domain -func (api *API) AttachWorkerToDomain(ctx context.Context, rc *ResourceContainer, params *WorkerDomainParams) (WorkerDomainResponse, error) { - uri := fmt.Sprintf("/accounts/%s/workers/domains", rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) - if err != nil { - return WorkerDomainResponse{}, err - } - - var r WorkerDomainResponse - err = json.Unmarshal(res, &r) - if err != nil { - return WorkerDomainResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return r, nil -} diff --git a/workers_example_test.go b/workers_example_test.go deleted file mode 100644 index f70c7b93a7..0000000000 --- a/workers_example_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package cloudflare_test - -// var ( -// workerScript = "addEventListener('fetch', event => {\n event.passThroughOnException()\nevent.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n return fetch(request)\n}" -// ) - -// func ExampleAPI_UploadWorker() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}, &cloudflare.WorkerScriptParams{Script: workerScript}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) - -// UploadWorkerWithName() -// } - -// func UploadWorkerWithName() { -// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.UploadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}, &cloudflare.WorkerScriptParams{Script: workerScript}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_DownloadWorker() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) - -// DownloadWorkerWithName() -// } - -// func DownloadWorkerWithName() { -// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.DownloadWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_DeleteWorker() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } -// res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ZoneID: zoneID}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) - -// DeleteWorkerWithName() -// } - -// func DeleteWorkerWithName() { -// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.DeleteWorker(context.Background(), &cloudflare.WorkerRequestParams{ScriptName: "baz"}) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_ListWorkerScripts() { -// api, err := cloudflare.New(apiKey, user, cloudflare.UsingAccount("foo")) -// if err != nil { -// log.Fatal(err) -// } - -// res, err := api.ListWorkerScripts(context.Background()) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res.WorkerList) -// } - -// func ExampleAPI_CreateWorkerRoute() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } -// route := cloudflare.WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} -// res, err := api.CreateWorkerRoute(context.Background(), zoneID, route) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_UpdateWorkerRoute() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } -// // pull from existing list of routes to perform update on -// routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) -// if err != nil { -// log.Fatal(err) -// } -// route := cloudflare.WorkerRoute{Pattern: "app2.example.com/*", Enabled: true} -// // update first route retrieved from the listWorkerRoutes call with details above -// res, err := api.UpdateWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID, route) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_ListWorkerRoutes() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } -// res, err := api.ListWorkerRoutes(context.Background(), zoneID) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } - -// func ExampleAPI_DeleteWorkerRoute() { -// api, err := cloudflare.New(apiKey, user) -// if err != nil { -// log.Fatal(err) -// } - -// zoneID, err := api.ZoneIDByName(domain) -// if err != nil { -// log.Fatal(err) -// } -// // pull from existing list of routes to perform delete on -// routesResponse, err := api.ListWorkerRoutes(context.Background(), zoneID) -// if err != nil { -// log.Fatal(err) -// } -// // delete first route retrieved from the listWorkerRoutes call -// res, err := api.DeleteWorkerRoute(context.Background(), zoneID, routesResponse.Routes[0].ID) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("%+v", res) -// } diff --git a/workers_kv.go b/workers_kv.go index f7a01bc062..7cdf30e3c6 100644 --- a/workers_kv.go +++ b/workers_kv.go @@ -106,6 +106,13 @@ type ListWorkersKVsParams struct { // // API reference: https://api.cloudflare.com/#workers-kv-namespace-create-a-namespace func (api *API) CreateWorkersKVNamespace(ctx context.Context, rc *ResourceContainer, params CreateWorkersKVNamespaceParams) (WorkersKVNamespaceResponse, error) { + if rc.Level != AccountRouteLevel { + return WorkersKVNamespaceResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return WorkersKVNamespaceResponse{}, ErrMissingIdentifier + } uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { @@ -124,6 +131,14 @@ func (api *API) CreateWorkersKVNamespace(ctx context.Context, rc *ResourceContai // // API reference: https://api.cloudflare.com/#workers-kv-namespace-list-namespaces func (api *API) ListWorkersKVNamespaces(ctx context.Context, rc *ResourceContainer, params ListWorkersKVNamespacesParams) ([]WorkersKVNamespace, *ResultInfo, error) { + if rc.Level != AccountRouteLevel { + return []WorkersKVNamespace{}, &ResultInfo{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []WorkersKVNamespace{}, &ResultInfo{}, ErrMissingIdentifier + } + autoPaginate := true if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false @@ -183,6 +198,14 @@ func (api *API) DeleteWorkersKVNamespace(ctx context.Context, rc *ResourceContai // // API reference: https://api.cloudflare.com/#workers-kv-namespace-rename-a-namespace func (api *API) UpdateWorkersKVNamespace(ctx context.Context, rc *ResourceContainer, params UpdateWorkersKVNamespaceParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingIdentifier + } + uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s", rc.Identifier, params.NamespaceID) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { @@ -201,6 +224,14 @@ func (api *API) UpdateWorkersKVNamespace(ctx context.Context, rc *ResourceContai // // API reference: https://api.cloudflare.com/#workers-kv-namespace-write-key-value-pair func (api *API) WriteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, params WriteWorkersKVEntryParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingIdentifier + } + uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key)) res, err := api.makeRequestContextWithHeaders( ctx, http.MethodPut, uri, params.Value, http.Header{"Content-Type": []string{"application/octet-stream"}}, @@ -221,6 +252,14 @@ func (api *API) WriteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, // // API reference: https://api.cloudflare.com/#workers-kv-namespace-write-multiple-key-value-pairs func (api *API) WriteWorkersKVEntries(ctx context.Context, rc *ResourceContainer, params WriteWorkersKVEntriesParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingIdentifier + } + uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", rc.Identifier, params.NamespaceID) res, err := api.makeRequestContextWithHeaders( ctx, http.MethodPut, uri, params.KVs, http.Header{"Content-Type": []string{"application/json"}}, @@ -242,6 +281,13 @@ func (api *API) WriteWorkersKVEntries(ctx context.Context, rc *ResourceContainer // // API reference: https://api.cloudflare.com/#workers-kv-namespace-read-key-value-pair func (api API) GetWorkersKV(ctx context.Context, rc *ResourceContainer, params GetWorkersKVParams) ([]byte, error) { + if rc.Level != AccountRouteLevel { + return []byte(``), ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []byte(``), ErrMissingIdentifier + } uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key)) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -254,6 +300,13 @@ func (api API) GetWorkersKV(ctx context.Context, rc *ResourceContainer, params G // // API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-key-value-pair func (api API) DeleteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, params DeleteWorkersKVEntryParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingIdentifier + } uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/values/%s", rc.Identifier, params.NamespaceID, url.PathEscape(params.Key)) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -271,6 +324,13 @@ func (api API) DeleteWorkersKVEntry(ctx context.Context, rc *ResourceContainer, // // API reference: https://api.cloudflare.com/#workers-kv-namespace-delete-multiple-key-value-pairs func (api *API) DeleteWorkersKVEntries(ctx context.Context, rc *ResourceContainer, params DeleteWorkersKVEntriesParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingIdentifier + } uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/bulk", rc.Identifier, params.NamespaceID) res, err := api.makeRequestContextWithHeaders( ctx, http.MethodDelete, uri, params.Keys, http.Header{"Content-Type": []string{"application/json"}}, @@ -291,6 +351,14 @@ func (api *API) DeleteWorkersKVEntries(ctx context.Context, rc *ResourceContaine // // API Reference: https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys func (api API) ListWorkersKVKeys(ctx context.Context, rc *ResourceContainer, params ListWorkersKVsParams) (ListStorageKeysResponse, error) { + if rc.Level != AccountRouteLevel { + return ListStorageKeysResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return ListStorageKeysResponse{}, ErrMissingIdentifier + } + uri := buildURI( fmt.Sprintf("/accounts/%s/storage/kv/namespaces/%s/keys", rc.Identifier, params.NamespaceID), params, diff --git a/workers_routes.go b/workers_routes.go index 31ec7937bf..ec43d9e8bb 100644 --- a/workers_routes.go +++ b/workers_routes.go @@ -8,6 +8,8 @@ import ( "net/http" ) +var ErrMissingWorkerRouteID = errors.New("missing required route ID") + type ListWorkerRoutes struct{} type CreateWorkerRouteParams struct { @@ -18,6 +20,7 @@ type CreateWorkerRouteParams struct { type ListWorkerRoutesParams struct{} type UpdateWorkerRouteParams struct { + ID string `json:"id,omitempty"` Pattern string `json:"pattern"` Script string `json:"script,omitempty"` } @@ -140,7 +143,11 @@ func (api *API) UpdateWorkerRoute(ctx context.Context, rc *ResourceContainer, pa return WorkerRouteResponse{}, ErrMissingIdentifier } - uri := fmt.Sprintf("/zones/%s/workers/routes/%s", rc.Identifier, params.Script) + if params.ID == "" { + return WorkerRouteResponse{}, ErrMissingWorkerRouteID + } + + uri := fmt.Sprintf("/zones/%s/workers/routes/%s", rc.Identifier, params.ID) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return WorkerRouteResponse{}, err diff --git a/workers_routes_test.go b/workers_routes_test.go index 7182c1571a..f0070a913a 100644 --- a/workers_routes_test.go +++ b/workers_routes_test.go @@ -1,348 +1,121 @@ package cloudflare -// func TestWorkers_CreateWorkerRoute(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, createWorkerRouteResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} -// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) -// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_CreateWorkerRouteEnt(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, createWorkerRouteResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script"} -// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) -// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_CreateWorkerRouteSingleScriptWithAccount(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, createWorkerRouteResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true} -// res, err := client.CreateWorkerRoute(context.Background(), "foo", route) -// want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_CreateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { -// setup() -// defer teardown() - -// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} -// _, err := client.CreateWorkerRoute(context.Background(), "foo", route) -// assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") -// } - -// func TestWorkers_CreateWorkerRouteWithNoScript(t *testing.T) { -// setup() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, createWorkerRouteResponse) //nolint -// }) - -// route := WorkerRoute{Pattern: "app1.example.com/*"} -// _, err := client.CreateWorkerRoute(context.Background(), "foo", route) -// assert.NoError(t, err) -// } - -// func TestWorkers_DeleteWorkerRoute(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint -// }) -// res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// }} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_DeleteWorkerRouteEnt(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { -// assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) -// w.Header().Set("content-type", "application/json") -// fmt.Fprintf(w, deleteWorkerRouteResponseData) //nolint -// }) -// res, err := client.DeleteWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1") -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// }} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_ListWorkerRoutes(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/filters", 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, listRouteResponseData) //nolint -// }) - -// res, err := client.ListWorkerRoutes(context.Background(), "foo") -// want := WorkerRoutesResponse{successResponse, -// []WorkerRoute{ -// {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Enabled: true}, -// {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Enabled: false}, -// }, -// } -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_ListWorkerRoutesEnt(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes", 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, listRouteEntResponseData) //nolint -// }) - -// res, err := client.ListWorkerRoutes(context.Background(), "foo") -// want := WorkerRoutesResponse{successResponse, -// []WorkerRoute{ -// {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Script: "test_script_1", Enabled: true}, -// {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Script: "test_script_2", Enabled: true}, -// {ID: "2b5bf4240cd34c77852fac70b1bf745a", Pattern: "app3.example.com/*", Script: "", Enabled: false}, -// }, -// } -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_GetWorkerRoute(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/1234", 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, getRouteResponseData) //nolint -// }) - -// res, err := client.GetWorkerRoute(context.Background(), "foo", "1234") -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// Pattern: "app1.example.com/*", -// Script: "script-name"}, -// } -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_UpdateWorkerRoute(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} -// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// Pattern: "app3.example.com/*", -// Enabled: true, -// }} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_UpdateWorkerRouteEnt(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app3.example.com/*", Script: "test_script_1"} -// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// Pattern: "app3.example.com/*", -// Script: "test_script_1", -// }} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_UpdateWorkerRouteSingleScriptWithAccount(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/filters/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint -// }) -// route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true} -// res, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) -// want := WorkerRouteResponse{successResponse, -// WorkerRoute{ -// ID: "e7a57d8746e74ae49c25994dadb421b1", -// Pattern: "app3.example.com/*", -// Script: "test_script_1", -// }} -// if assert.NoError(t, err) { -// assert.Equal(t, want, res) -// } -// } - -// func TestWorkers_ListWorkerBindingsMultiScript(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings", 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, listBindingsResponseData) //nolint -// }) - -// mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings/MY_WASM/content", 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/wasm") -// _, _ = w.Write([]byte("mock multi-script wasm")) -// }) - -// res, err := client.ListWorkerBindings(context.Background(), &WorkerRequestParams{ -// ScriptName: "my-script", -// }) -// assert.NoError(t, err) - -// assert.Equal(t, successResponse, res.Response) -// assert.Equal(t, 7, len(res.BindingList)) - -// assert.Equal(t, res.BindingList[0], WorkerBindingListItem{ -// Name: "MY_KV", -// Binding: WorkerKvNamespaceBinding{ -// NamespaceID: "89f5f8fd93f94cb98473f6f421aa3b65", -// }, -// }) -// assert.Equal(t, WorkerKvNamespaceBindingType, res.BindingList[0].Binding.Type()) - -// assert.Equal(t, "MY_WASM", res.BindingList[1].Name) -// wasmBinding := res.BindingList[1].Binding.(WorkerWebAssemblyBinding) -// wasmModuleContent, err := io.ReadAll(wasmBinding.Module) -// assert.NoError(t, err) -// assert.Equal(t, []byte("mock multi-script wasm"), wasmModuleContent) -// assert.Equal(t, WorkerWebAssemblyBindingType, res.BindingList[1].Binding.Type()) - -// assert.Equal(t, res.BindingList[2], WorkerBindingListItem{ -// Name: "MY_PLAIN_TEXT", -// Binding: WorkerPlainTextBinding{ -// Text: "text", -// }, -// }) -// assert.Equal(t, WorkerPlainTextBindingType, res.BindingList[2].Binding.Type()) - -// assert.Equal(t, res.BindingList[3], WorkerBindingListItem{ -// Name: "MY_SECRET_TEXT", -// Binding: WorkerSecretTextBinding{}, -// }) -// assert.Equal(t, WorkerSecretTextBindingType, res.BindingList[3].Binding.Type()) - -// environment := "MY_ENVIRONMENT" -// assert.Equal(t, res.BindingList[4], WorkerBindingListItem{ -// Name: "MY_SERVICE_BINDING", -// Binding: WorkerServiceBinding{ -// Service: "MY_SERVICE", -// Environment: &environment, -// }, -// }) -// assert.Equal(t, WorkerServiceBindingType, res.BindingList[4].Binding.Type()) - -// assert.Equal(t, res.BindingList[5], WorkerBindingListItem{ -// Name: "MY_NEW_BINDING", -// Binding: WorkerInheritBinding{}, -// }) -// assert.Equal(t, WorkerInheritBindingType, res.BindingList[5].Binding.Type()) - -// assert.Equal(t, res.BindingList[6], WorkerBindingListItem{ -// Name: "MY_BUCKET", -// Binding: WorkerR2BucketBinding{ -// BucketName: "bucket", -// }, -// }) -// assert.Equal(t, WorkerR2BucketBindingType, res.BindingList[6].Binding.Type()) -// } - -// func TestWorkers_UpdateWorkerRouteErrorsWhenMixingSingleAndMultiScriptProperties(t *testing.T) { -// setup() -// defer teardown() - -// route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script", Enabled: true} -// _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) -// assert.EqualError(t, err, "Only `Script` or `Enabled` may be specified for a WorkerRoute, not both") -// } - -// func TestWorkers_UpdateWorkerRouteWithNoScript(t *testing.T) { -// setup() -// defer teardown() - -// mux.HandleFunc("/zones"+testAccountID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) //nolint -// }) - -// route := WorkerRoute{Pattern: "app1.example.com/*"} -// _, err := client.UpdateWorkerRoute(context.Background(), "foo", "e7a57d8746e74ae49c25994dadb421b1", route) -// assert.NoError(t, err) -// } +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateWorkersRoute(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/zones/"+testZoneID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, createWorkerRouteResponse) + }) + + res, err := client.CreateWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), CreateWorkerRouteParams{ + Pattern: "app1.example.com/*", + Script: "example", + }) + + want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}} + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} + +func TestDeleteWorkersRoute(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, deleteWorkerRouteResponseData) + }) + res, err := client.DeleteWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), "e7a57d8746e74ae49c25994dadb421b1") + want := WorkerRouteResponse{successResponse, + WorkerRoute{ + ID: "e7a57d8746e74ae49c25994dadb421b1", + }} + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} + +func TestListWorkersRoute(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/zones/"+testZoneID+"/workers/routes", 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, listWorkerRouteResponse) + }) + + res, err := client.ListWorkerRoutes(context.Background(), ZoneIdentifier(testZoneID), ListWorkerRoutesParams{}) + want := WorkerRoutesResponse{successResponse, + []WorkerRoute{ + {ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", ScriptName: "test_script_1"}, + {ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", ScriptName: "test_script_2"}, + {ID: "2b5bf4240cd34c77852fac70b1bf745a", Pattern: "app3.example.com/*", ScriptName: "test_script_3"}, + }, + } + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} + +func TestGetWorkersRoute(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/1234", 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, getRouteResponseData) + }) + + res, err := client.GetWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), "1234") + want := WorkerRouteResponse{successResponse, + WorkerRoute{ + ID: "e7a57d8746e74ae49c25994dadb421b1", + Pattern: "app1.example.com/*", + ScriptName: "script-name"}, + } + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} + +func TestUpdateWorkersRoute(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) + }) + + res, err := client.UpdateWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), UpdateWorkerRouteParams{ + ID: "e7a57d8746e74ae49c25994dadb421b1", + Pattern: "app3.example.com/*", + Script: "test_script_1", + }) + want := WorkerRouteResponse{successResponse, + WorkerRoute{ + ID: "e7a57d8746e74ae49c25994dadb421b1", + Pattern: "app3.example.com/*", + ScriptName: "test_script_1", + }} + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} diff --git a/workers_secrets.go b/workers_secrets.go index 09d8ba337e..20d30fe54d 100644 --- a/workers_secrets.go +++ b/workers_secrets.go @@ -32,11 +32,33 @@ type WorkersListSecretsResponse struct { Result []WorkersSecret `json:"result"` } +type SetWorkersSecretParams struct { + ScriptName string + Secret *WorkersPutSecretRequest +} + +type DeleteWorkersSecretParams struct { + ScriptName string + SecretName string +} + +type ListWorkersSecretsParams struct { + ScriptName string +} + // SetWorkersSecret creates or updates a secret // API reference: https://api.cloudflare.com/ -func (api *API) SetWorkersSecret(ctx context.Context, script string, req *WorkersPutSecretRequest) (WorkersPutSecretResponse, error) { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets", api.AccountID, script) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, req) +func (api *API) SetWorkersSecret(ctx context.Context, rc *ResourceContainer, params SetWorkersSecretParams) (WorkersPutSecretResponse, error) { + if rc.Level != AccountRouteLevel { + return WorkersPutSecretResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return WorkersPutSecretResponse{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets", rc.Identifier, params.ScriptName) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.Secret) if err != nil { return WorkersPutSecretResponse{}, err } @@ -51,8 +73,16 @@ func (api *API) SetWorkersSecret(ctx context.Context, script string, req *Worker // DeleteWorkersSecret deletes a secret // API reference: https://api.cloudflare.com/ -func (api *API) DeleteWorkersSecret(ctx context.Context, script, secretName string) (Response, error) { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets/%s", api.AccountID, script, secretName) +func (api *API) DeleteWorkersSecret(ctx context.Context, rc *ResourceContainer, params DeleteWorkersSecretParams) (Response, error) { + if rc.Level != AccountRouteLevel { + return Response{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return Response{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets/%s", rc.Identifier, params.ScriptName, params.SecretName) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return Response{}, err @@ -68,8 +98,16 @@ func (api *API) DeleteWorkersSecret(ctx context.Context, script, secretName stri // ListWorkersSecrets lists secrets for a given worker // API reference: https://api.cloudflare.com/ -func (api *API) ListWorkersSecrets(ctx context.Context, script string) (WorkersListSecretsResponse, error) { - uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets", api.AccountID, script) +func (api *API) ListWorkersSecrets(ctx context.Context, rc *ResourceContainer, params ListWorkersSecretsParams) (WorkersListSecretsResponse, error) { + if rc.Level != AccountRouteLevel { + return WorkersListSecretsResponse{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return WorkersListSecretsResponse{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/workers/scripts/%s/secrets", rc.Identifier, params.ScriptName) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return WorkersListSecretsResponse{}, err diff --git a/workers_secrets_test.go b/workers_secrets_test.go index c08ef71dd2..55af3d9f13 100644 --- a/workers_secrets_test.go +++ b/workers_secrets_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" ) -func TestWorkers_SetWorkersSecret(t *testing.T) { - setup(UsingAccount("foo")) +func TestSetWorkersSecret(t *testing.T) { + setup() defer teardown() response := `{ @@ -23,7 +23,7 @@ func TestWorkers_SetWorkersSecret(t *testing.T) { "messages": [] }` - mux.HandleFunc("/accounts/foo/workers/scripts/test-script/secrets", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets", 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/javascript") fmt.Fprintf(w, response) //nolint @@ -32,7 +32,7 @@ func TestWorkers_SetWorkersSecret(t *testing.T) { Name: "my-secret", Text: "super-secret", } - res, err := client.SetWorkersSecret(context.Background(), "test-script", req) + res, err := client.SetWorkersSecret(context.Background(), AccountIdentifier(testAccountID), SetWorkersSecretParams{ScriptName: "test-script", Secret: req}) want := WorkersPutSecretResponse{ successResponse, WorkersSecret{ @@ -46,8 +46,8 @@ func TestWorkers_SetWorkersSecret(t *testing.T) { } } -func TestWorkers_DeleteWorkersSecret(t *testing.T) { - setup(UsingAccount("foo")) +func TestDeleteWorkersSecret(t *testing.T) { + setup() defer teardown() response := `{ @@ -60,13 +60,13 @@ func TestWorkers_DeleteWorkersSecret(t *testing.T) { "messages": [] }` - mux.HandleFunc("/accounts/foo/workers/scripts/test-script/secrets/my-secret", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets/my-secret", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") fmt.Fprintf(w, response) //nolint }) - res, err := client.DeleteWorkersSecret(context.Background(), "test-script", "my-secret") + res, err := client.DeleteWorkersSecret(context.Background(), AccountIdentifier(testAccountID), DeleteWorkersSecretParams{ScriptName: "test-script", SecretName: "my-secret"}) want := successResponse if assert.NoError(t, err) { @@ -74,8 +74,8 @@ func TestWorkers_DeleteWorkersSecret(t *testing.T) { } } -func TestWorkers_ListWorkersSecret(t *testing.T) { - setup(UsingAccount("foo")) +func TestListWorkersSecret(t *testing.T) { + setup() defer teardown() response := `{ @@ -88,13 +88,13 @@ func TestWorkers_ListWorkersSecret(t *testing.T) { "messages": [] }` - mux.HandleFunc("/accounts/foo/workers/scripts/test-script/secrets", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets", 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/javascript") fmt.Fprintf(w, response) //nolint }) - res, err := client.ListWorkersSecrets(context.Background(), "test-script") + res, err := client.ListWorkersSecrets(context.Background(), AccountIdentifier(testAccountID), ListWorkersSecretsParams{ScriptName: "test-script"}) want := WorkersListSecretsResponse{ successResponse, []WorkersSecret{ diff --git a/workers_tail.go b/workers_tail.go index 478112b4a0..09d7f2fd1a 100644 --- a/workers_tail.go +++ b/workers_tail.go @@ -42,6 +42,7 @@ func (api *API) StartWorkersTail(ctx context.Context, rc *ResourceContainer, scr if rc.Identifier == "" { return WorkersTail{}, ErrMissingAccountID } + if scriptName == "" { return WorkersTail{}, ErrMissingScriptName } diff --git a/workers_test.go b/workers_test.go index d3a44d7f4e..2e08292c6b 100644 --- a/workers_test.go +++ b/workers_test.go @@ -89,7 +89,7 @@ const ( "errors": [], "messages": [] }` - listRouteEntResponseData = `{ + listWorkerRouteResponse = `{ "result": [ { "id": "e7a57d8746e74ae49c25994dadb421b1", @@ -103,7 +103,8 @@ const ( }, { "id": "2b5bf4240cd34c77852fac70b1bf745a", - "pattern": "app3.example.com/*" + "pattern": "app3.example.com/*", + "script": "test_script_3" } ], "success": true, @@ -389,7 +390,7 @@ func TestListWorkers(t *testing.T) { fmt.Fprintf(w, listWorkersResponseData) }) - res, err := client.ListWorkers(context.Background(), AccountIdentifier(testAccountID), ListWorkersParams{}) + res, _, err := client.ListWorkers(context.Background(), AccountIdentifier(testAccountID), ListWorkersParams{}) sampleDate, _ := time.Parse(time.RFC3339Nano, "2018-04-22T17:10:48.938097Z") want := []WorkerMetaData{ { @@ -421,7 +422,7 @@ func TestUploadWorker_Basic(t *testing.T) { w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) //nolint }) - res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{Name: "foo", Script: workerScript}) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ successResponse, @@ -460,7 +461,7 @@ func TestUploadWorker_Module(t *testing.T) { w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerModuleResponseData) }) - res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{Name: "foo", Script: workerModuleScript, Module: true}) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerModuleScript, Module: true}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ successResponse, @@ -506,8 +507,8 @@ func TestUploadWorker_WithDurableObjectBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerDurableObjectBinding{ ClassName: "TheClass", @@ -563,8 +564,8 @@ func TestUploadWorker_WithInheritBinding(t *testing.T) { }} res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerInheritBinding{}, "b2": WorkerInheritBinding{ @@ -602,8 +603,8 @@ func TestUploadWorker_WithKVBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerKvNamespaceBinding{ NamespaceID: "test-namespace", @@ -643,8 +644,8 @@ func TestUploadWorker_WithWasmBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerWebAssemblyBinding{ Module: strings.NewReader("fake-wasm"), @@ -681,8 +682,8 @@ func TestUploadWorker_WithPlainTextBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerPlainTextBinding{ Text: "plain text value", @@ -726,9 +727,9 @@ func TestUploadWorker_ModuleWithPlainTextBinding(t *testing.T) { }) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerModuleScript, - Module: true, + ScriptName: "bar", + Script: workerModuleScript, + Module: true, Bindings: map[string]WorkerBinding{ "b1": WorkerPlainTextBinding{ Text: "plain text value", @@ -765,8 +766,8 @@ func TestUploadWorker_WithSecretTextBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerSecretTextBinding{ Text: "secret text value", @@ -808,8 +809,8 @@ func TestUploadWorker_WithServiceBinding(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ - Name: "bar", - Script: workerScript, + ScriptName: "bar", + Script: workerScript, Bindings: map[string]WorkerBinding{ "b1": WorkerServiceBinding{ Service: "the_service", From b40cdd033f824586420f0ba9c0bf8d27b988c865 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 30 Nov 2022 15:20:15 +1100 Subject: [PATCH 010/370] update godoc --- workers.go | 2 +- workers_bindings.go | 10 +++++----- workers_routes.go | 8 ++++---- workers_secrets.go | 6 ++++-- workers_tail.go | 6 +++--- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/workers.go b/workers.go index ae2bf7c5df..d5474bc034 100644 --- a/workers.go +++ b/workers.go @@ -103,7 +103,7 @@ type DeleteWorkerParams struct { ScriptName string } -// DeleteWorker deletes worker for a zone. +// DeleteWorker deletes a single Worker. // // API reference: https://api.cloudflare.com/#worker-script-delete-worker func (api *API) DeleteWorker(ctx context.Context, rc *ResourceContainer, params DeleteWorkerParams) error { diff --git a/workers_bindings.go b/workers_bindings.go index d2ac3ee96a..9631065892 100644 --- a/workers_bindings.go +++ b/workers_bindings.go @@ -106,7 +106,7 @@ func (b WorkerInheritBinding) serialize(bindingName string) (workerBindingMeta, return meta, nil, nil } -// WorkerKvNamespaceBinding is a binding to a Workers KV Namespace +// WorkerKvNamespaceBinding is a binding to a Workers KV Namespace. // // https://developers.cloudflare.com/workers/archive/api/resource-bindings/kv-namespaces/ type WorkerKvNamespaceBinding struct { @@ -130,7 +130,7 @@ func (b WorkerKvNamespaceBinding) serialize(bindingName string) (workerBindingMe }, nil, nil } -// WorkerDurableObjectBinding is a binding to a Workers Durable Object +// WorkerDurableObjectBinding is a binding to a Workers Durable Object. // // https://api.cloudflare.com/#durable-objects-namespace-properties type WorkerDurableObjectBinding struct { @@ -156,7 +156,7 @@ func (b WorkerDurableObjectBinding) serialize(bindingName string) (workerBinding }, nil, nil } -// WorkerWebAssemblyBinding is a binding to a WebAssembly module +// WorkerWebAssemblyBinding is a binding to a WebAssembly module. // // https://developers.cloudflare.com/workers/archive/api/resource-bindings/webassembly-modules/ type WorkerWebAssemblyBinding struct { @@ -190,7 +190,7 @@ func (b WorkerWebAssemblyBinding) serialize(bindingName string) (workerBindingMe }, bodyWriter, nil } -// WorkerPlainTextBinding is a binding to plain text +// WorkerPlainTextBinding is a binding to plain text. // // https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-plain-text-binding type WorkerPlainTextBinding struct { @@ -214,7 +214,7 @@ func (b WorkerPlainTextBinding) serialize(bindingName string) (workerBindingMeta }, nil, nil } -// WorkerSecretTextBinding is a binding to secret text +// WorkerSecretTextBinding is a binding to secret text. // // https://developers.cloudflare.com/workers/tooling/api/scripts/#add-a-secret-text-binding type WorkerSecretTextBinding struct { diff --git a/workers_routes.go b/workers_routes.go index ec43d9e8bb..d6dc1c2a71 100644 --- a/workers_routes.go +++ b/workers_routes.go @@ -25,7 +25,7 @@ type UpdateWorkerRouteParams struct { Script string `json:"script,omitempty"` } -// CreateWorkerRoute creates worker route for a zone +// CreateWorkerRoute creates worker route for a script. // // API reference: https://api.cloudflare.com/#worker-routes-create-route func (api *API) CreateWorkerRoute(ctx context.Context, rc *ResourceContainer, params CreateWorkerRouteParams) (WorkerRouteResponse, error) { @@ -51,7 +51,7 @@ func (api *API) CreateWorkerRoute(ctx context.Context, rc *ResourceContainer, pa return r, nil } -// DeleteWorkerRoute deletes worker route for a zone +// DeleteWorkerRoute deletes worker route for a script. // // API reference: https://api.cloudflare.com/#worker-routes-delete-route func (api *API) DeleteWorkerRoute(ctx context.Context, rc *ResourceContainer, routeID string) (WorkerRouteResponse, error) { @@ -80,7 +80,7 @@ func (api *API) DeleteWorkerRoute(ctx context.Context, rc *ResourceContainer, ro return r, nil } -// ListWorkerRoutes returns list of Worker routes +// ListWorkerRoutes returns list of Worker routes. // // API reference: https://api.cloudflare.com/#worker-routes-list-routes func (api *API) ListWorkerRoutes(ctx context.Context, rc *ResourceContainer, params ListWorkerRoutesParams) (WorkerRoutesResponse, error) { @@ -131,7 +131,7 @@ func (api *API) GetWorkerRoute(ctx context.Context, rc *ResourceContainer, route return r, nil } -// UpdateWorkerRoute updates worker route for a zone. +// UpdateWorkerRoute updates worker route for a script. // // API reference: https://api.cloudflare.com/#worker-routes-update-route func (api *API) UpdateWorkerRoute(ctx context.Context, rc *ResourceContainer, params UpdateWorkerRouteParams) (WorkerRouteResponse, error) { diff --git a/workers_secrets.go b/workers_secrets.go index 20d30fe54d..458cd1a7c4 100644 --- a/workers_secrets.go +++ b/workers_secrets.go @@ -46,7 +46,8 @@ type ListWorkersSecretsParams struct { ScriptName string } -// SetWorkersSecret creates or updates a secret +// SetWorkersSecret creates or updates a secret. +// // API reference: https://api.cloudflare.com/ func (api *API) SetWorkersSecret(ctx context.Context, rc *ResourceContainer, params SetWorkersSecretParams) (WorkersPutSecretResponse, error) { if rc.Level != AccountRouteLevel { @@ -71,7 +72,8 @@ func (api *API) SetWorkersSecret(ctx context.Context, rc *ResourceContainer, par return result, err } -// DeleteWorkersSecret deletes a secret +// DeleteWorkersSecret deletes a secret. +// // API reference: https://api.cloudflare.com/ func (api *API) DeleteWorkersSecret(ctx context.Context, rc *ResourceContainer, params DeleteWorkersSecretParams) (Response, error) { if rc.Level != AccountRouteLevel { diff --git a/workers_tail.go b/workers_tail.go index 09d7f2fd1a..0f074b0b66 100644 --- a/workers_tail.go +++ b/workers_tail.go @@ -35,7 +35,7 @@ type ListWorkersTailResponse struct { Result WorkersTail } -// StartWorkersTail Starts a tail that receives logs and exception from a Worker +// StartWorkersTail Starts a tail that receives logs and exception from a Worker. // // API reference: https://api.cloudflare.com/#worker-tail-logs-start-tail func (api *API) StartWorkersTail(ctx context.Context, rc *ResourceContainer, scriptName string) (WorkersTail, error) { @@ -61,7 +61,7 @@ func (api *API) StartWorkersTail(ctx context.Context, rc *ResourceContainer, scr return workerstailResponse.Result, nil } -// ListWorkersTail Get list of tails currently deployed on a worker +// ListWorkersTail Get list of tails currently deployed on a Worker. // // API reference: https://api.cloudflare.com/#worker-tail-logs-list-tails func (api *API) ListWorkersTail(ctx context.Context, rc *ResourceContainer, params ListWorkersTailParameters) (WorkersTail, error) { @@ -87,7 +87,7 @@ func (api *API) ListWorkersTail(ctx context.Context, rc *ResourceContainer, para return workerstailResponse.Result, nil } -// DeleteWorkersTail Deletes a tail from a Worker +// DeleteWorkersTail Deletes a tail from a Worker. // // API reference: https://api.cloudflare.com/#worker-tail-logs-delete-tail func (api *API) DeleteWorkersTail(ctx context.Context, rc *ResourceContainer, scriptName, tailID string) error { From 50a6512cfcbfcc38e7030aa922d9b6e7eb5db7fc Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 30 Nov 2022 15:27:03 +1100 Subject: [PATCH 011/370] add changelog entry for workers methods --- .changelog/1137.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .changelog/1137.txt diff --git a/.changelog/1137.txt b/.changelog/1137.txt new file mode 100644 index 0000000000..b479d14d44 --- /dev/null +++ b/.changelog/1137.txt @@ -0,0 +1,39 @@ +```release-note:note +workers: all worker methods have been split into product ownership(-ish) files +``` + +```release-note:note +workers: all worker methods now require an explicit `ResourceContainer` for endpoints instead of relying on the globally defined `api.AccountID` +``` + +```release-note:breaking-change +workers: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers: API operations now target account level resources instead of older zone level resources (these are a 1:1 now) +``` + +```release-note:breaking-change +workers_bindings: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers_kv: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers_tails: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers_secrets: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers_routes: method signatures have been updated to align with the upcoming client conventions +``` + +```release-note:breaking-change +workers_cron_triggers: method signatures have been updated to align with the upcoming client conventions +``` From f7fe8394019ddc7245a7f2153736872d039af75a Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 30 Nov 2022 15:30:46 +1100 Subject: [PATCH 012/370] clean up linter errors --- workers_bindings_test.go | 2 +- workers_kv_test.go | 26 +++++++++++++------------- workers_routes_test.go | 10 +++++----- workers_secrets_test.go | 6 +++--- workers_test.go | 28 ++++++++++++++-------------- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/workers_bindings_test.go b/workers_bindings_test.go index a21aec3419..f8dea25ad3 100644 --- a/workers_bindings_test.go +++ b/workers_bindings_test.go @@ -17,7 +17,7 @@ func TestListWorkerBindings(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings", 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, listBindingsResponseData) + fmt.Fprint(w, listBindingsResponseData) }) mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/my-script/bindings/MY_WASM/content", func(w http.ResponseWriter, r *http.Request) { diff --git a/workers_kv_test.go b/workers_kv_test.go index 1ad7ae091d..80d7b140b9 100644 --- a/workers_kv_test.go +++ b/workers_kv_test.go @@ -29,7 +29,7 @@ func TestWorkersKV_CreateWorkersKVNamespace(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/storage/kv/namespaces", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.CreateWorkersKVNamespace(context.Background(), AccountIdentifier(testAccountID), CreateWorkersKVNamespaceParams{Title: "Namespace"}) @@ -60,7 +60,7 @@ func TestWorkersKV_DeleteWorkersKVNamespace(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s", namespace), func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.DeleteWorkersKVNamespace(context.Background(), AccountIdentifier(testAccountID), namespace) @@ -99,7 +99,7 @@ func TestWorkersKV_ListWorkersKVNamespaces(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/storage/kv/namespaces", 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, _, err := client.ListWorkersKVNamespaces(context.Background(), AccountIdentifier(testAccountID), ListWorkersKVNamespacesParams{}) @@ -170,10 +170,10 @@ func TestWorkersKV_ListWorkersKVNamespaceMultiplePages(t *testing.T) { w.Header().Set("content-type", "application/javascript") if r.URL.Query().Get("page") == "1" { - fmt.Fprintf(w, response1) //nolint + fmt.Fprint(w, response1) return } else if r.URL.Query().Get("page") == "2" { - fmt.Fprintf(w, response2) //nolint + fmt.Fprint(w, response2) return } else { panic(errors.New("Got a request for an unexpected page")) @@ -218,7 +218,7 @@ func TestWorkersKV_UpdateWorkersKVNamespace(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s", namespace), 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.UpdateWorkersKVNamespace(context.Background(), AccountIdentifier(testAccountID), UpdateWorkersKVNamespaceParams{Title: "Namespace", NamespaceID: namespace}) @@ -246,7 +246,7 @@ func TestWorkersKV_WriteWorkersKVEntry(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/values/%s", namespace, key), 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/octet-stream") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) want := successResponse @@ -278,7 +278,7 @@ func TestWorkersKV_WriteWorkersKVEntries(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/bulk", namespace), 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, response) //nolint + fmt.Fprint(w, response) }) want := successResponse @@ -297,7 +297,7 @@ func TestWorkersKV_ReadWorkersKV(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/values/%s", namespace, key), 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", "text/plain") - fmt.Fprintf(w, "test_value") + fmt.Fprint(w, "test_value") }) res, err := client.GetWorkersKV(context.Background(), AccountIdentifier(testAccountID), GetWorkersKVParams{NamespaceID: namespace, Key: key}) @@ -324,7 +324,7 @@ func TestWorkersKV_DeleteWorkersKVEntry(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/values/%s", namespace, key), func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.DeleteWorkersKVEntry(context.Background(), AccountIdentifier(testAccountID), DeleteWorkersKVEntryParams{NamespaceID: namespace, Key: key}) @@ -352,7 +352,7 @@ func TestWorkersKV_DeleteWorkersKVBulk(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/bulk", namespace), func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) want := successResponse @@ -386,7 +386,7 @@ func TestWorkersKV_ListKeys(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/keys", namespace), 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.ListWorkersKVKeys(context.Background(), AccountIdentifier(testAccountID), ListWorkersKVsParams{NamespaceID: namespace}) @@ -456,7 +456,7 @@ func TestWorkersKV_ListKeysWithParameters(t *testing.T) { mux.HandleFunc(fmt.Sprintf("/accounts/"+testAccountID+"/storage/kv/namespaces/%s/keys", namespace), 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) limit, prefix := 25, "test-prefix" diff --git a/workers_routes_test.go b/workers_routes_test.go index f0070a913a..8d36fdc9d4 100644 --- a/workers_routes_test.go +++ b/workers_routes_test.go @@ -16,7 +16,7 @@ func TestCreateWorkersRoute(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/workers/routes", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, createWorkerRouteResponse) + fmt.Fprint(w, createWorkerRouteResponse) }) res, err := client.CreateWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), CreateWorkerRouteParams{ @@ -37,7 +37,7 @@ func TestDeleteWorkersRoute(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, deleteWorkerRouteResponseData) + fmt.Fprint(w, deleteWorkerRouteResponseData) }) res, err := client.DeleteWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), "e7a57d8746e74ae49c25994dadb421b1") want := WorkerRouteResponse{successResponse, @@ -56,7 +56,7 @@ func TestListWorkersRoute(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/workers/routes", 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, listWorkerRouteResponse) + fmt.Fprint(w, listWorkerRouteResponse) }) res, err := client.ListWorkerRoutes(context.Background(), ZoneIdentifier(testZoneID), ListWorkerRoutesParams{}) @@ -79,7 +79,7 @@ func TestGetWorkersRoute(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/1234", 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, getRouteResponseData) + fmt.Fprint(w, getRouteResponseData) }) res, err := client.GetWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), "1234") @@ -101,7 +101,7 @@ func TestUpdateWorkersRoute(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/workers/routes/e7a57d8746e74ae49c25994dadb421b1", 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, updateWorkerRouteEntResponse) + fmt.Fprint(w, updateWorkerRouteEntResponse) }) res, err := client.UpdateWorkerRoute(context.Background(), ZoneIdentifier(testZoneID), UpdateWorkerRouteParams{ diff --git a/workers_secrets_test.go b/workers_secrets_test.go index 55af3d9f13..dc3ac99faa 100644 --- a/workers_secrets_test.go +++ b/workers_secrets_test.go @@ -26,7 +26,7 @@ func TestSetWorkersSecret(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets", 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) req := &WorkersPutSecretRequest{ Name: "my-secret", @@ -63,7 +63,7 @@ func TestDeleteWorkersSecret(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets/my-secret", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.DeleteWorkersSecret(context.Background(), AccountIdentifier(testAccountID), DeleteWorkersSecretParams{ScriptName: "test-script", SecretName: "my-secret"}) @@ -91,7 +91,7 @@ func TestListWorkersSecret(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/test-script/secrets", 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/javascript") - fmt.Fprintf(w, response) //nolint + fmt.Fprint(w, response) }) res, err := client.ListWorkersSecrets(context.Background(), AccountIdentifier(testAccountID), ListWorkersSecretsParams{ScriptName: "test-script"}) diff --git a/workers_test.go b/workers_test.go index 2e08292c6b..647f1af327 100644 --- a/workers_test.go +++ b/workers_test.go @@ -328,7 +328,7 @@ func TestDeleteWorker(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/javascript") - fmt.Fprintf(w, deleteWorkerResponseData) + fmt.Fprint(w, deleteWorkerResponseData) }) err := client.DeleteWorker(context.Background(), AccountIdentifier(testAccountID), DeleteWorkerParams{ScriptName: "bar"}) @@ -342,7 +342,7 @@ func TestGetWorker(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", 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/javascript") - fmt.Fprintf(w, workerScript) + fmt.Fprint(w, workerScript) }) res, err := client.GetWorker(context.Background(), AccountIdentifier(testAccountID), "foo") want := WorkerScriptResponse{ @@ -363,7 +363,7 @@ func TestGetWorker_Module(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", 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", "multipart/form-data; boundary=workermodulescriptdownload") - fmt.Fprintf(w, workerModuleScriptDownloadResponse) + fmt.Fprint(w, workerModuleScriptDownloadResponse) }) res, err := client.GetWorker(context.Background(), AccountIdentifier(testAccountID), "foo") @@ -387,7 +387,7 @@ func TestListWorkers(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts", 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, listWorkersResponseData) + fmt.Fprint(w, listWorkersResponseData) }) res, _, err := client.ListWorkers(context.Background(), AccountIdentifier(testAccountID), ListWorkersParams{}) @@ -420,7 +420,7 @@ func TestUploadWorker_Basic(t *testing.T) { contentTypeHeader := r.Header.Get("content-type") assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprint(w, uploadWorkerResponseData) }) res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") @@ -459,7 +459,7 @@ func TestUploadWorker_Module(t *testing.T) { assert.Equal(t, expectedContentType, contentTypeHeader, "Expected content-type request header to be %s, got %s", expectedContentType, contentTypeHeader) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerModuleResponseData) + fmt.Fprint(w, uploadWorkerModuleResponseData) }) res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerModuleScript, Module: true}) formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") @@ -501,7 +501,7 @@ func TestUploadWorker_WithDurableObjectBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -546,7 +546,7 @@ func TestUploadWorker_WithInheritBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -598,7 +598,7 @@ func TestUploadWorker_WithKVBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -639,7 +639,7 @@ func TestUploadWorker_WithWasmBinding(t *testing.T) { assert.Equal(t, []byte("fake-wasm"), wasmContent) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -677,7 +677,7 @@ func TestUploadWorker_WithPlainTextBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -723,7 +723,7 @@ func TestUploadWorker_ModuleWithPlainTextBinding(t *testing.T) { assert.Equal(t, expectedContentDisposition, contentDispositonHeader, "Expected content-disposition request header to be %s, got %s", expectedContentDisposition, contentDispositonHeader) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerModuleResponseData) //nolint + fmt.Fprint(w, uploadWorkerModuleResponseData) }) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ @@ -761,7 +761,7 @@ func TestUploadWorker_WithSecretTextBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -804,7 +804,7 @@ func TestUploadWorker_WithServiceBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) //nolint + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) From 1a69cb258e1c08a57174de8fc6d30e615e9e19e5 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 5 Dec 2022 08:58:08 +0000 Subject: [PATCH 013/370] Update CHANGELOG.md for #1136 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594b3bd880..da8af86849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ ## 0.56.0 (Unreleased) +BREAKING CHANGES: + +* pages: Changed the type of EnvVars in PagesProjectDeploymentConfigEnvironment & PagesProjectDeployment in order to properly support secrets. ([#1136](https://github.com/cloudflare/cloudflare-go/issues/1136)) + NOTES: * pages: removed the v1 logs endpoint for Pages deployments. Please switch to v2: https://developers.cloudflare.com/api/operations/pages-deployment-get-deployment-logs ([#1135](https://github.com/cloudflare/cloudflare-go/issues/1135)) ENHANCEMENTS: +* pages: Updates bindings and other Functions related propreties. Service bindings, secrets, fail open/close and usage model are all now supported. ([#1136](https://github.com/cloudflare/cloudflare-go/issues/1136)) * workers: Support for Workers Analytics Engine bindings ([#1133](https://github.com/cloudflare/cloudflare-go/issues/1133)) ## 0.55.0 (November 23th, 2022) From 14bf9fe4e218a2951cf2462e8c21c343c30011e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 16:01:00 +0000 Subject: [PATCH 014/370] build(deps): bump github.com/urfave/cli/v2 from 2.23.5 to 2.23.6 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.23.5 to 2.23.6. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.23.5...v2.23.6) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6f7c4fe2c2..0180f040b2 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.1 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.23.5 + github.com/urfave/cli/v2 v2.23.6 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 310708a4bf..5c629c4917 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw= -github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.23.6 h1:iWmtKD+prGo1nKUtLO0Wg4z9esfBM4rAV4QRLQiEmJ4= +github.com/urfave/cli/v2 v2.23.6/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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 9292d79ed5974c3c526d67a791bbc314f2607456 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 5 Dec 2022 16:01:22 +0000 Subject: [PATCH 015/370] add CHANGELOG for #1139 --- .changelog/1139.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1139.txt diff --git a/.changelog/1139.txt b/.changelog/1139.txt new file mode 100644 index 0000000000..71f26a2e88 --- /dev/null +++ b/.changelog/1139.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.23.5 to 2.23.6 +``` From 4db8734a77f5ca2ce7f5ee667134f46440efd914 Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Mon, 5 Dec 2022 13:21:07 -0500 Subject: [PATCH 016/370] add Ignore option to cache rules query string struct --- rulesets.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rulesets.go b/rulesets.go index 4a15f579fb..1f18d64a7a 100644 --- a/rulesets.go +++ b/rulesets.go @@ -330,6 +330,7 @@ type RulesetRuleActionParametersCustomKeyFields struct { type RulesetRuleActionParametersCustomKeyQuery struct { Include *RulesetRuleActionParametersCustomKeyList `json:"include,omitempty"` Exclude *RulesetRuleActionParametersCustomKeyList `json:"exclude,omitempty"` + Ignore *bool `json:"ignore,omitempty"` } type RulesetRuleActionParametersCustomKeyList struct { From 1851bd7af17b941a3d5688198dfeb94af55bf32c Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Mon, 5 Dec 2022 13:26:33 -0500 Subject: [PATCH 017/370] add changelog --- .changelog/1140.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1140.txt diff --git a/.changelog/1140.txt b/.changelog/1140.txt new file mode 100644 index 0000000000..f6b31ad5a8 --- /dev/null +++ b/.changelog/1140.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cache_rules: add ignore option to query string struct +``` \ No newline at end of file From f6e2924bc01107f2e833624687d8955d6d74b8d8 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 5 Dec 2022 18:37:06 +0000 Subject: [PATCH 018/370] Update CHANGELOG.md for #1139 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da8af86849..f1ced88b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ ENHANCEMENTS: * pages: Updates bindings and other Functions related propreties. Service bindings, secrets, fail open/close and usage model are all now supported. ([#1136](https://github.com/cloudflare/cloudflare-go/issues/1136)) * workers: Support for Workers Analytics Engine bindings ([#1133](https://github.com/cloudflare/cloudflare-go/issues/1133)) +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.23.5 to 2.23.6 ([#1139](https://github.com/cloudflare/cloudflare-go/issues/1139)) + ## 0.55.0 (November 23th, 2022) BREAKING CHANGES: From 701879076553e5495fae578ff4e25893d4fafa44 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 5 Dec 2022 19:13:39 +0000 Subject: [PATCH 019/370] Update CHANGELOG.md for #1140 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1ced88b6c..07dd039ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ NOTES: ENHANCEMENTS: +* cache_rules: add ignore option to query string struct ([#1140](https://github.com/cloudflare/cloudflare-go/issues/1140)) * pages: Updates bindings and other Functions related propreties. Service bindings, secrets, fail open/close and usage model are all now supported. ([#1136](https://github.com/cloudflare/cloudflare-go/issues/1136)) * workers: Support for Workers Analytics Engine bindings ([#1133](https://github.com/cloudflare/cloudflare-go/issues/1133)) From d7efda7b30549c48e7e69cf9b1b76c518138dfdc Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Mon, 5 Dec 2022 15:53:01 -0500 Subject: [PATCH 020/370] fix CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07dd039ccb..f0487665f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ -## 0.56.0 (Unreleased) +## 0.57.0 (Unreleased) +## 0.56.0 (December 5th, 2022) BREAKING CHANGES: From 29204296b5429e17acefd404ba9383d92c1694a6 Mon Sep 17 00:00:00 2001 From: Michael Borkenstein Date: Tue, 6 Dec 2022 14:26:11 -0600 Subject: [PATCH 021/370] GATE-3151: adds support for egress policies --- .changelog/1142.txt | 3 +++ teams_rules.go | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .changelog/1142.txt diff --git a/.changelog/1142.txt b/.changelog/1142.txt new file mode 100644 index 0000000000..48f9efbcd7 --- /dev/null +++ b/.changelog/1142.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +teams_rules: adds support for Egress Policies +``` diff --git a/teams_rules.go b/teams_rules.go index 5a7732049b..16c5134e2a 100644 --- a/teams_rules.go +++ b/teams_rules.go @@ -35,6 +35,14 @@ type TeamsRuleSettings struct { // whether to disable dnssec validation for allow action InsecureDisableDNSSECValidation bool `json:"insecure_disable_dnssec_validation"` + + EgressSettings *EgressSettings `json:"egress"` +} + +type EgressSettings struct { + Ipv6Range string `json:"ipv6"` + Ipv4 string `json:"ipv4"` + Ipv4Fallback string `json:"ipv4_fallback"` } // TeamsL4OverrideSettings used in l4 filter type rule with action set to override. @@ -61,9 +69,10 @@ type TeamsFilterType string type TeamsGatewayAction string const ( - HttpFilter TeamsFilterType = "http" - DnsFilter TeamsFilterType = "dns" - L4Filter TeamsFilterType = "l4" + HttpFilter TeamsFilterType = "http" + DnsFilter TeamsFilterType = "dns" + L4Filter TeamsFilterType = "l4" + EgressFilter TeamsFilterType = "egress" ) const ( @@ -79,6 +88,7 @@ const ( NoIsolate TeamsGatewayAction = "noisolate" Override TeamsGatewayAction = "override" L4Override TeamsGatewayAction = "l4_override" + Egress TeamsGatewayAction = "egress" ) func TeamsRulesActionValues() []string { @@ -95,6 +105,7 @@ func TeamsRulesActionValues() []string { string(NoIsolate), string(Override), string(L4Override), + string(Egress), } } From bd8b1a3ab9317290dca6bf6373aeda5592b7f9a9 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 9 Dec 2022 19:41:46 +0000 Subject: [PATCH 022/370] Update CHANGELOG.md for #1137 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0487665f0..eb62fee0ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,21 @@ ## 0.57.0 (Unreleased) + +BREAKING CHANGES: + +* workers: API operations now target account level resources instead of older zone level resources (these are a 1:1 now) ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_bindings: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_cron_triggers: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_kv: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_routes: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_secrets: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers_tails: method signatures have been updated to align with the upcoming client conventions ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) + +NOTES: + +* workers: all worker methods have been split into product ownership(-ish) files ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +* workers: all worker methods now require an explicit `ResourceContainer` for endpoints instead of relying on the globally defined `api.AccountID` ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) + ## 0.56.0 (December 5th, 2022) BREAKING CHANGES: From 600453b4c7cd41f93890b7636d52d78b23e5112f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 16:00:59 +0000 Subject: [PATCH 023/370] build(deps): bump github.com/urfave/cli/v2 from 2.23.6 to 2.23.7 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.23.6 to 2.23.7. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.23.6...v2.23.7) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0180f040b2..e1025876d6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.1 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.23.6 + github.com/urfave/cli/v2 v2.23.7 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 5c629c4917..35c42f5773 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.23.6 h1:iWmtKD+prGo1nKUtLO0Wg4z9esfBM4rAV4QRLQiEmJ4= -github.com/urfave/cli/v2 v2.23.6/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= +github.com/urfave/cli/v2 v2.23.7/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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 29acf5b16920a0468ed812f15478ce02a92eae6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 16:02:40 +0000 Subject: [PATCH 024/370] build(deps): bump goreleaser/goreleaser-action from 3.2.0 to 4.1.0 Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3.2.0 to 4.1.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v3.2.0...v4.1.0) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9d6a468159..7063c4e377 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: with: go-version: ^1.17 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v3.2.0 + uses: goreleaser/goreleaser-action@v4.1.0 with: version: latest args: release --rm-dist From 8bf017c25de3394f80ed0fb110739ababc723145 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 13 Dec 2022 16:03:02 +0000 Subject: [PATCH 025/370] add CHANGELOG for #1146 --- .changelog/1146.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1146.txt diff --git a/.changelog/1146.txt b/.changelog/1146.txt new file mode 100644 index 0000000000..76ce4035d9 --- /dev/null +++ b/.changelog/1146.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps goreleaser/goreleaser-action from 3.2.0 to 4.1.0 +``` From 898dfae3766df1c7fc0a009529a5d8599f19c192 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 13 Dec 2022 19:30:20 +0000 Subject: [PATCH 026/370] Update CHANGELOG.md for #1146 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb62fee0ed..59e388e900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ NOTES: * workers: all worker methods have been split into product ownership(-ish) files ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) * workers: all worker methods now require an explicit `ResourceContainer` for endpoints instead of relying on the globally defined `api.AccountID` ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +DEPENDENCIES: + +* deps: bumps goreleaser/goreleaser-action from 3.2.0 to 4.1.0 ([#1146](https://github.com/cloudflare/cloudflare-go/issues/1146)) + ## 0.56.0 (December 5th, 2022) BREAKING CHANGES: From 432ff823340ed05cd9060b871aeb230de507b538 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Thu, 15 Dec 2022 10:50:49 -0500 Subject: [PATCH 027/370] Support for Managed Networks --- devices_managed_networks.go | 127 +++++++++++++++++++++ devices_managed_networks_test.go | 188 +++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 devices_managed_networks.go create mode 100644 devices_managed_networks_test.go diff --git a/devices_managed_networks.go b/devices_managed_networks.go new file mode 100644 index 0000000000..c8f065ccd0 --- /dev/null +++ b/devices_managed_networks.go @@ -0,0 +1,127 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +type Config struct { + TlsSockAddr string `json:"tls_sockaddr,omitempty"` + Sha256 string `json:"sha256,omitempty"` +} + +type DeviceManagedNetworks struct { + NetworkID string `json:"network_id,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Config *Config `json:"config"` +} + +type DeviceManagedNetworksResponse struct { + Response + Result DeviceManagedNetworks `json:"result"` +} + +type DeviceManagedNetworksListResponse struct { + Response + Result []DeviceManagedNetworks `json:"result"` +} + +// ListTeamsDevice returns all devices for a given account. +// +// API reference : https://api.cloudflare.com/#device-managed-networks-list-device-managed-networks +func (api *API) ListManagedNetworks(ctx context.Context, accountID string) ([]DeviceManagedNetworks, error) { + uri := fmt.Sprintf("/%s/%s/devices/networks", AccountRouteRoot, accountID) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []DeviceManagedNetworks{}, err + } + + var response DeviceManagedNetworksListResponse + err = json.Unmarshal(res, &response) + if err != nil { + return []DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// CreateDeviceManagedNetwork creates a new Device Managed Network. +// +// API reference: https://api.cloudflare.com/#device-managed-networks-create-device-managed-network +func (api *API) CreateDeviceManagedNetwork(ctx context.Context, accountID string, req DeviceManagedNetworks) (DeviceManagedNetworks, error) { + uri := fmt.Sprintf("/%s/%s/devices/networks", AccountRouteRoot, accountID) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, req) + if err != nil { + return DeviceManagedNetworks{}, err + } + + var deviceManagedNetworksResponse DeviceManagedNetworksResponse + if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { + return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return deviceManagedNetworksResponse.Result, err +} + +// UpdateDeviceManagedNetwork Update a Device Managed Network. +// +// API reference: https://api.cloudflare.com/#device-managed-networks-update-device-managed-network +func (api *API) UpdateDeviceManagedNetwork(ctx context.Context, accountID string, networkID string, req DeviceManagedNetworks) (DeviceManagedNetworks, error) { + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, req) + if err != nil { + return DeviceManagedNetworks{}, err + } + + var deviceManagedNetworksResponse DeviceManagedNetworksResponse + + if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { + return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return deviceManagedNetworksResponse.Result, err +} + +// GetDeviceManagedNetwork gets a single Managed Network. +// +// API reference: https://api.cloudflare.com/#device-managed-networks-device-managed-network-details +func (api *API) GetDeviceManagedNetwork(ctx context.Context, accountID string, networkID string) (DeviceManagedNetworks, error) { + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) + + deviceManagedNetworksResponse := DeviceManagedNetworksResponse{} + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return DeviceManagedNetworks{}, err + } + + if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { + return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return deviceManagedNetworksResponse.Result, err +} + +// DeleteManagedNetworks deletes a Device Managed Network. Returns the remaining device managed networks for the account. +// +// API reference: https://api.cloudflare.com/#device-managed-networks-delete-device-managed-network +func (api *API) DeleteManagedNetworks(ctx context.Context, accountID, networkID string) ([]DeviceManagedNetworks, error) { + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) + + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return []DeviceManagedNetworks{}, err + } + + var response DeviceManagedNetworksListResponse + if err := json.Unmarshal(res, &response); err != nil { + return []DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, err +} diff --git a/devices_managed_networks_test.go b/devices_managed_networks_test.go new file mode 100644 index 0000000000..0fc99cc4d8 --- /dev/null +++ b/devices_managed_networks_test.go @@ -0,0 +1,188 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetDeviceManagedNetworks(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": [ + { + "network_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "type": "tls", + "name": "managed-network-1", + "config": { + "tls_sockaddr": "foobar:1234", + "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" + } + } + ] + }`) + } + + want := []DeviceManagedNetworks{{ + NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + }} + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks", handler) + + actual, err := client.ListManagedNetworks(context.Background(), testAccountID) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeviceManagedNetwork(t *testing.T) { + setup() + defer teardown() + + id := "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" + 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": + { + "network_id": "%s", + "type": "tls", + "name": "managed-network-1", + "config": { + "tls_sockaddr": "foobar:1234", + "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" + } + } + }`, id) + } + + want := DeviceManagedNetworks{ + NetworkID: id, + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+id, handler) + + actual, err := client.GetDeviceManagedNetwork(context.Background(), testAccountID, id) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestCreateDeviceManagedNetwork(t *testing.T) { + setup() + defer teardown() + + id := "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": + { + "network_id": "%s", + "type": "tls", + "name": "managed-network-1", + "config": { + "tls_sockaddr": "foobar:1234", + "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" + } + } + }`, id) + } + + want := DeviceManagedNetworks{ + NetworkID: id, + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks", handler) + + actual, err := client.CreateDeviceManagedNetwork(context.Background(), testAccountID, want) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteDeviceManagedNetwork(t *testing.T) { + setup() + defer teardown() + + id := "480f4f69-1a28-4fdd-9240-1ed29f0ac1db" + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "network_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "type": "tls", + "name": "managed-network-1", + "config": { + "tls_sockaddr": "foobar:1234", + "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" + } + } + ] + }`) + } + + want := []DeviceManagedNetworks{{ + NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + }} + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) + + actual, err := client.DeleteManagedNetworks(context.Background(), testAccountID, id) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } + +} From 24cd9dcedbb8f4c74b7d76b62473dcae28cfa267 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Thu, 15 Dec 2022 10:56:49 -0500 Subject: [PATCH 028/370] adding changelog for 1148 --- .changelog/1148.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1148.txt diff --git a/.changelog/1148.txt b/.changelog/1148.txt new file mode 100644 index 0000000000..55149599e0 --- /dev/null +++ b/.changelog/1148.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +managed_networks: add CRUD functionality for managednetworks +``` \ No newline at end of file From 42eb64632fa5c60ffe33048526045bb48a40259f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Dec 2022 12:10:21 +1100 Subject: [PATCH 029/370] convert to newer method conventions --- devices_managed_networks.go | 107 ++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/devices_managed_networks.go b/devices_managed_networks.go index c8f065ccd0..1f6129a6a9 100644 --- a/devices_managed_networks.go +++ b/devices_managed_networks.go @@ -12,38 +12,59 @@ type Config struct { Sha256 string `json:"sha256,omitempty"` } -type DeviceManagedNetworks struct { +type DeviceManagedNetwork struct { NetworkID string `json:"network_id,omitempty"` Type string `json:"type"` Name string `json:"name"` Config *Config `json:"config"` } -type DeviceManagedNetworksResponse struct { +type DeviceManagedNetworkResponse struct { Response - Result DeviceManagedNetworks `json:"result"` + Result DeviceManagedNetwork `json:"result"` } -type DeviceManagedNetworksListResponse struct { +type DeviceManagedNetworkListResponse struct { Response - Result []DeviceManagedNetworks `json:"result"` + Result []DeviceManagedNetwork `json:"result"` } -// ListTeamsDevice returns all devices for a given account. +type ListDeviceManagedNetworksParams struct{} + +type CreateDeviceManagedNetworkParams struct { + NetworkID string `json:"network_id,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Config *Config `json:"config"` +} + +type UpdateDeviceManagedNetworkParams struct { + NetworkID string `json:"network_id,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Config *Config `json:"config"` +} + +// ListDeviceManagedNetwork returns all Device Managed Networks for a given +// account. // // API reference : https://api.cloudflare.com/#device-managed-networks-list-device-managed-networks -func (api *API) ListManagedNetworks(ctx context.Context, accountID string) ([]DeviceManagedNetworks, error) { - uri := fmt.Sprintf("/%s/%s/devices/networks", AccountRouteRoot, accountID) +func (api *API) ListDeviceManagedNetworks(ctx context.Context, rc *ResourceContainer, params ListDeviceManagedNetworksParams) ([]DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return []DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/networks", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []DeviceManagedNetworks{}, err + return []DeviceManagedNetwork{}, err } - var response DeviceManagedNetworksListResponse + var response DeviceManagedNetworkListResponse err = json.Unmarshal(res, &response) if err != nil { - return []DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return response.Result, nil @@ -52,17 +73,21 @@ func (api *API) ListManagedNetworks(ctx context.Context, accountID string) ([]De // CreateDeviceManagedNetwork creates a new Device Managed Network. // // API reference: https://api.cloudflare.com/#device-managed-networks-create-device-managed-network -func (api *API) CreateDeviceManagedNetwork(ctx context.Context, accountID string, req DeviceManagedNetworks) (DeviceManagedNetworks, error) { - uri := fmt.Sprintf("/%s/%s/devices/networks", AccountRouteRoot, accountID) +func (api *API) CreateDeviceManagedNetwork(ctx context.Context, rc *ResourceContainer, params CreateDeviceManagedNetworkParams) (DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/networks", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, req) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { - return DeviceManagedNetworks{}, err + return DeviceManagedNetwork{}, err } - var deviceManagedNetworksResponse DeviceManagedNetworksResponse + var deviceManagedNetworksResponse DeviceManagedNetworkResponse if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { - return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return deviceManagedNetworksResponse.Result, err @@ -71,56 +96,68 @@ func (api *API) CreateDeviceManagedNetwork(ctx context.Context, accountID string // UpdateDeviceManagedNetwork Update a Device Managed Network. // // API reference: https://api.cloudflare.com/#device-managed-networks-update-device-managed-network -func (api *API) UpdateDeviceManagedNetwork(ctx context.Context, accountID string, networkID string, req DeviceManagedNetworks) (DeviceManagedNetworks, error) { - uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) +func (api *API) UpdateDeviceManagedNetwork(ctx context.Context, rc *ResourceContainer, params UpdateDeviceManagedNetworkParams) (DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, req) + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", rc.Level, rc.Identifier, params.NetworkID) + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { - return DeviceManagedNetworks{}, err + return DeviceManagedNetwork{}, err } - var deviceManagedNetworksResponse DeviceManagedNetworksResponse + var deviceManagedNetworksResponse DeviceManagedNetworkResponse if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { - return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return deviceManagedNetworksResponse.Result, err } -// GetDeviceManagedNetwork gets a single Managed Network. +// GetDeviceManagedNetwork gets a single Device Managed Network. // // API reference: https://api.cloudflare.com/#device-managed-networks-device-managed-network-details -func (api *API) GetDeviceManagedNetwork(ctx context.Context, accountID string, networkID string) (DeviceManagedNetworks, error) { - uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) +func (api *API) GetDeviceManagedNetwork(ctx context.Context, rc *ResourceContainer, networkID string) (DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", rc.Level, rc.Identifier, networkID) - deviceManagedNetworksResponse := DeviceManagedNetworksResponse{} + deviceManagedNetworksResponse := DeviceManagedNetworkResponse{} res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return DeviceManagedNetworks{}, err + return DeviceManagedNetwork{}, err } if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { - return DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return deviceManagedNetworksResponse.Result, err } -// DeleteManagedNetworks deletes a Device Managed Network. Returns the remaining device managed networks for the account. +// DeleteManagedNetworks deletes a Device Managed Network. // // API reference: https://api.cloudflare.com/#device-managed-networks-delete-device-managed-network -func (api *API) DeleteManagedNetworks(ctx context.Context, accountID, networkID string) ([]DeviceManagedNetworks, error) { - uri := fmt.Sprintf("/%s/%s/devices/networks/%s", AccountRouteRoot, accountID, networkID) +func (api *API) DeleteManagedNetworks(ctx context.Context, rc *ResourceContainer, networkID string) ([]DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return []DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/networks/%s", rc.Level, rc.Identifier, networkID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return []DeviceManagedNetworks{}, err + return []DeviceManagedNetwork{}, err } - var response DeviceManagedNetworksListResponse + var response DeviceManagedNetworkListResponse if err := json.Unmarshal(res, &response); err != nil { - return []DeviceManagedNetworks{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return response.Result, err From 8f4c0301b1b4e823c0b6c7c89835aed7e8d2173b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Dec 2022 12:10:54 +1100 Subject: [PATCH 030/370] update tests to match method convention updates --- devices_managed_networks_test.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/devices_managed_networks_test.go b/devices_managed_networks_test.go index 0fc99cc4d8..fed5783738 100644 --- a/devices_managed_networks_test.go +++ b/devices_managed_networks_test.go @@ -34,7 +34,7 @@ func TestGetDeviceManagedNetworks(t *testing.T) { }`) } - want := []DeviceManagedNetworks{{ + want := []DeviceManagedNetwork{{ NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Type: "tls", Name: "managed-network-1", @@ -46,7 +46,7 @@ func TestGetDeviceManagedNetworks(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks", handler) - actual, err := client.ListManagedNetworks(context.Background(), testAccountID) + actual, err := client.ListDeviceManagedNetworks(context.Background(), AccountIdentifier(testAccountID), ListDeviceManagedNetworksParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -65,7 +65,7 @@ func TestDeviceManagedNetwork(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": + "result": { "network_id": "%s", "type": "tls", @@ -78,7 +78,7 @@ func TestDeviceManagedNetwork(t *testing.T) { }`, id) } - want := DeviceManagedNetworks{ + want := DeviceManagedNetwork{ NetworkID: id, Type: "tls", Name: "managed-network-1", @@ -90,7 +90,7 @@ func TestDeviceManagedNetwork(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+id, handler) - actual, err := client.GetDeviceManagedNetwork(context.Background(), testAccountID, id) + actual, err := client.GetDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), id) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -109,7 +109,7 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": + "result": { "network_id": "%s", "type": "tls", @@ -122,7 +122,7 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { }`, id) } - want := DeviceManagedNetworks{ + want := DeviceManagedNetwork{ NetworkID: id, Type: "tls", Name: "managed-network-1", @@ -134,7 +134,15 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks", handler) - actual, err := client.CreateDeviceManagedNetwork(context.Background(), testAccountID, want) + actual, err := client.CreateDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), CreateDeviceManagedNetworkParams{ + NetworkID: id, + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -167,7 +175,7 @@ func TestDeleteDeviceManagedNetwork(t *testing.T) { }`) } - want := []DeviceManagedNetworks{{ + want := []DeviceManagedNetwork{{ NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Type: "tls", Name: "managed-network-1", @@ -179,7 +187,7 @@ func TestDeleteDeviceManagedNetwork(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.DeleteManagedNetworks(context.Background(), testAccountID, id) + actual, err := client.DeleteManagedNetworks(context.Background(), AccountIdentifier(testAccountID), id) if assert.NoError(t, err) { assert.Equal(t, want, actual) From db74b8da2924263eaf567428b98ee056bc03d985 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Dec 2022 12:18:01 +1100 Subject: [PATCH 031/370] lint fixes --- devices_managed_networks_test.go | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/devices_managed_networks_test.go b/devices_managed_networks_test.go index fed5783738..7f2f4bb6b7 100644 --- a/devices_managed_networks_test.go +++ b/devices_managed_networks_test.go @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" ) +const testNetworkID = "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" + func TestGetDeviceManagedNetworks(t *testing.T) { setup() defer teardown() @@ -35,7 +37,7 @@ func TestGetDeviceManagedNetworks(t *testing.T) { } want := []DeviceManagedNetwork{{ - NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + NetworkID: testNetworkID, Type: "tls", Name: "managed-network-1", Config: &Config{ @@ -57,7 +59,6 @@ func TestDeviceManagedNetwork(t *testing.T) { setup() defer teardown() - id := "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" 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") @@ -75,11 +76,11 @@ func TestDeviceManagedNetwork(t *testing.T) { "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" } } - }`, id) + }`, testNetworkID) } want := DeviceManagedNetwork{ - NetworkID: id, + NetworkID: testNetworkID, Type: "tls", Name: "managed-network-1", Config: &Config{ @@ -88,9 +89,9 @@ func TestDeviceManagedNetwork(t *testing.T) { }, } - mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+id, handler) + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+testNetworkID, handler) - actual, err := client.GetDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), id) + actual, err := client.GetDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), testNetworkID) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -101,7 +102,6 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { setup() defer teardown() - id := "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") @@ -119,11 +119,11 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" } } - }`, id) + }`, testNetworkID) } want := DeviceManagedNetwork{ - NetworkID: id, + NetworkID: testNetworkID, Type: "tls", Name: "managed-network-1", Config: &Config{ @@ -135,7 +135,7 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks", handler) actual, err := client.CreateDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), CreateDeviceManagedNetworkParams{ - NetworkID: id, + NetworkID: testNetworkID, Type: "tls", Name: "managed-network-1", Config: &Config{ @@ -153,7 +153,6 @@ func TestDeleteDeviceManagedNetwork(t *testing.T) { setup() defer teardown() - id := "480f4f69-1a28-4fdd-9240-1ed29f0ac1db" handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/json") @@ -176,7 +175,7 @@ func TestDeleteDeviceManagedNetwork(t *testing.T) { } want := []DeviceManagedNetwork{{ - NetworkID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + NetworkID: testNetworkID, Type: "tls", Name: "managed-network-1", Config: &Config{ @@ -185,12 +184,11 @@ func TestDeleteDeviceManagedNetwork(t *testing.T) { }, }} - mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+testNetworkID, handler) - actual, err := client.DeleteManagedNetworks(context.Background(), AccountIdentifier(testAccountID), id) + actual, err := client.DeleteManagedNetworks(context.Background(), AccountIdentifier(testAccountID), testNetworkID) if assert.NoError(t, err) { assert.Equal(t, want, actual) } - } From e3f657419c400b2a6288c2976b1ad41679d56d4d Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 19 Dec 2022 01:25:04 +0000 Subject: [PATCH 032/370] Update CHANGELOG.md for #1148 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59e388e900..1deaa4068b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ NOTES: * workers: all worker methods have been split into product ownership(-ish) files ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) * workers: all worker methods now require an explicit `ResourceContainer` for endpoints instead of relying on the globally defined `api.AccountID` ([#1137](https://github.com/cloudflare/cloudflare-go/issues/1137)) +ENHANCEMENTS: + +* managed_networks: add CRUD functionality for managednetworks ([#1148](https://github.com/cloudflare/cloudflare-go/issues/1148)) + DEPENDENCIES: * deps: bumps goreleaser/goreleaser-action from 3.2.0 to 4.1.0 ([#1146](https://github.com/cloudflare/cloudflare-go/issues/1146)) From 02e5fb196c4f2a4d1ae65a8da93e7ea8734744e2 Mon Sep 17 00:00:00 2001 From: vasil Date: Tue, 20 Dec 2022 20:43:30 -0600 Subject: [PATCH 033/370] add support for mtls certificates --- mtls_certificates.go | 135 ++++++++++++++++++++++ mtls_certificates_test.go | 236 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 mtls_certificates.go create mode 100644 mtls_certificates_test.go diff --git a/mtls_certificates.go b/mtls_certificates.go new file mode 100644 index 0000000000..fb264c6ebc --- /dev/null +++ b/mtls_certificates.go @@ -0,0 +1,135 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +// MTLSAssociationDetails represents the metadata for an existing association between a user-uploaded mTLS certificate and a Cloudflare service. +type MTLSAssociationDetails struct { + Service string `json:"service"` + Status string `json:"status"` +} + +// MTLSAssociationResponse represents the response from the retrieval endpoint for mTLS certificate associations. +type MTLSAssociationResponse struct { + Response + Result []MTLSAssociationDetails `json:"result"` +} + +// MTLSCertificateDetails represents the metadata for a user-uploaded mTLS certificate. +type MTLSCertificateDetails struct { + ID string `json:"id"` + Name string `json:"name"` + Issuer string `json:"issuer"` + Signature string `json:"signature"` + SerialNumber string `json:"serial_number"` + Certificates string `json:"certificates"` + CA bool `json:"ca"` + UploadedOn time.Time `json:"uploaded_on"` + UpdatedAt time.Time `json:"updated_at"` + ExpiresOn time.Time `json:"expires_on"` +} + +// MTLSCertificateResponse represents the response from endpoints relating to retrieving, creating, and deleting an mTLS certificate. +type MTLSCertificateResponse struct { + Response + Result MTLSCertificateDetails `json:"result"` +} + +// MTLSCertificatesResponse represents the response from the mTLS certificate list endpoint. +type MTLSCertificatesResponse struct { + Response + Result []MTLSCertificateDetails `json:"result"` +} + +// MTLSCertificateParams represents the data related to the mTLS certificate being uploaded. Name is an optional field. +type MTLSCertificateParams struct { + Name string `json:"name"` + Certificates string `json:"certificates"` + PrivateKey string `json:"private_key"` + CA bool `json:"ca"` +} + +// ListMTLSCertificates returns a list of all user-uploaded mTLS certificates. +// +// API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificates +func (api *API) ListMTLSCertificates(ctx context.Context, accountID string) ([]MTLSCertificateDetails, error) { + uri := fmt.Sprintf("/accounts/%s/mtls_certificates", accountID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []MTLSCertificateDetails{}, err + } + var r MTLSCertificatesResponse + if err := json.Unmarshal(res, &r); err != nil { + return []MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// GetMTLSCertificateDetails returns the metadata associated with a user-uploaded mTLS certificate. +// +// API reference: https://api.cloudflare.com/#mtls-certificate-management-get-mtls-certificate +func (api *API) GetMTLSCertificateDetails(ctx context.Context, accountID, certificateID string) (MTLSCertificateDetails, error) { + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", accountID, certificateID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return MTLSCertificateDetails{}, err + } + var r MTLSCertificateResponse + if err := json.Unmarshal(res, &r); err != nil { + return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// ListMTLSCertificateAssociations returns a list of all existing associations between the mTLS certificate and Cloudflare services. +// +// API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificate-associations +func (api *API) ListMTLSCertificateAssociations(ctx context.Context, accountID, certificateID string) ([]MTLSAssociationDetails, error) { + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s/associations", accountID, certificateID) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []MTLSAssociationDetails{}, err + } + var r MTLSAssociationResponse + if err := json.Unmarshal(res, &r); err != nil { + return []MTLSAssociationDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// UploadMTLSCertificate will upload the provided certificate for use with mTLS enabled Cloudflare services. +// +// API reference: https://api.cloudflare.com/#mtls-certificate-management-upload-mtls-certificate +func (api *API) UploadMTLSCertificate(ctx context.Context, accountID string, params MTLSCertificateParams) (MTLSCertificateDetails, error) { + uri := fmt.Sprintf("/accounts/%s/mtls_certificates", accountID) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return MTLSCertificateDetails{}, err + } + var r MTLSCertificateResponse + if err := json.Unmarshal(res, &r); err != nil { + return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} + +// DeleteMTLSCertificate will delete the specified mTLS certificate. +// +// API reference: https://api.cloudflare.com/#mtls-certificate-management-delete-mtls-certificate +func (api *API) DeleteMTLSCertificate(ctx context.Context, accountID, certificateID string) (MTLSCertificateDetails, error) { + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", accountID, certificateID) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return MTLSCertificateDetails{}, err + } + var r MTLSCertificateResponse + if err := json.Unmarshal(res, &r); err != nil { + return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return r.Result, nil +} diff --git a/mtls_certificates_test.go b/mtls_certificates_test.go new file mode 100644 index 0000000000..390e37cb0b --- /dev/null +++ b/mtls_certificates_test.go @@ -0,0 +1,236 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestGetMTLSCertificate(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + "name": "example_ca_cert_5", + "issuer": "O=Example Inc.,L=California,ST=San Francisco,C=US", + "signature": "SHA256WithRSA", + "serial_number": "235217144297995885180570755458463043449861756659", + "certificates": "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + "ca": true, + "uploaded_on": "2022-11-22T17:32:30.467938Z", + "expires_on": "2122-10-29T16:59:47Z" + } + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", handler) + expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") + uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") + want := MTLSCertificateDetails{ + ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + Name: "example_ca_cert_5", + Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", + Signature: "SHA256WithRSA", + SerialNumber: "235217144297995885180570755458463043449861756659", + Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + CA: true, + UploadedOn: uploadedOn, + ExpiresOn: expiresOn, + } + + actual, err := client.GetMTLSCertificateDetails(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListMTLSCertificates(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + "name": "example_ca_cert_5", + "issuer": "O=Example Inc.,L=California,ST=San Francisco,C=US", + "signature": "SHA256WithRSA", + "serial_number": "235217144297995885180570755458463043449861756659", + "certificates": "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + "ca": true, + "uploaded_on": "2022-11-22T17:32:30.467938Z", + "expires_on": "2122-10-29T16:59:47Z" + } + ] + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates", handler) + expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") + uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") + want := []MTLSCertificateDetails{ + { + ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + Name: "example_ca_cert_5", + Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", + Signature: "SHA256WithRSA", + SerialNumber: "235217144297995885180570755458463043449861756659", + Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + CA: true, + UploadedOn: uploadedOn, + ExpiresOn: expiresOn, + }, + } + + actual, err := client.ListMTLSCertificates(context.Background(), "01a7362d577a6c3019a474fd6f485823") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListCertificateAssociations(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "service": "gateway", + "status": "pending_deployment" + } + ] + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60/associations", handler) + want := []MTLSAssociationDetails{ + { + Service: "gateway", + Status: "pending_deployment", + }, + } + + actual, err := client.ListMTLSCertificateAssociations(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUploadMTLSCertificate(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + "name": "example_ca_cert_5", + "issuer": "O=Example Inc.,L=California,ST=San Francisco,C=US", + "signature": "SHA256WithRSA", + "serial_number": "235217144297995885180570755458463043449861756659", + "certificates": "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + "ca": true, + "uploaded_on": "2022-11-22T17:32:30.467938Z", + "updated_at": "2022-11-22T17:32:30.467938Z", + "expires_on": "2122-10-29T16:59:47Z" + } + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates", handler) + expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") + uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") + want := MTLSCertificateDetails{ + ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + Name: "example_ca_cert_5", + Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", + Signature: "SHA256WithRSA", + SerialNumber: "235217144297995885180570755458463043449861756659", + Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + CA: true, + UploadedOn: uploadedOn, + UpdatedAt: uploadedOn, + ExpiresOn: expiresOn, + } + + cert := MTLSCertificateParams{ + Name: "example_ca_cert_5", + Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + PrivateKey: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEXDkcICRU3XBv9hiiPnBWIjgTQyowmVFxDr11mONgZB/cMYjE/OvQjvnpwNcOaSK16MOpAjNbELKRx2lZiVJaLRDCccqCxXwP/CrdRChcqGzo7mbNksMlcidrErb0LlEBKLFC2QjRmRKqB+YOs4TD8WsZu2S667A2fZmjRlaqOxFi1h62ee0P+TLU628UC/nl41JifSt5Evt7hMDHakemdwZblNYr2p6T3NQjdhjYXTtP4UmOGJBhJ7i7Kicg3d3CIgdTMbggSeGWqjndr4ldVnD96FN3cVT5uDFsn2CJXTFgdeBWoUnMS4VnUZzPWGf4vSBXC8qV7Ls+w46yT7T1AgMBAAECggEAQZnp/oqCeNPOR6l5S2L+1tfx0gWjZ78hJVteUpZ0iHSK7F6kKeOxyOird7vUXV0kmo+cJq+0hp0Ke4eam640FCpwKfYoSQ4/R3vgujGWJnaihCN5tv5sMet0XeJPuz5qE7ALoKCvwI6aXLHs20aAeZIDTQJ9QbGSGnJVzOWn+JDTidIgZpN57RpXfSAwnJPTQK/PN8i5z108hsaDOdEgGmxYZ7kYqMqzX20KXmth58LDfPixs5JGtS60iiKC/wOcGzkB2/AdTSojR76oEU77cANP/3zO25NG//whUdYlW0t0d7PgXxIeJe+xgYnamDQJx3qonVyt4H77ha0ObRAj9QKBgQDicZr+VTwFMnELP3a+FXGnjehRiuS1i7MXGKxNweCD+dFlML0FplSQS8Ro2n+d8lu8BBXGx0qm6VXu8Rhn7TAUL6q+PCgfarzxfIhacb/TZCqfieIHsMlVBfhV5HCXnk+kis0tuC/PRArcWTwDHJUJXkBhvkUsNswvQzavDPI7KwKBgQDd/WgLkj7A3X5fgIHZH/GbDSBiXwzKb+rF4ZCT2XFgG/OAW7vapfcX/w+v+5lBLyrocmOAS3PGGAhM5T3HLnUCQfnK4qgps1Lqibkc9Tmnsn60LanUjuUMsYv/zSw70tozbzhJ0pioEpWfRxRZBztO2Rr8Ntm7h6Fk701EXGNAXwKBgQCD1xsjy2J3sCerIdcz0u5qXLAPkeuZW+34m4/ucdwTWwc0gEz9lhsULFj9p4G351zLuiEnq+7mAWLcDJlmIO3mQt6JhiLiL9Y0T4pgBmxmWqKKYtAsJB0EmMY+1BNN44mBRqMxZFTJu1cLdhT/xstrOeoIPqytknYNanfTMZlzIwKBgHrLXe5oq0XMP8dcMneEcAUwsaU4pr6kQd3L9EmUkl5zl7J9C+DaxWAEuwzBw/iGutlxzRB+rD/7szu14wJ29EqXbDGKRzMp+se5/yfBjm7xEZ1hVPw7PwBShfqt57X/4Ktq7lwHnmH6RcGhc+P7WBc5iO/S94YAdIp8xOT3pf9JAoGAE0QkqJUY+5Mgr+fBO0VNV72ZoPveGpW+De59uhKAOnu1zljQCUtk59m6+DXfm0tNYKtawa5n8iN71Zh+s62xXSt3pYi1Y5CCCmv8Y4BhwIcPwXKk3zEvLgSHVTpC0bayA9aSO4bbZgVXa5w+Z0w/vvfp9DWo1IS3EnQRrz6WMYA=\n-----END PRIVATE KEY-----", + CA: true, + } + actual, err := client.UploadMTLSCertificate(context.Background(), "01a7362d577a6c3019a474fd6f485823", cert) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteMTLSCertificate(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + "name": "example_ca_cert_5", + "issuer": "O=Example Inc.,L=California,ST=San Francisco,C=US", + "signature": "SHA256WithRSA", + "serial_number": "235217144297995885180570755458463043449861756659", + "certificates": "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + "ca": true, + "uploaded_on": "2022-11-22T17:32:30.467938Z", + "expires_on": "2122-10-29T16:59:47Z" + } + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", handler) + expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") + uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") + want := MTLSCertificateDetails{ + ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + Name: "example_ca_cert_5", + Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", + Signature: "SHA256WithRSA", + SerialNumber: "235217144297995885180570755458463043449861756659", + Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", + CA: true, + UploadedOn: uploadedOn, + ExpiresOn: expiresOn, + } + + actual, err := client.DeleteMTLSCertificate(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From 54b0448e0d939a676e855afe9b0c1813f519be45 Mon Sep 17 00:00:00 2001 From: vasil Date: Wed, 21 Dec 2022 13:24:51 -0600 Subject: [PATCH 034/370] add mTLS certificate store to list of supported features in README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 311bea03d7..988d1a3cac 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ The current feature list includes: - [x] [Load Balancing](https://blog.cloudflare.com/introducing-load-balancing-intelligent-failover-with-cloudflare/) - [x] [Logpush Jobs](https://developers.cloudflare.com/logs/logpush/) - [x] Magic Transit / Magic WAN +- [x] mTLS Certificate Store - [x] Notifications - [ ] Organization Administration - [x] [Origin CA](https://blog.cloudflare.com/universal-ssl-encryption-all-the-way-to-the-origin-for-free/) From 75edb988e7beebf2652126b26045e705c175e848 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 22 Dec 2022 07:19:24 +1100 Subject: [PATCH 035/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1deaa4068b..07db3e3ff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.57.0 (Unreleased) +## 0.58.0 (Unreleased) + +## 0.57.0 (December 22nd, 2022) BREAKING CHANGES: From c0d6c00670bd1d37ddc65ff0073d4283e83284ca Mon Sep 17 00:00:00 2001 From: Jacob White Date: Wed, 21 Dec 2022 22:50:28 -0500 Subject: [PATCH 036/370] Add tags and comments to DNS records --- cmd/flarectl/dns.go | 2 +- cmd/flarectl/zone.go | 2 +- dns.go | 100 +++++++++++++++++++++++++++++----- dns_example_test.go | 8 +-- dns_test.go | 126 +++++++++++++++++++++++++++++++++++++++++-- example_test.go | 2 +- 6 files changed, 218 insertions(+), 22 deletions(-) diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index db9653e037..69ec20e32f 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -88,7 +88,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr := cloudflare.DNSRecord{ Name: name + "." + zone, } - records, err := api.DNSRecords(context.Background(), zoneID, rr) + records, _, err := api.DNSRecords(context.Background(), zoneID, rr, cloudflare.DNSListParameters{}) if err != nil { fmt.Fprintln(os.Stderr, "Error fetching DNS records: ", err) return err diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index 5cd2c81a4c..e4c8e29132 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -300,7 +300,7 @@ func zoneRecords(c *cli.Context) error { rr.Content = c.String("content") } var err error - records, err = api.DNSRecords(context.Background(), zoneID, rr) + records, _, err = api.DNSRecords(context.Background(), zoneID, rr, cloudflare.DNSListParameters{}) if err != nil { fmt.Println(err) return err diff --git a/dns.go b/dns.go index affb167efb..1bde15391f 100644 --- a/dns.go +++ b/dns.go @@ -29,6 +29,8 @@ type DNSRecord struct { Proxied *bool `json:"proxied,omitempty"` Proxiable bool `json:"proxiable,omitempty"` Locked bool `json:"locked,omitempty"` + Comment string `json:"comment,omitempty"` + Tags []string `json:"tags,omitempty"` } // DNSRecordResponse represents the response from the DNS endpoint. @@ -38,6 +40,39 @@ type DNSRecordResponse struct { ResultInfo `json:"result_info"` } +type TagQueryParameter string + +const ( + TagQueryPresent TagQueryParameter = "present" + TagQueryAbsent TagQueryParameter = "absent" + TagQueryExact TagQueryParameter = "exact" + TagQueryContains TagQueryParameter = "contains" + TagQueryStartsWith TagQueryParameter = "startswith" + TagQueryEndsWith TagQueryParameter = "endswith" +) + +type TagSearch struct { + Tag string + Query TagQueryParameter +} + +type ListDirection string + +const ( + ListDirectionAsc ListDirection = "asc" + ListDirectionDesc ListDirection = "desc" +) + +type DNSListParameters struct { + TagSearch []TagSearch `url:"-"` + Order string `url:"order,omitempty"` + TagMatch string `url:"tag-match,omitempty"` + Direction ListDirection `url:"direction,omitempty"` + TagQuery string `url:"-"` + Match string `url:"match,omitempty"` + ResultInfo +} + // DNSListResponse represents the response from the list DNS records endpoint. type DNSListResponse struct { Result []DNSRecord `json:"result"` @@ -90,7 +125,7 @@ func (api *API) CreateDNSRecord(ctx context.Context, zoneID string, rr DNSRecord // This takes a DNSRecord to allow filtering of the results returned. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records -func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord) ([]DNSRecord, error) { +func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord, params DNSListParameters) ([]DNSRecord, *ResultInfo, error) { // Construct a query string v := url.Values{} // Using default per_page value as specified by the API @@ -104,30 +139,71 @@ func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord) ([] v.Set("content", rr.Content) } + if rr.Proxied != nil { + v.Set("proxied", strconv.FormatBool(*rr.Proxied)) + } + + if len(params.TagSearch) > 0 { + for _, tagParam := range params.TagSearch { + tagText := fmt.Sprintf("tag.%s", tagParam.Tag) + if tagParam.Query != "" { + tagText += fmt.Sprintf(".%s", tagParam.Query) + } + v.Add("tag", tagText) + } + } + + if params.Order != "" { + v.Set("order", params.Order) + } + + if params.TagMatch != "" { + v.Set("tag-match", params.TagMatch) + } + + if params.Direction != "" { + v.Set("direction", string(params.Direction)) + } + + if params.Match != "" { + v.Set("match", params.Match) + } + + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } + + if params.PerPage < 1 { + params.PerPage = 50 + } + + if params.Page < 1 { + params.Page = 1 + } + var records []DNSRecord - page := 1 + var listResponse DNSListResponse // Loop over makeRequest until what we've fetched all records for { - v.Set("page", strconv.Itoa(page)) + v.Set("page", strconv.Itoa(params.Page)) uri := fmt.Sprintf("/zones/%s/dns_records?%s", zoneID, v.Encode()) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []DNSRecord{}, err + return []DNSRecord{}, &ResultInfo{}, err } - var r DNSListResponse - err = json.Unmarshal(res, &r) + err = json.Unmarshal(res, &listResponse) if err != nil { - return []DNSRecord{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []DNSRecord{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - records = append(records, r.Result...) - if r.ResultInfo.Page >= r.ResultInfo.TotalPages { + records = append(records, listResponse.Result...) + params.ResultInfo = listResponse.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { break } - // Loop around and fetch the next page - page++ } - return records, nil + return records, &listResponse.ResultInfo, nil } // DNSRecord returns a single DNS record for the given zone & record diff --git a/dns_example_test.go b/dns_example_test.go index 8f0a5f33c7..2af07b87bb 100644 --- a/dns_example_test.go +++ b/dns_example_test.go @@ -20,7 +20,7 @@ func ExampleAPI_DNSRecords_all() { } // Fetch all records for a zone - recs, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}) + recs, _, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -43,7 +43,7 @@ func ExampleAPI_DNSRecords_filterByContent() { // Fetch only records whose content is 198.51.100.1 localhost := cloudflare.DNSRecord{Content: "198.51.100.1"} - recs, err := api.DNSRecords(context.Background(), zoneID, localhost) + recs, _, err := api.DNSRecords(context.Background(), zoneID, localhost, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -67,7 +67,7 @@ func ExampleAPI_DNSRecords_filterByName() { // Fetch records of any type with name "foo.example.com" // The name must be fully-qualified foo := cloudflare.DNSRecord{Name: "foo.example.com"} - recs, err := api.DNSRecords(context.Background(), zoneID, foo) + recs, _, err := api.DNSRecords(context.Background(), zoneID, foo, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -90,7 +90,7 @@ func ExampleAPI_DNSRecords_filterByType() { // Fetch only AAAA type records aaaa := cloudflare.DNSRecord{Type: "AAAA"} - recs, err := api.DNSRecords(context.Background(), zoneID, aaaa) + recs, _, err := api.DNSRecords(context.Background(), zoneID, aaaa, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } diff --git a/dns_test.go b/dns_test.go index b2cc16fdb0..093977f35e 100644 --- a/dns_test.go +++ b/dns_test.go @@ -200,8 +200,10 @@ func TestDNSRecords(t *testing.T) { } ], "result_info": { + "count": 1, "page": 1, - "total_pages": 1 + "per_page": 20, + "total_count": 2000 } }`) } @@ -231,12 +233,126 @@ func TestDNSRecords(t *testing.T) { }, }} - actual, err := client.DNSRecords(context.Background(), testZoneID, unicodeInput) + actual, _, err := client.DNSRecords(context.Background(), testZoneID, unicodeInput, DNSListParameters{}) require.NoError(t, err) assert.Equal(t, want, actual) } +func TestDNSRecordsSearch(t *testing.T) { + setup() + defer teardown() + + unicodeInput := DNSRecord{ + Name: "example.com", + Type: "A", + Content: "198.51.100.4", + } + asciiInput := DNSRecord{ + Name: "example.com", + Type: "A", + Content: "198.51.100.4", + } + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + assert.Equal(t, asciiInput.Name, r.URL.Query().Get("name")) + assert.Equal(t, asciiInput.Type, r.URL.Query().Get("type")) + assert.Equal(t, asciiInput.Content, r.URL.Query().Get("content")) + assert.Equal(t, "all", r.URL.Query().Get("match")) + assert.Equal(t, "any", r.URL.Query().Get("tag-match")) + assert.Equal(t, "1", r.URL.Query().Get("page")) + assert.Equal(t, "type", r.URL.Query().Get("order")) + assert.Equal(t, "asc", r.URL.Query().Get("direction")) + fmt.Println(r.URL.Query()["tag"]) + tags := r.URL.Query()["tag"] + assert.Equal(t, 2, len(tags)) + assert.Equal(t, "tag.tag1", tags[0]) + assert.Equal(t, "tag.tag2.contains", tags[1]) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "type": "A", + "name": "example.com", + "content": "198.51.100.4", + "proxiable": true, + "proxied": false, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": ["tag1", "tag2extended"] + } + ], + "result_info": { + "count": 1, + "page": 1, + "per_page": 20, + "total_count": 2000 + } + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/dns_records", handler) + + proxied := false + createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") + want := []DNSRecord{{ + ID: "372e67954025e0ba6aaa6d586b9e0b59", + Type: "A", + Name: asciiInput.Name, + Content: asciiInput.Content, + Proxiable: true, + Proxied: &proxied, + TTL: 120, + Locked: false, + ZoneID: testZoneID, + ZoneName: "example.com", + CreatedOn: createdOn, + ModifiedOn: modifiedOn, + Data: map[string]interface{}{}, + Meta: map[string]interface{}{ + "auto_added": true, + "source": "primary", + }, + Tags: []string{"tag1", "tag2extended"}, + }} + + actual, resultInfo, err := client.DNSRecords(context.Background(), testZoneID, unicodeInput, DNSListParameters{ + Match: "all", + Order: "type", + Direction: ListDirectionAsc, + TagMatch: "any", + TagSearch: []TagSearch{ + { + Tag: "tag1", + }, + { + Tag: "tag2", + Query: TagQueryContains, + }, + }, + }) + require.NoError(t, err) + assert.Equal(t, 2000, resultInfo.Total) + + assert.Equal(t, want, actual) +} + func TestDNSRecord(t *testing.T) { setup() defer teardown() @@ -266,7 +382,9 @@ func TestDNSRecord(t *testing.T) { "meta": { "auto_added": true, "source": "primary" - } + }, + "comment": "This is a comment", + "tags": ["tag1", "tag2"] } }`) } @@ -295,6 +413,8 @@ func TestDNSRecord(t *testing.T) { "auto_added": true, "source": "primary", }, + Comment: "This is a comment", + Tags: []string{"tag1", "tag2"}, } actual, err := client.DNSRecord(context.Background(), testZoneID, dnsRecordID) diff --git a/example_test.go b/example_test.go index 3320d363f2..ff8c986762 100644 --- a/example_test.go +++ b/example_test.go @@ -28,7 +28,7 @@ func Example() { } // Fetch all DNS records for example.org - records, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}) + records, _, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) if err != nil { fmt.Println(err) return From e6ec95d36f2803d16e95e7dc31ce92d974bd4c20 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Wed, 21 Dec 2022 22:52:02 -0500 Subject: [PATCH 037/370] Add changelog --- .changelog/1151.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changelog/1151.txt diff --git a/.changelog/1151.txt b/.changelog/1151.txt new file mode 100644 index 0000000000..9a333df6e7 --- /dev/null +++ b/.changelog/1151.txt @@ -0,0 +1,6 @@ +```release-note:breaking-change +dns: changes how DNS records are listed +``` +```release-note:enhancement +dns: add support for tags and comments +``` \ No newline at end of file From 465a7f8de145d295e4d0c3c95dda4d47a68fa4f6 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Wed, 21 Dec 2022 23:26:12 -0500 Subject: [PATCH 038/370] Replace method signatures --- .changelog/1151.txt | 4 ++++ cmd/flarectl/dns.go | 12 +++++----- cmd/flarectl/zone.go | 6 ++--- dns.go | 41 +++++++++++++++++++++---------- dns_example_test.go | 10 ++++---- dns_test.go | 57 ++++++++++++++++++++++++++++---------------- example_test.go | 2 +- 7 files changed, 83 insertions(+), 49 deletions(-) diff --git a/.changelog/1151.txt b/.changelog/1151.txt index 9a333df6e7..502952ff37 100644 --- a/.changelog/1151.txt +++ b/.changelog/1151.txt @@ -1,6 +1,10 @@ ```release-note:breaking-change dns: changes how DNS records are listed ``` + ```release-note:enhancement dns: add support for tags and comments +``` +```release-note:breaking-change +dns: method signatures have been updated to align with the upcoming client conventions ``` \ No newline at end of file diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index 69ec20e32f..2d0712a53c 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -50,7 +50,7 @@ func dnsCreate(c *cli.Context) error { Proxied: &proxy, Priority: &priority, } - resp, err := api.CreateDNSRecord(context.Background(), zoneID, record) + resp, err := api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) if err != nil { fmt.Fprintln(os.Stderr, "Error creating DNS record: ", err) return err @@ -88,7 +88,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr := cloudflare.DNSRecord{ Name: name + "." + zone, } - records, _, err := api.DNSRecords(context.Background(), zoneID, rr, cloudflare.DNSListParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.DNSListParameters{}) if err != nil { fmt.Fprintln(os.Stderr, "Error fetching DNS records: ", err) return err @@ -108,7 +108,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr.Proxied = &proxy rr.Priority = &priority - err := api.UpdateDNSRecord(context.Background(), zoneID, r.ID, rr) + err := api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), r.ID, rr) if err != nil { fmt.Println("Error updating DNS record:", err) return err @@ -126,7 +126,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr.Proxied = &proxy rr.Priority = &priority // TODO: Print the response. - resp, err = api.CreateDNSRecord(context.Background(), zoneID, rr) + resp, err = api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) if err != nil { fmt.Println("Error creating DNS record:", err) return err @@ -171,7 +171,7 @@ func dnsUpdate(c *cli.Context) error { Proxied: &proxy, Priority: &priority, } - err = api.UpdateDNSRecord(context.Background(), zoneID, recordID, record) + err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), recordID, record) if err != nil { fmt.Fprintln(os.Stderr, "Error updating DNS record: ", err) return err @@ -194,7 +194,7 @@ func dnsDelete(c *cli.Context) error { return err } - err = api.DeleteDNSRecord(context.Background(), zoneID, recordID) + err = api.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), recordID) if err != nil { fmt.Fprintln(os.Stderr, "Error deleting DNS record: ", err) return err diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index e4c8e29132..b8e21c4eb3 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -279,11 +279,11 @@ func zoneRecords(c *cli.Context) error { return err } - // Create a an empty record for searching for records + // Create an empty record for searching for records rr := cloudflare.DNSRecord{} var records []cloudflare.DNSRecord if c.String("id") != "" { - rec, err := api.DNSRecord(context.Background(), zoneID, c.String("id")) + rec, err := api.GetDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), c.String("id")) if err != nil { fmt.Println(err) return err @@ -300,7 +300,7 @@ func zoneRecords(c *cli.Context) error { rr.Content = c.String("content") } var err error - records, _, err = api.DNSRecords(context.Background(), zoneID, rr, cloudflare.DNSListParameters{}) + records, _, err = api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.DNSListParameters{}) if err != nil { fmt.Println(err) return err diff --git a/dns.go b/dns.go index 1bde15391f..357ec6208b 100644 --- a/dns.go +++ b/dns.go @@ -102,10 +102,13 @@ func toUTS46ASCII(name string) string { // CreateDNSRecord creates a DNS record for the zone identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record -func (api *API) CreateDNSRecord(ctx context.Context, zoneID string, rr DNSRecord) (*DNSRecordResponse, error) { +func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, rr DNSRecord) (*DNSRecordResponse, error) { + if rc.Identifier == "" { + return nil, ErrMissingZoneID + } rr.Name = toUTS46ASCII(rr.Name) - uri := fmt.Sprintf("/zones/%s/dns_records", zoneID) + uri := fmt.Sprintf("/zones/%s/dns_records", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, rr) if err != nil { return nil, err @@ -120,12 +123,15 @@ func (api *API) CreateDNSRecord(ctx context.Context, zoneID string, rr DNSRecord return recordResp, nil } -// DNSRecords returns a slice of DNS records for the given zone identifier. +// ListDNSRecords returns a slice of DNS records for the given zone identifier. // // This takes a DNSRecord to allow filtering of the results returned. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records -func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord, params DNSListParameters) ([]DNSRecord, *ResultInfo, error) { +func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DNSRecord, params DNSListParameters) ([]DNSRecord, *ResultInfo, error) { + if rc.Identifier == "" { + return nil, nil, ErrMissingZoneID + } // Construct a query string v := url.Values{} // Using default per_page value as specified by the API @@ -188,7 +194,7 @@ func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord, par // Loop over makeRequest until what we've fetched all records for { v.Set("page", strconv.Itoa(params.Page)) - uri := fmt.Sprintf("/zones/%s/dns_records?%s", zoneID, v.Encode()) + uri := fmt.Sprintf("/zones/%s/dns_records?%s", rc.Identifier, v.Encode()) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []DNSRecord{}, &ResultInfo{}, err @@ -206,12 +212,15 @@ func (api *API) DNSRecords(ctx context.Context, zoneID string, rr DNSRecord, par return records, &listResponse.ResultInfo, nil } -// DNSRecord returns a single DNS record for the given zone & record +// GetDNSRecord returns a single DNS record for the given zone & record // identifiers. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details -func (api *API) DNSRecord(ctx context.Context, zoneID, recordID string) (DNSRecord, error) { - uri := fmt.Sprintf("/zones/%s/dns_records/%s", zoneID, recordID) +func (api *API) GetDNSRecord(ctx context.Context, rc *ResourceContainer, recordID string) (DNSRecord, error) { + if rc.Identifier == "" { + return DNSRecord{}, ErrMissingZoneID + } + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return DNSRecord{}, err @@ -228,13 +237,16 @@ func (api *API) DNSRecord(ctx context.Context, zoneID, recordID string) (DNSReco // identifiers. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record -func (api *API) UpdateDNSRecord(ctx context.Context, zoneID, recordID string, rr DNSRecord) error { +func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, recordID string, rr DNSRecord) error { + if rc.Identifier == "" { + return ErrMissingZoneID + } rr.Name = toUTS46ASCII(rr.Name) // Populate the record name from the existing one if the update didn't // specify it. if rr.Name == "" || rr.Type == "" { - rec, err := api.DNSRecord(ctx, zoneID, recordID) + rec, err := api.GetDNSRecord(ctx, rc, recordID) if err != nil { return err } @@ -246,7 +258,7 @@ func (api *API) UpdateDNSRecord(ctx context.Context, zoneID, recordID string, rr rr.Type = rec.Type } } - uri := fmt.Sprintf("/zones/%s/dns_records/%s", zoneID, recordID) + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, rr) if err != nil { return err @@ -263,8 +275,11 @@ func (api *API) UpdateDNSRecord(ctx context.Context, zoneID, recordID string, rr // identifiers. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record -func (api *API) DeleteDNSRecord(ctx context.Context, zoneID, recordID string) error { - uri := fmt.Sprintf("/zones/%s/dns_records/%s", zoneID, recordID) +func (api *API) DeleteDNSRecord(ctx context.Context, rc *ResourceContainer, recordID string) error { + if rc.Identifier == "" { + return ErrMissingZoneID + } + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err diff --git a/dns_example_test.go b/dns_example_test.go index 2af07b87bb..7c799f81aa 100644 --- a/dns_example_test.go +++ b/dns_example_test.go @@ -5,7 +5,7 @@ import ( "fmt" "log" - cloudflare "github.com/cloudflare/cloudflare-go" + "github.com/cloudflare/cloudflare-go" ) func ExampleAPI_DNSRecords_all() { @@ -20,7 +20,7 @@ func ExampleAPI_DNSRecords_all() { } // Fetch all records for a zone - recs, _, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -43,7 +43,7 @@ func ExampleAPI_DNSRecords_filterByContent() { // Fetch only records whose content is 198.51.100.1 localhost := cloudflare.DNSRecord{Content: "198.51.100.1"} - recs, _, err := api.DNSRecords(context.Background(), zoneID, localhost, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), localhost, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -67,7 +67,7 @@ func ExampleAPI_DNSRecords_filterByName() { // Fetch records of any type with name "foo.example.com" // The name must be fully-qualified foo := cloudflare.DNSRecord{Name: "foo.example.com"} - recs, _, err := api.DNSRecords(context.Background(), zoneID, foo, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), foo, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } @@ -90,7 +90,7 @@ func ExampleAPI_DNSRecords_filterByType() { // Fetch only AAAA type records aaaa := cloudflare.DNSRecord{Type: "AAAA"} - recs, _, err := api.DNSRecords(context.Background(), zoneID, aaaa, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), aaaa, cloudflare.DNSListParameters{}) if err != nil { log.Fatal(err) } diff --git a/dns_test.go b/dns_test.go index 093977f35e..2ed51ee846 100644 --- a/dns_test.go +++ b/dns_test.go @@ -146,7 +146,9 @@ func TestCreateDNSRecord(t *testing.T) { Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, } - actual, err := client.CreateDNSRecord(context.Background(), testZoneID, unicodeInput) + _, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(""), unicodeInput) + assert.Equal(t, ErrMissingZoneID, err) + actual, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), unicodeInput) require.NoError(t, err) assert.Equal(t, want, actual) @@ -233,7 +235,10 @@ func TestDNSRecords(t *testing.T) { }, }} - actual, _, err := client.DNSRecords(context.Background(), testZoneID, unicodeInput, DNSListParameters{}) + _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), unicodeInput, DNSListParameters{}) + assert.Equal(t, ErrMissingZoneID, err) + + actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), unicodeInput, DNSListParameters{}) require.NoError(t, err) assert.Equal(t, want, actual) @@ -243,12 +248,7 @@ func TestDNSRecordsSearch(t *testing.T) { setup() defer teardown() - unicodeInput := DNSRecord{ - Name: "example.com", - Type: "A", - Content: "198.51.100.4", - } - asciiInput := DNSRecord{ + recordInput := DNSRecord{ Name: "example.com", Type: "A", Content: "198.51.100.4", @@ -256,9 +256,9 @@ func TestDNSRecordsSearch(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) - assert.Equal(t, asciiInput.Name, r.URL.Query().Get("name")) - assert.Equal(t, asciiInput.Type, r.URL.Query().Get("type")) - assert.Equal(t, asciiInput.Content, r.URL.Query().Get("content")) + assert.Equal(t, recordInput.Name, r.URL.Query().Get("name")) + assert.Equal(t, recordInput.Type, r.URL.Query().Get("type")) + assert.Equal(t, recordInput.Content, r.URL.Query().Get("content")) assert.Equal(t, "all", r.URL.Query().Get("match")) assert.Equal(t, "any", r.URL.Query().Get("tag-match")) assert.Equal(t, "1", r.URL.Query().Get("page")) @@ -282,7 +282,7 @@ func TestDNSRecordsSearch(t *testing.T) { "name": "example.com", "content": "198.51.100.4", "proxiable": true, - "proxied": false, + "proxied": true, "ttl": 120, "locked": false, "zone_id": "d56084adb405e0b7e32c52321bf07be6", @@ -308,14 +308,14 @@ func TestDNSRecordsSearch(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records", handler) - proxied := false + proxied := true createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") want := []DNSRecord{{ ID: "372e67954025e0ba6aaa6d586b9e0b59", Type: "A", - Name: asciiInput.Name, - Content: asciiInput.Content, + Name: recordInput.Name, + Content: recordInput.Content, Proxiable: true, Proxied: &proxied, TTL: 120, @@ -332,7 +332,10 @@ func TestDNSRecordsSearch(t *testing.T) { Tags: []string{"tag1", "tag2extended"}, }} - actual, resultInfo, err := client.DNSRecords(context.Background(), testZoneID, unicodeInput, DNSListParameters{ + actual, resultInfo, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), recordInput, DNSListParameters{ + ResultInfo: ResultInfo{ + Page: 1, + }, Match: "all", Order: "type", Direction: ListDirectionAsc, @@ -417,7 +420,10 @@ func TestDNSRecord(t *testing.T) { Tags: []string{"tag1", "tag2"}, } - actual, err := client.DNSRecord(context.Background(), testZoneID, dnsRecordID) + _, err := client.GetDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID) + assert.Equal(t, ErrMissingZoneID, err) + + actual, err := client.GetDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID) require.NoError(t, err) assert.Equal(t, want, actual) @@ -475,7 +481,10 @@ func TestUpdateDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), testZoneID, dnsRecordID, input) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID, input) + assert.Equal(t, ErrMissingZoneID, err) + + err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, input) require.NoError(t, err) } @@ -584,7 +593,10 @@ func TestUpdateDNSRecordWithoutName(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), testZoneID, dnsRecordID, unicodeInput) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID, unicodeInput) + assert.Equal(t, ErrMissingZoneID, err) + + err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, unicodeInput) require.NoError(t, err) } @@ -692,7 +704,7 @@ func TestUpdateDNSRecordWithoutType(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), testZoneID, dnsRecordID, unicodeInput) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, unicodeInput) require.NoError(t, err) } @@ -718,6 +730,9 @@ func TestDeleteDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.DeleteDNSRecord(context.Background(), testZoneID, dnsRecordID) + err := client.DeleteDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID) + assert.Equal(t, ErrMissingZoneID, err) + + err = client.DeleteDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID) require.NoError(t, err) } diff --git a/example_test.go b/example_test.go index ff8c986762..dd38c54897 100644 --- a/example_test.go +++ b/example_test.go @@ -28,7 +28,7 @@ func Example() { } // Fetch all DNS records for example.org - records, _, err := api.DNSRecords(context.Background(), zoneID, cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) if err != nil { fmt.Println(err) return From 1d918688edd2093bb8c4a002b48557c3712d5056 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Wed, 21 Dec 2022 23:28:49 -0500 Subject: [PATCH 039/370] Fix example refernce --- dns_example_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dns_example_test.go b/dns_example_test.go index 7c799f81aa..9c9e32cc44 100644 --- a/dns_example_test.go +++ b/dns_example_test.go @@ -8,7 +8,7 @@ import ( "github.com/cloudflare/cloudflare-go" ) -func ExampleAPI_DNSRecords_all() { +func ExampleAPI_ListDNSRecords_all() { api, err := cloudflare.New("deadbeef", "test@example.org") if err != nil { log.Fatal(err) @@ -30,7 +30,7 @@ func ExampleAPI_DNSRecords_all() { } } -func ExampleAPI_DNSRecords_filterByContent() { +func ExampleAPI_ListDNSRecords_filterByContent() { api, err := cloudflare.New("deadbeef", "test@example.org") if err != nil { log.Fatal(err) @@ -53,7 +53,7 @@ func ExampleAPI_DNSRecords_filterByContent() { } } -func ExampleAPI_DNSRecords_filterByName() { +func ExampleAPI_ListDNSRecords_filterByName() { api, err := cloudflare.New("deadbeef", "test@example.org") if err != nil { log.Fatal(err) @@ -77,7 +77,7 @@ func ExampleAPI_DNSRecords_filterByName() { } } -func ExampleAPI_DNSRecords_filterByType() { +func ExampleAPI_ListDNSRecords_filterByType() { api, err := cloudflare.New("deadbeef", "test@example.org") if err != nil { log.Fatal(err) From d796af7acd602cb9daa9422edc3299926246329d Mon Sep 17 00:00:00 2001 From: favonia Date: Thu, 22 Dec 2022 07:51:35 -0600 Subject: [PATCH 040/370] remove unnecessary time.Duration(...) --- cloudflare.go | 4 ++-- cloudflare_experimental.go | 4 ++-- cloudflare_test.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cloudflare.go b/cloudflare.go index 952382864b..adf63b9419 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -65,8 +65,8 @@ func newClient(opts ...Option) (*API, error) { rateLimiter: rate.NewLimiter(rate.Limit(4), 1), // 4rps equates to default api limit (1200 req/5 min) retryPolicy: RetryPolicy{ MaxRetries: 3, - MinRetryDelay: time.Duration(1) * time.Second, - MaxRetryDelay: time.Duration(30) * time.Second, + MinRetryDelay: 1 * time.Second, + MaxRetryDelay: 30 * time.Second, }, logger: silentLogger, } diff --git a/cloudflare_experimental.go b/cloudflare_experimental.go index 009d3e1249..8856643b5b 100644 --- a/cloudflare_experimental.go +++ b/cloudflare_experimental.go @@ -98,13 +98,13 @@ func NewExperimental(config *ClientParams) (*Client, error) { if c.RetryPolicy.MinRetryDelay > 0 { retryClient.RetryWaitMin = c.RetryPolicy.MinRetryDelay } else { - retryClient.RetryWaitMin = time.Duration(1) * time.Second + retryClient.RetryWaitMin = 1 * time.Second } if c.RetryPolicy.MaxRetryDelay > 0 { retryClient.RetryWaitMax = c.RetryPolicy.MaxRetryDelay } else { - retryClient.RetryWaitMax = time.Duration(30) * time.Second + retryClient.RetryWaitMax = 30 * time.Second } retryClient.Logger = silentRetryLogger diff --git a/cloudflare_test.go b/cloudflare_test.go index 24ec3154f2..831b1464d9 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -495,18 +495,18 @@ func TestContextTimeout(t *testing.T) { defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { - time.Sleep(time.Second * time.Duration(3)) + time.Sleep(3 * time.Second) } mux.HandleFunc("/timeout", handler) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(1)) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() start := time.Now() _, err := client.makeRequestContext(ctx, http.MethodHead, "/timeout", nil) assert.ErrorIs(t, err, context.DeadlineExceeded) - assert.WithinDuration(t, start, time.Now(), time.Second*2, + assert.WithinDuration(t, start, time.Now(), 2*time.Second, "makeRequestContext took too much time with an expiring context") } From 06a1da1ecbd3f28fa5cf04403708c4685dba6e08 Mon Sep 17 00:00:00 2001 From: vasil Date: Thu, 22 Dec 2022 09:39:17 -0600 Subject: [PATCH 041/370] updated function signatures and added input validation --- mtls_certificates.go | 89 +++++++++++++++++++++++++++++++-------- mtls_certificates_test.go | 21 ++++++--- 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/mtls_certificates.go b/mtls_certificates.go index fb264c6ebc..ca20eb75f9 100644 --- a/mtls_certificates.go +++ b/mtls_certificates.go @@ -3,6 +3,7 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" "time" @@ -43,38 +44,67 @@ type MTLSCertificateResponse struct { // MTLSCertificatesResponse represents the response from the mTLS certificate list endpoint. type MTLSCertificatesResponse struct { Response - Result []MTLSCertificateDetails `json:"result"` + Result []MTLSCertificateDetails `json:"result"` + ResultInfo `json:"result_info"` } // MTLSCertificateParams represents the data related to the mTLS certificate being uploaded. Name is an optional field. -type MTLSCertificateParams struct { +type CreateMTLSCertificateParams struct { Name string `json:"name"` Certificates string `json:"certificates"` PrivateKey string `json:"private_key"` CA bool `json:"ca"` } +type ListMTLSCertificatesParams struct { + PaginationOptions + Limit int `url:"limit,omitempty"` + Offset int `url:"offset,omitempty"` + Name string `url:"name,omitempty"` + CA bool `url:"ca,omitempty"` +} + +var ( + ErrMissingCertificateID = errors.New("missing required certificate ID") +) + // ListMTLSCertificates returns a list of all user-uploaded mTLS certificates. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificates -func (api *API) ListMTLSCertificates(ctx context.Context, accountID string) ([]MTLSCertificateDetails, error) { - uri := fmt.Sprintf("/accounts/%s/mtls_certificates", accountID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) +func (api *API) ListMTLSCertificates(ctx context.Context, rc *ResourceContainer, params ListMTLSCertificatesParams) ([]MTLSCertificateDetails, ResultInfo, error) { + switch { + case rc.Level != AccountRouteLevel: + return []MTLSCertificateDetails{}, ResultInfo{}, ErrRequiredAccountLevelResourceContainer + case rc.Identifier == "": + return []MTLSCertificateDetails{}, ResultInfo{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/mtls_certificates", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) if err != nil { - return []MTLSCertificateDetails{}, err + return []MTLSCertificateDetails{}, ResultInfo{}, err } var r MTLSCertificatesResponse if err := json.Unmarshal(res, &r); err != nil { - return []MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []MTLSCertificateDetails{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return r.Result, nil + return r.Result, r.ResultInfo, err } // GetMTLSCertificateDetails returns the metadata associated with a user-uploaded mTLS certificate. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-get-mtls-certificate -func (api *API) GetMTLSCertificateDetails(ctx context.Context, accountID, certificateID string) (MTLSCertificateDetails, error) { - uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", accountID, certificateID) +func (api *API) GetMTLSCertificateDetails(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificateDetails, error) { + switch { + case rc.Level != AccountRouteLevel: + return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer + case rc.Identifier == "": + return MTLSCertificateDetails{}, ErrMissingAccountID + case certificateID == "": + return MTLSCertificateDetails{}, ErrMissingCertificateID + } + + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", rc.Identifier, certificateID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return MTLSCertificateDetails{}, err @@ -89,8 +119,17 @@ func (api *API) GetMTLSCertificateDetails(ctx context.Context, accountID, certif // ListMTLSCertificateAssociations returns a list of all existing associations between the mTLS certificate and Cloudflare services. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificate-associations -func (api *API) ListMTLSCertificateAssociations(ctx context.Context, accountID, certificateID string) ([]MTLSAssociationDetails, error) { - uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s/associations", accountID, certificateID) +func (api *API) ListMTLSCertificateAssociations(ctx context.Context, rc *ResourceContainer, certificateID string) ([]MTLSAssociationDetails, error) { + switch { + case rc.Level != AccountRouteLevel: + return []MTLSAssociationDetails{}, ErrRequiredAccountLevelResourceContainer + case rc.Identifier == "": + return []MTLSAssociationDetails{}, ErrMissingAccountID + case certificateID == "": + return []MTLSAssociationDetails{}, ErrMissingCertificateID + } + + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s/associations", rc.Identifier, certificateID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []MTLSAssociationDetails{}, err @@ -102,11 +141,18 @@ func (api *API) ListMTLSCertificateAssociations(ctx context.Context, accountID, return r.Result, nil } -// UploadMTLSCertificate will upload the provided certificate for use with mTLS enabled Cloudflare services. +// CreateMTLSCertificate will create the provided certificate for use with mTLS enabled Cloudflare services. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-upload-mtls-certificate -func (api *API) UploadMTLSCertificate(ctx context.Context, accountID string, params MTLSCertificateParams) (MTLSCertificateDetails, error) { - uri := fmt.Sprintf("/accounts/%s/mtls_certificates", accountID) +func (api *API) CreateMTLSCertificate(ctx context.Context, rc *ResourceContainer, params CreateMTLSCertificateParams) (MTLSCertificateDetails, error) { + switch { + case rc.Level != AccountRouteLevel: + return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer + case rc.Identifier == "": + return MTLSCertificateDetails{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/mtls_certificates", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return MTLSCertificateDetails{}, err @@ -121,8 +167,17 @@ func (api *API) UploadMTLSCertificate(ctx context.Context, accountID string, par // DeleteMTLSCertificate will delete the specified mTLS certificate. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-delete-mtls-certificate -func (api *API) DeleteMTLSCertificate(ctx context.Context, accountID, certificateID string) (MTLSCertificateDetails, error) { - uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", accountID, certificateID) +func (api *API) DeleteMTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificateDetails, error) { + switch { + case rc.Level != AccountRouteLevel: + return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer + case rc.Identifier == "": + return MTLSCertificateDetails{}, ErrMissingAccountID + case certificateID == "": + return MTLSCertificateDetails{}, ErrMissingCertificateID + } + + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", rc.Identifier, certificateID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return MTLSCertificateDetails{}, err diff --git a/mtls_certificates_test.go b/mtls_certificates_test.go index 390e37cb0b..30156d0ef4 100644 --- a/mtls_certificates_test.go +++ b/mtls_certificates_test.go @@ -49,7 +49,7 @@ func TestGetMTLSCertificate(t *testing.T) { ExpiresOn: expiresOn, } - actual, err := client.GetMTLSCertificateDetails(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + actual, err := client.GetMTLSCertificateDetails(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -77,7 +77,14 @@ func TestListMTLSCertificates(t *testing.T) { "uploaded_on": "2022-11-22T17:32:30.467938Z", "expires_on": "2122-10-29T16:59:47Z" } - ] + ], + "result_info": { + "page": 1, + "per_page": 50, + "count": 1, + "total_count": 1, + "total_pages": 1 + } }`) } @@ -98,7 +105,7 @@ func TestListMTLSCertificates(t *testing.T) { }, } - actual, err := client.ListMTLSCertificates(context.Background(), "01a7362d577a6c3019a474fd6f485823") + actual, _, err := client.ListMTLSCertificates(context.Background(), AccountIdentifier(testAccountID), ListMTLSCertificatesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -131,7 +138,7 @@ func TestListCertificateAssociations(t *testing.T) { }, } - actual, err := client.ListMTLSCertificateAssociations(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + actual, err := client.ListMTLSCertificateAssociations(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -178,13 +185,13 @@ func TestUploadMTLSCertificate(t *testing.T) { ExpiresOn: expiresOn, } - cert := MTLSCertificateParams{ + cert := CreateMTLSCertificateParams{ Name: "example_ca_cert_5", Certificates: "-----BEGIN CERTIFICATE-----\nMIIDmDCCAoCgAwIBAgIUKTOAZNjcXVZRj4oQt0SHsl1c1vMwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjAgFw0yMjExMjIxNjU5NDdaGA8yMTIyMTAyOTE2NTk0N1owUTELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDVNhbiBGcmFuY2lzY28xEzARBgNVBAcMCkNhbGlmb3JuaWExFTATBgNVBAoMDEV4YW1wbGUgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMRcORwgJFTdcG/2GKI+cFYiOBNDKjCZUXEOvXWY42BkH9wxiMT869CO+enA1w5pIrXow6kCM1sQspHHaVmJUlotEMJxyoLFfA/8Kt1EKFyobOjuZs2SwyVyJ2sStvQuUQEosULZCNGZEqoH5g6zhMPxaxm7ZLrrsDZ9maNGVqo7EWLWHrZ57Q/5MtTrbxQL+eXjUmJ9K3kS+3uEwMdqR6Z3BluU1ivanpPc1CN2GNhdO0/hSY4YkGEnuLsqJyDd3cIiB1MxuCBJ4ZaqOd2viV1WcP3oU3dxVPm4MWyfYIldMWB14FahScxLhWdRnM9YZ/i9IFcLypXsuz7DjrJPtPUCAwEAAaNmMGQwHQYDVR0OBBYEFP5JzLUawNF+c3AXsYTEWHh7z2czMB8GA1UdIwQYMBaAFP5JzLUawNF+c3AXsYTEWHh7z2czMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQBc+Be7NDhpE09y7hLPZGRPl1cSKBw4RI0XIv6rlbSTFs5EebpTGjhx/whNxwEZhB9HZ7111Oa1YlT8xkI9DshB78mjAHCKBAJ76moK8tkG0aqdYpJ4ZcJTVBB7l98Rvgc7zfTii7WemTy72deBbSeiEtXavm4EF0mWjHhQ5Nxpnp00Bqn5g1x8CyTDypgmugnep+xG+iFzNmTdsz7WI9T/7kDMXqB7M/FPWBORyS98OJqNDswCLF8bIZYwUBEe+bRHFomoShMzaC3tvim7WCb16noDkSTMlfKO4pnvKhpcVdSgwcruATV7y+W+Lvmz2OT/Gui4JhqeoTewsxndhDDE\n-----END CERTIFICATE-----", PrivateKey: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEXDkcICRU3XBv9hiiPnBWIjgTQyowmVFxDr11mONgZB/cMYjE/OvQjvnpwNcOaSK16MOpAjNbELKRx2lZiVJaLRDCccqCxXwP/CrdRChcqGzo7mbNksMlcidrErb0LlEBKLFC2QjRmRKqB+YOs4TD8WsZu2S667A2fZmjRlaqOxFi1h62ee0P+TLU628UC/nl41JifSt5Evt7hMDHakemdwZblNYr2p6T3NQjdhjYXTtP4UmOGJBhJ7i7Kicg3d3CIgdTMbggSeGWqjndr4ldVnD96FN3cVT5uDFsn2CJXTFgdeBWoUnMS4VnUZzPWGf4vSBXC8qV7Ls+w46yT7T1AgMBAAECggEAQZnp/oqCeNPOR6l5S2L+1tfx0gWjZ78hJVteUpZ0iHSK7F6kKeOxyOird7vUXV0kmo+cJq+0hp0Ke4eam640FCpwKfYoSQ4/R3vgujGWJnaihCN5tv5sMet0XeJPuz5qE7ALoKCvwI6aXLHs20aAeZIDTQJ9QbGSGnJVzOWn+JDTidIgZpN57RpXfSAwnJPTQK/PN8i5z108hsaDOdEgGmxYZ7kYqMqzX20KXmth58LDfPixs5JGtS60iiKC/wOcGzkB2/AdTSojR76oEU77cANP/3zO25NG//whUdYlW0t0d7PgXxIeJe+xgYnamDQJx3qonVyt4H77ha0ObRAj9QKBgQDicZr+VTwFMnELP3a+FXGnjehRiuS1i7MXGKxNweCD+dFlML0FplSQS8Ro2n+d8lu8BBXGx0qm6VXu8Rhn7TAUL6q+PCgfarzxfIhacb/TZCqfieIHsMlVBfhV5HCXnk+kis0tuC/PRArcWTwDHJUJXkBhvkUsNswvQzavDPI7KwKBgQDd/WgLkj7A3X5fgIHZH/GbDSBiXwzKb+rF4ZCT2XFgG/OAW7vapfcX/w+v+5lBLyrocmOAS3PGGAhM5T3HLnUCQfnK4qgps1Lqibkc9Tmnsn60LanUjuUMsYv/zSw70tozbzhJ0pioEpWfRxRZBztO2Rr8Ntm7h6Fk701EXGNAXwKBgQCD1xsjy2J3sCerIdcz0u5qXLAPkeuZW+34m4/ucdwTWwc0gEz9lhsULFj9p4G351zLuiEnq+7mAWLcDJlmIO3mQt6JhiLiL9Y0T4pgBmxmWqKKYtAsJB0EmMY+1BNN44mBRqMxZFTJu1cLdhT/xstrOeoIPqytknYNanfTMZlzIwKBgHrLXe5oq0XMP8dcMneEcAUwsaU4pr6kQd3L9EmUkl5zl7J9C+DaxWAEuwzBw/iGutlxzRB+rD/7szu14wJ29EqXbDGKRzMp+se5/yfBjm7xEZ1hVPw7PwBShfqt57X/4Ktq7lwHnmH6RcGhc+P7WBc5iO/S94YAdIp8xOT3pf9JAoGAE0QkqJUY+5Mgr+fBO0VNV72ZoPveGpW+De59uhKAOnu1zljQCUtk59m6+DXfm0tNYKtawa5n8iN71Zh+s62xXSt3pYi1Y5CCCmv8Y4BhwIcPwXKk3zEvLgSHVTpC0bayA9aSO4bbZgVXa5w+Z0w/vvfp9DWo1IS3EnQRrz6WMYA=\n-----END PRIVATE KEY-----", CA: true, } - actual, err := client.UploadMTLSCertificate(context.Background(), "01a7362d577a6c3019a474fd6f485823", cert) + actual, err := client.CreateMTLSCertificate(context.Background(), AccountIdentifier(testAccountID), cert) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -229,7 +236,7 @@ func TestDeleteMTLSCertificate(t *testing.T) { ExpiresOn: expiresOn, } - actual, err := client.DeleteMTLSCertificate(context.Background(), "01a7362d577a6c3019a474fd6f485823", "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + actual, err := client.DeleteMTLSCertificate(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") if assert.NoError(t, err) { assert.Equal(t, want, actual) } From 4f0c4c368862c109242903b4d93331ea1d688632 Mon Sep 17 00:00:00 2001 From: Jacob White Date: Thu, 22 Dec 2022 16:52:53 -0500 Subject: [PATCH 042/370] Address PR comments --- .changelog/1151.txt | 1 + dns.go | 106 +++++++++++++++----------------------------- dns_test.go | 16 ------- utils.go | 2 +- 4 files changed, 37 insertions(+), 88 deletions(-) diff --git a/.changelog/1151.txt b/.changelog/1151.txt index 502952ff37..9b98839e1c 100644 --- a/.changelog/1151.txt +++ b/.changelog/1151.txt @@ -5,6 +5,7 @@ dns: changes how DNS records are listed ```release-note:enhancement dns: add support for tags and comments ``` + ```release-note:breaking-change dns: method signatures have been updated to align with the upcoming client conventions ``` \ No newline at end of file diff --git a/dns.go b/dns.go index 357ec6208b..ce6c12f989 100644 --- a/dns.go +++ b/dns.go @@ -5,8 +5,6 @@ import ( "encoding/json" "fmt" "net/http" - "net/url" - "strconv" "time" "golang.org/x/net/idna" @@ -14,11 +12,11 @@ import ( // DNSRecord represents a DNS record in a zone. type DNSRecord struct { - CreatedOn time.Time `json:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty"` - Type string `json:"type,omitempty"` - Name string `json:"name,omitempty"` - Content string `json:"content,omitempty"` + CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` + Type string `json:"type,omitempty" url:"type,omitempty"` + Name string `json:"name,omitempty" url:"name,omitempty"` + Content string `json:"content,omitempty" url:"content,omitempty"` Meta interface{} `json:"meta,omitempty"` Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC ID string `json:"id,omitempty"` @@ -26,10 +24,10 @@ type DNSRecord struct { ZoneName string `json:"zone_name,omitempty"` Priority *uint16 `json:"priority,omitempty"` TTL int `json:"ttl,omitempty"` - Proxied *bool `json:"proxied,omitempty"` + Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` Proxiable bool `json:"proxiable,omitempty"` Locked bool `json:"locked,omitempty"` - Comment string `json:"comment,omitempty"` + Comment string `json:"comment,omitempty" url:"comment,omitempty"` Tags []string `json:"tags,omitempty"` } @@ -40,21 +38,21 @@ type DNSRecordResponse struct { ResultInfo `json:"result_info"` } -type TagQueryParameter string - -const ( - TagQueryPresent TagQueryParameter = "present" - TagQueryAbsent TagQueryParameter = "absent" - TagQueryExact TagQueryParameter = "exact" - TagQueryContains TagQueryParameter = "contains" - TagQueryStartsWith TagQueryParameter = "startswith" - TagQueryEndsWith TagQueryParameter = "endswith" -) - -type TagSearch struct { - Tag string - Query TagQueryParameter -} +//type TagQueryParameter string +// +//const ( +// TagQueryPresent TagQueryParameter = "present" +// TagQueryAbsent TagQueryParameter = "absent" +// TagQueryExact TagQueryParameter = "exact" +// TagQueryContains TagQueryParameter = "contains" +// TagQueryStartsWith TagQueryParameter = "startswith" +// TagQueryEndsWith TagQueryParameter = "endswith" +//) +// +//type TagSearch struct { +// Tag string +// Query TagQueryParameter +//} type ListDirection string @@ -64,15 +62,20 @@ const ( ) type DNSListParameters struct { - TagSearch []TagSearch `url:"-"` - Order string `url:"order,omitempty"` - TagMatch string `url:"tag-match,omitempty"` + //TagSearch []TagSearch `url:"-"` + Order string `url:"order,omitempty"` + //TagMatch string `url:"tag-match,omitempty"` Direction ListDirection `url:"direction,omitempty"` - TagQuery string `url:"-"` - Match string `url:"match,omitempty"` + //TagQuery string `url:"-"` + Match string `url:"match,omitempty"` ResultInfo } +type ListDNSRecordsCombined struct { + DNSRecord + DNSListParameters +} + // DNSListResponse represents the response from the list DNS records endpoint. type DNSListResponse struct { Result []DNSRecord `json:"result"` @@ -132,47 +135,9 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DN if rc.Identifier == "" { return nil, nil, ErrMissingZoneID } - // Construct a query string - v := url.Values{} - // Using default per_page value as specified by the API - if rr.Name != "" { - v.Set("name", toUTS46ASCII(rr.Name)) - } - if rr.Type != "" { - v.Set("type", rr.Type) - } - if rr.Content != "" { - v.Set("content", rr.Content) - } - if rr.Proxied != nil { - v.Set("proxied", strconv.FormatBool(*rr.Proxied)) - } - - if len(params.TagSearch) > 0 { - for _, tagParam := range params.TagSearch { - tagText := fmt.Sprintf("tag.%s", tagParam.Tag) - if tagParam.Query != "" { - tagText += fmt.Sprintf(".%s", tagParam.Query) - } - v.Add("tag", tagText) - } - } - - if params.Order != "" { - v.Set("order", params.Order) - } - - if params.TagMatch != "" { - v.Set("tag-match", params.TagMatch) - } - - if params.Direction != "" { - v.Set("direction", string(params.Direction)) - } - - if params.Match != "" { - v.Set("match", params.Match) + if rr.Name != "" { + rr.Name = toUTS46ASCII(rr.Name) } autoPaginate := true @@ -193,8 +158,7 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DN // Loop over makeRequest until what we've fetched all records for { - v.Set("page", strconv.Itoa(params.Page)) - uri := fmt.Sprintf("/zones/%s/dns_records?%s", rc.Identifier, v.Encode()) + uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), ListDNSRecordsCombined{rr, params}) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []DNSRecord{}, &ResultInfo{}, err diff --git a/dns_test.go b/dns_test.go index 2ed51ee846..fc61d3e28b 100644 --- a/dns_test.go +++ b/dns_test.go @@ -260,15 +260,9 @@ func TestDNSRecordsSearch(t *testing.T) { assert.Equal(t, recordInput.Type, r.URL.Query().Get("type")) assert.Equal(t, recordInput.Content, r.URL.Query().Get("content")) assert.Equal(t, "all", r.URL.Query().Get("match")) - assert.Equal(t, "any", r.URL.Query().Get("tag-match")) assert.Equal(t, "1", r.URL.Query().Get("page")) assert.Equal(t, "type", r.URL.Query().Get("order")) assert.Equal(t, "asc", r.URL.Query().Get("direction")) - fmt.Println(r.URL.Query()["tag"]) - tags := r.URL.Query()["tag"] - assert.Equal(t, 2, len(tags)) - assert.Equal(t, "tag.tag1", tags[0]) - assert.Equal(t, "tag.tag2.contains", tags[1]) w.Header().Set("content-type", "application/json") fmt.Fprint(w, `{ @@ -339,16 +333,6 @@ func TestDNSRecordsSearch(t *testing.T) { Match: "all", Order: "type", Direction: ListDirectionAsc, - TagMatch: "any", - TagSearch: []TagSearch{ - { - Tag: "tag1", - }, - { - Tag: "tag2", - Query: TagQueryContains, - }, - }, }) require.NoError(t, err) assert.Equal(t, 2000, resultInfo.Total) diff --git a/utils.go b/utils.go index 38d4315d76..bc2dc56338 100644 --- a/utils.go +++ b/utils.go @@ -16,7 +16,7 @@ func buildURI(path string, options interface{}) string { } // loadFixture takes a series of path components and returns the JSON fixture at -// that locationassociated. +// that location associated. func loadFixture(parts ...string) string { paths := []string{"testdata", "fixtures"} paths = append(paths, parts...) From 1b620d1fc2585ee01091f89db4b19a2a4b78365f Mon Sep 17 00:00:00 2001 From: Jacob White Date: Thu, 22 Dec 2022 17:13:35 -0500 Subject: [PATCH 043/370] Don't export combined DNS list parameters --- dns.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dns.go b/dns.go index ce6c12f989..eb188c3e61 100644 --- a/dns.go +++ b/dns.go @@ -71,7 +71,7 @@ type DNSListParameters struct { ResultInfo } -type ListDNSRecordsCombined struct { +type listDNSRecordsCombined struct { DNSRecord DNSListParameters } @@ -158,7 +158,7 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DN // Loop over makeRequest until what we've fetched all records for { - uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), ListDNSRecordsCombined{rr, params}) + uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), listDNSRecordsCombined{rr, params}) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []DNSRecord{}, &ResultInfo{}, err From 3f86deb0bbaf80ee6db4867d47850a20bad302bd Mon Sep 17 00:00:00 2001 From: Jacob White Date: Thu, 22 Dec 2022 17:14:52 -0500 Subject: [PATCH 044/370] DNSListParameters -> ListDNSParameters --- cmd/flarectl/dns.go | 2 +- cmd/flarectl/zone.go | 2 +- dns.go | 6 +++--- dns_example_test.go | 8 ++++---- dns_test.go | 6 +++--- example_test.go | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index 2d0712a53c..b556bc8bd5 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -88,7 +88,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr := cloudflare.DNSRecord{ Name: name + "." + zone, } - records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.DNSListParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.ListDNSParameters{}) if err != nil { fmt.Fprintln(os.Stderr, "Error fetching DNS records: ", err) return err diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index b8e21c4eb3..662cdb2aef 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -300,7 +300,7 @@ func zoneRecords(c *cli.Context) error { rr.Content = c.String("content") } var err error - records, _, err = api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.DNSListParameters{}) + records, _, err = api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.ListDNSParameters{}) if err != nil { fmt.Println(err) return err diff --git a/dns.go b/dns.go index eb188c3e61..bb8776fcf5 100644 --- a/dns.go +++ b/dns.go @@ -61,7 +61,7 @@ const ( ListDirectionDesc ListDirection = "desc" ) -type DNSListParameters struct { +type ListDNSParameters struct { //TagSearch []TagSearch `url:"-"` Order string `url:"order,omitempty"` //TagMatch string `url:"tag-match,omitempty"` @@ -73,7 +73,7 @@ type DNSListParameters struct { type listDNSRecordsCombined struct { DNSRecord - DNSListParameters + ListDNSParameters } // DNSListResponse represents the response from the list DNS records endpoint. @@ -131,7 +131,7 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, rr D // This takes a DNSRecord to allow filtering of the results returned. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records -func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DNSRecord, params DNSListParameters) ([]DNSRecord, *ResultInfo, error) { +func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DNSRecord, params ListDNSParameters) ([]DNSRecord, *ResultInfo, error) { if rc.Identifier == "" { return nil, nil, ErrMissingZoneID } diff --git a/dns_example_test.go b/dns_example_test.go index 9c9e32cc44..b84d558050 100644 --- a/dns_example_test.go +++ b/dns_example_test.go @@ -20,7 +20,7 @@ func ExampleAPI_ListDNSRecords_all() { } // Fetch all records for a zone - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.ListDNSParameters{}) if err != nil { log.Fatal(err) } @@ -43,7 +43,7 @@ func ExampleAPI_ListDNSRecords_filterByContent() { // Fetch only records whose content is 198.51.100.1 localhost := cloudflare.DNSRecord{Content: "198.51.100.1"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), localhost, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), localhost, cloudflare.ListDNSParameters{}) if err != nil { log.Fatal(err) } @@ -67,7 +67,7 @@ func ExampleAPI_ListDNSRecords_filterByName() { // Fetch records of any type with name "foo.example.com" // The name must be fully-qualified foo := cloudflare.DNSRecord{Name: "foo.example.com"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), foo, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), foo, cloudflare.ListDNSParameters{}) if err != nil { log.Fatal(err) } @@ -90,7 +90,7 @@ func ExampleAPI_ListDNSRecords_filterByType() { // Fetch only AAAA type records aaaa := cloudflare.DNSRecord{Type: "AAAA"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), aaaa, cloudflare.DNSListParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), aaaa, cloudflare.ListDNSParameters{}) if err != nil { log.Fatal(err) } diff --git a/dns_test.go b/dns_test.go index fc61d3e28b..e317366b34 100644 --- a/dns_test.go +++ b/dns_test.go @@ -235,10 +235,10 @@ func TestDNSRecords(t *testing.T) { }, }} - _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), unicodeInput, DNSListParameters{}) + _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), unicodeInput, ListDNSParameters{}) assert.Equal(t, ErrMissingZoneID, err) - actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), unicodeInput, DNSListParameters{}) + actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), unicodeInput, ListDNSParameters{}) require.NoError(t, err) assert.Equal(t, want, actual) @@ -326,7 +326,7 @@ func TestDNSRecordsSearch(t *testing.T) { Tags: []string{"tag1", "tag2extended"}, }} - actual, resultInfo, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), recordInput, DNSListParameters{ + actual, resultInfo, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), recordInput, ListDNSParameters{ ResultInfo: ResultInfo{ Page: 1, }, diff --git a/example_test.go b/example_test.go index dd38c54897..43e41ea608 100644 --- a/example_test.go +++ b/example_test.go @@ -28,7 +28,7 @@ func Example() { } // Fetch all DNS records for example.org - records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.DNSListParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.ListDNSParameters{}) if err != nil { fmt.Println(err) return From 1be29fa28f882e7bacbb1803e551a48b2837cf02 Mon Sep 17 00:00:00 2001 From: Mikey Sleevi Date: Tue, 20 Dec 2022 20:53:21 -0700 Subject: [PATCH 045/370] Adds support for Tiered Caching Adds support for utilizing previously undocumented APIs for Tiered Caching endpoints. It allows for setting zones to utilize either generic, smart or off. Implementation: * Adds three new api methods for manipulating tiered cache settings * GetTieredCache which returns the current setting * SetTieredCache which allows for manipulation of existing settings * DeleteTieredCache which allows for unsetting tiered cache --- .changelog/1149.txt | 3 + tiered_cache.go | 316 ++++++++++++++++++++++++++++++++++++++++++ tiered_cache_test.go | 321 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 640 insertions(+) create mode 100644 .changelog/1149.txt create mode 100644 tiered_cache.go create mode 100644 tiered_cache_test.go diff --git a/.changelog/1149.txt b/.changelog/1149.txt new file mode 100644 index 0000000000..c6c40af07d --- /dev/null +++ b/.changelog/1149.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +tiered_cache: Add support for Tiered Caching interactions for setting Smart and Generic topologies +``` \ No newline at end of file diff --git a/tiered_cache.go b/tiered_cache.go new file mode 100644 index 0000000000..77b0ce5bbd --- /dev/null +++ b/tiered_cache.go @@ -0,0 +1,316 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "time" +) + +type TieredCacheType int + +const ( + TieredCacheOff TieredCacheType = 0 + TieredCacheGeneric TieredCacheType = 1 + TieredCacheSmart TieredCacheType = 2 +) + +func (e TieredCacheType) String() string { + switch e { + case TieredCacheGeneric: + return "generic" + case TieredCacheSmart: + return "smart" + case TieredCacheOff: + return "off" + default: + return fmt.Sprintf("%d", int(e)) + } +} + +type TieredCache struct { + Type TieredCacheType + LastModified time.Time +} + +// GetTieredCache allows you to retrieve the current Tiered Cache Settings for a Zone. +// This function does not support custom topologies, only Generic and Smart Tiered Caching. +// +// API Reference: https://api.cloudflare.com/#smart-tiered-cache-get-smart-tiered-cache-setting +// API Reference: https://api.cloudflare.com/#tiered-cache-get-tiered-cache-setting +func (api *API) GetTieredCache(ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + var lastModified time.Time + + generic, err := getGenericTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + lastModified = generic.LastModified + + smart, err := getSmartTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + + if smart.LastModified.After(lastModified) { + lastModified = smart.LastModified + } + + if generic.Type == TieredCacheOff { + return TieredCache{Type: TieredCacheOff, LastModified: lastModified}, nil + } + + if smart.Type == TieredCacheOff { + return TieredCache{Type: TieredCacheGeneric, LastModified: lastModified}, nil + } + + return TieredCache{Type: TieredCacheSmart, LastModified: lastModified}, nil +} + +// SetTieredCache allows you to set a zone's tiered cache topology between the available types. +// Using the value of TieredCacheOff will disable Tiered Cache entirely. +// +// API Reference: https://api.cloudflare.com/#smart-tiered-cache-patch-smart-tiered-cache-setting +// API Reference: https://api.cloudflare.com/#tiered-cache-patch-tiered-cache-setting +func (api *API) SetTieredCache(ctx context.Context, rc *ResourceContainer, value TieredCacheType) (TieredCache, error) { + if value == TieredCacheOff { + return api.DeleteTieredCache(ctx, rc) + } + + var lastModified time.Time + + if value == TieredCacheGeneric { + result, err := deleteSmartTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + lastModified = result.LastModified + + result, err = enableGenericTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + + if result.LastModified.After(lastModified) { + lastModified = result.LastModified + } + return TieredCache{Type: TieredCacheGeneric, LastModified: lastModified}, nil + } + + result, err := enableGenericTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + lastModified = result.LastModified + + result, err = enableSmartTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + + if result.LastModified.After(lastModified) { + lastModified = result.LastModified + } + return TieredCache{Type: TieredCacheSmart, LastModified: lastModified}, nil +} + +// DeleteTieredCache allows you to delete the tiered cache settings for a zone. +// This is equivalent to using SetTieredCache with the value of TieredCacheOff. +// +// API Reference: https://api.cloudflare.com/#smart-tiered-cache-delete-smart-tiered-cache-setting +// API Reference: https://api.cloudflare.com/#tiered-cache-patch-tiered-cache-setting +func (api *API) DeleteTieredCache(ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + var lastModified time.Time + + result, err := deleteSmartTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + lastModified = result.LastModified + + result, err = disableGenericTieredCache(api, ctx, rc) + if err != nil { + return TieredCache{}, err + } + + if result.LastModified.After(lastModified) { + lastModified = result.LastModified + } + return TieredCache{Type: TieredCacheOff, LastModified: lastModified}, nil +} + +type tieredCacheResult struct { + ID string `json:"id"` + Value string `json:"value,omitempty"` + LastModified time.Time `json:"modified_on"` +} + +type tieredCacheResponse struct { + Result tieredCacheResult `json:"result"` + Response +} + +type tieredCacheSetting struct { + Value string `json:"value"` +} + +func getGenericTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/argo/tiered_caching", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to retrieve generic tiered cache failed") + } + + if response.Result.Value == "off" { + return TieredCache{Type: TieredCacheOff, LastModified: response.Result.LastModified}, nil + } + + return TieredCache{Type: TieredCacheGeneric, LastModified: response.Result.LastModified}, nil +} + +func getSmartTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/cache/tiered_cache_smart_topology_enable", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + var notFoundError *NotFoundError + if errors.As(err, ¬FoundError) { + return TieredCache{Type: TieredCacheOff}, nil + } + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to retrieve smart tiered cache failed") + } + + if response.Result.Value == "off" { + return TieredCache{Type: TieredCacheOff, LastModified: response.Result.LastModified}, nil + } + return TieredCache{Type: TieredCacheSmart, LastModified: response.Result.LastModified}, nil +} + +func enableGenericTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/argo/tiered_caching", rc.Identifier) + setting := tieredCacheSetting{ + Value: "on", + } + body, err := json.Marshal(setting) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, body) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to enable generic tiered cache failed") + } + + return TieredCache{Type: TieredCacheGeneric, LastModified: response.Result.LastModified}, nil +} + +func enableSmartTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/cache/tiered_cache_smart_topology_enable", rc.Identifier) + setting := tieredCacheSetting{ + Value: "on", + } + body, err := json.Marshal(setting) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, body) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to enable smart tiered cache failed") + } + + return TieredCache{Type: TieredCacheSmart, LastModified: response.Result.LastModified}, nil +} + +func disableGenericTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/argo/tiered_caching", rc.Identifier) + setting := tieredCacheSetting{ + Value: "off", + } + body, err := json.Marshal(setting) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, body) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to disable generic tiered cache failed") + } + + return TieredCache{Type: TieredCacheOff, LastModified: response.Result.LastModified}, nil +} + +func deleteSmartTieredCache(api *API, ctx context.Context, rc *ResourceContainer) (TieredCache, error) { + uri := fmt.Sprintf("/zones/%s/cache/tiered_cache_smart_topology_enable", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + var notFoundError *NotFoundError + if errors.As(err, ¬FoundError) { + return TieredCache{Type: TieredCacheOff}, nil + } + return TieredCache{Type: TieredCacheOff}, err + } + + var response tieredCacheResponse + err = json.Unmarshal(res, &response) + if err != nil { + return TieredCache{Type: TieredCacheOff}, err + } + + if !response.Success { + return TieredCache{Type: TieredCacheOff}, errors.New("request to disable smart tiered cache failed") + } + + return TieredCache{Type: TieredCacheOff, LastModified: response.Result.LastModified}, nil +} diff --git a/tiered_cache_test.go b/tiered_cache_test.go new file mode 100644 index 0000000000..7277b5315e --- /dev/null +++ b/tiered_cache_test.go @@ -0,0 +1,321 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func createSmartTieredCacheHandler(val string, lastModified string) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "editable": true, + "id": "tiered_cache_smart_topology_enable", + "modified_on": "%s", + "value": "%s" + } + }`, lastModified, val) + } +} + +func nonexistentSmartTieredCacheHandler() func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + w.WriteHeader(404) + fmt.Fprintf(w, `{ + "result": null, + "success": false, + "errors": [ + { + "code": 1142, + "message": "Unable to retrieve tiered_cache_smart_topology_enable setting value. The zone setting does not exist." + } + ], + "messages": [] + }`) + } +} + +func createGenericTieredCacheHandler(val string, lastModified string) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "tiered_caching", + "value": "%s", + "modified_on": "%s", + "editable": false + } + }`, val, lastModified) + } +} + +func TestGetTieredCache(t *testing.T) { + t.Run("can identify when Smart Tiered Cache", func(t *testing.T) { + t.Run("is disabled", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("off", lastModified)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheGeneric, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("is enabled", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("on", lastModified)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheSmart, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("zone setting does not exist", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", nonexistentSmartTieredCacheHandler()) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheGeneric, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + }) + + t.Run("can identify when generic tiered cache", func(t *testing.T) { + t.Run("is disabled", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("off", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("on", lastModified)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheOff, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("is enabled", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", nonexistentSmartTieredCacheHandler()) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheGeneric, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + }) + + t.Run("determines the latest last modified when", func(t *testing.T) { + t.Run("smart tiered cache zone setting does not exist", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", nonexistentSmartTieredCacheHandler()) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheGeneric, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("Generic Tiered Cache was modified more recently", func(t *testing.T) { + setup() + defer teardown() + + earlier := time.Now().Add(time.Minute * -5).Format(time.RFC3339) + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", earlier)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("on", lastModified)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheSmart, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("smart tiered cache was modified more recently", func(t *testing.T) { + setup() + defer teardown() + + earlier := time.Now().Add(time.Minute * -5).Format(time.RFC3339) + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("on", earlier)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheSmart, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + }) +} + +func TestSetTieredCache(t *testing.T) { + t.Run("can enable tiered caching", func(t *testing.T) { + t.Run("using smart caching", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", createSmartTieredCacheHandler("on", lastModified)) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheSmart, + LastModified: wanted, + } + + got, err := client.SetTieredCache(context.Background(), ZoneIdentifier(testZoneID), TieredCacheSmart) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + + t.Run("use generic caching", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("on", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", nonexistentSmartTieredCacheHandler()) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheGeneric, + LastModified: wanted, + } + + got, err := client.SetTieredCache(context.Background(), ZoneIdentifier(testZoneID), TieredCacheGeneric) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) + }) +} + +func TestDeleteTieredCache(t *testing.T) { + t.Run("can disable tiered caching", func(t *testing.T) { + setup() + defer teardown() + + lastModified := time.Now().Format(time.RFC3339) + + mux.HandleFunc("/zones/"+testZoneID+"/argo/tiered_caching", createGenericTieredCacheHandler("off", lastModified)) + mux.HandleFunc("/zones/"+testZoneID+"/cache/tiered_cache_smart_topology_enable", nonexistentSmartTieredCacheHandler()) + + wanted, _ := time.Parse(time.RFC3339, lastModified) + want := TieredCache{ + Type: TieredCacheOff, + LastModified: wanted, + } + + got, err := client.GetTieredCache(context.Background(), ZoneIdentifier(testZoneID)) + + if assert.NoError(t, err) { + assert.Equal(t, want, got) + } + }) +} From 6153c1e32fa46b7049683687b7f76eb554c95217 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Dec 2022 10:54:46 +1100 Subject: [PATCH 046/370] Update tiered_cache_test.go --- tiered_cache_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiered_cache_test.go b/tiered_cache_test.go index 7277b5315e..c30ada6404 100644 --- a/tiered_cache_test.go +++ b/tiered_cache_test.go @@ -200,7 +200,7 @@ func TestGetTieredCache(t *testing.T) { } }) - t.Run("Generic Tiered Cache was modified more recently", func(t *testing.T) { + t.Run("generic tiered cache was modified more recently", func(t *testing.T) { setup() defer teardown() From f7fa179568cc533dcc24782edb4b54f81298c45b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 22 Dec 2022 23:57:12 +0000 Subject: [PATCH 047/370] Update CHANGELOG.md for #1149 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07db3e3ff7..7946b1c5ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.58.0 (Unreleased) +ENHANCEMENTS: + +* tiered_cache: Add support for Tiered Caching interactions for setting Smart and Generic topologies ([#1149](https://github.com/cloudflare/cloudflare-go/issues/1149)) + ## 0.57.0 (December 22nd, 2022) BREAKING CHANGES: From 7e65cb260bcf1c28f0be179f204d638743d385a7 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Dec 2022 14:24:53 +1100 Subject: [PATCH 048/370] workers: default body to provided payload This was previously incorrectly always using `body` (an uninitialised slice of bytes) for the script payload when the configuration was not for an ES module upload. Fixes the upload so that both types are covered. --- .changelog/1155.txt | 3 +++ workers.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/1155.txt diff --git a/.changelog/1155.txt b/.changelog/1155.txt new file mode 100644 index 0000000000..d2572b3dfa --- /dev/null +++ b/.changelog/1155.txt @@ -0,0 +1,3 @@ +```release-note:bug +workers: correctly set `body` value for non-ES module uploads +``` diff --git a/workers.go b/workers.go index d5474bc034..b1b3ed7f59 100644 --- a/workers.go +++ b/workers.go @@ -214,10 +214,10 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params return WorkerScriptResponse{}, ErrMissingAccountID } + body := []byte(params.Script) var ( contentType = "application/javascript" err error - body []byte ) if params.Module || len(params.Bindings) > 0 { From c6b5cbfef61b414b490d977f9b7ecbb14692994d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Dec 2022 14:29:33 +1100 Subject: [PATCH 049/370] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7946b1c5ab..24a593ca0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.58.0 (Unreleased) +## 0.57.1 (Unreleased) ENHANCEMENTS: From c9b38359f0416c455ee4493df807429e213d5673 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 23 Dec 2022 03:31:34 +0000 Subject: [PATCH 050/370] Update CHANGELOG.md for #1155 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24a593ca0c..365f7c0aad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ENHANCEMENTS: * tiered_cache: Add support for Tiered Caching interactions for setting Smart and Generic topologies ([#1149](https://github.com/cloudflare/cloudflare-go/issues/1149)) +BUG FIXES: + +* workers: correctly set `body` value for non-ES module uploads ([#1155](https://github.com/cloudflare/cloudflare-go/issues/1155)) + ## 0.57.0 (December 22nd, 2022) BREAKING CHANGES: From ad9f553efef40bf15fb92b55d86f63165a5dfa15 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Dec 2022 14:36:13 +1100 Subject: [PATCH 051/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 365f7c0aad..7b7bfc9ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.57.1 (Unreleased) +## 0.58.0 (Unreleased) + +## 0.57.1 (December 23rd, 2022) ENHANCEMENTS: From 191b2270de1be66eef1d2205a628949a1f88f9ba Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Fri, 23 Dec 2022 11:00:35 -0500 Subject: [PATCH 052/370] firewall_rules/filter: reset fResponse on each loop to avoid residual data --- filter.go | 1 + firewall_rules.go | 1 + 2 files changed, 2 insertions(+) diff --git a/filter.go b/filter.go index 904b6b055f..b5f084648a 100644 --- a/filter.go +++ b/filter.go @@ -124,6 +124,7 @@ func (api *API) Filters(ctx context.Context, rc *ResourceContainer, params Filte var filters []Filter var fResponse FiltersDetailResponse for { + fResponse = FiltersDetailResponse{} uri := buildURI(fmt.Sprintf("/zones/%s/filters", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) diff --git a/firewall_rules.go b/firewall_rules.go index 4d5636c379..51b4ae87ec 100644 --- a/firewall_rules.go +++ b/firewall_rules.go @@ -90,6 +90,7 @@ func (api *API) FirewallRules(ctx context.Context, rc *ResourceContainer, params var firewallRules []FirewallRule var fResponse FirewallRulesDetailResponse for { + fResponse = FirewallRulesDetailResponse{} uri := buildURI(fmt.Sprintf("/zones/%s/firewall/rules", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) From e206cfef76784f2bd85041655d88b8a129df661e Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Fri, 23 Dec 2022 12:48:50 -0500 Subject: [PATCH 053/370] add changelog --- .changelog/1156.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changelog/1156.txt diff --git a/.changelog/1156.txt b/.changelog/1156.txt new file mode 100644 index 0000000000..b93b0d8789 --- /dev/null +++ b/.changelog/1156.txt @@ -0,0 +1,6 @@ +```release-note:bug +firewall_rules: use empty reponse struct on each page call +``` +```release-note:bug +filter: use empty reponse struct on each page call +``` From 0efc21194956b6908849cd2d70563afb512c2f4e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Dec 2022 11:31:46 +1100 Subject: [PATCH 054/370] update method signatures correctly --- .changelog/1151.txt | 14 +++-- cmd/flarectl/dns.go | 27 +++++---- cmd/flarectl/zone.go | 4 +- dns.go | 130 +++++++++++++++++++++++++------------------ dns_example_test.go | 15 ++--- dns_test.go | 85 +++++++++++++++------------- example_test.go | 2 +- 7 files changed, 157 insertions(+), 120 deletions(-) diff --git a/.changelog/1151.txt b/.changelog/1151.txt index 9b98839e1c..5482d72f8e 100644 --- a/.changelog/1151.txt +++ b/.changelog/1151.txt @@ -1,11 +1,15 @@ -```release-note:breaking-change -dns: changes how DNS records are listed -``` - ```release-note:enhancement dns: add support for tags and comments ``` ```release-note:breaking-change dns: method signatures have been updated to align with the upcoming client conventions -``` \ No newline at end of file +``` + +```release-note:breaking-change +dns: `DNSRecords` has been renamed to `ListDNSRecords` +``` + +```release-note:breaking-change +dns: `DNSRecord` has been renamed to `GetDNSRecord` +``` diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index b556bc8bd5..aa7617e022 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -42,7 +42,7 @@ func dnsCreate(c *cli.Context) error { return err } - record := cloudflare.DNSRecord{ + record := cloudflare.CreateDNSRecordParams{ Name: name, Type: strings.ToUpper(rtype), Content: content, @@ -84,11 +84,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { return err } - // Look for an existing record - rr := cloudflare.DNSRecord{ - Name: name + "." + zone, - } - records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.ListDNSParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: name + "." + zone}) if err != nil { fmt.Fprintln(os.Stderr, "Error fetching DNS records: ", err) return err @@ -101,6 +97,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { // has multiple RRs we'll just update the first one. for _, r := range records { if r.Type == rtype { + rr := cloudflare.UpdateDNSRecordParams{} rr.ID = r.ID rr.Type = r.Type rr.Content = content @@ -108,18 +105,28 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr.Proxied = &proxy rr.Priority = &priority - err := api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), r.ID, rr) + err := api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) if err != nil { fmt.Println("Error updating DNS record:", err) return err } resp = &cloudflare.DNSRecordResponse{ - Result: rr, + Result: cloudflare.DNSRecord{ + ID: rr.ID, + Name: rr.Name, + Type: rr.Type, + Content: rr.Content, + TTL: rr.TTL, + Proxiable: rr.Proxiable, + Proxied: &proxy, + Locked: rr.Locked, + }, } } } } else { // Record doesn't exist - create it + rr := cloudflare.CreateDNSRecordParams{} rr.Type = rtype rr.Content = content rr.TTL = ttl @@ -162,7 +169,7 @@ func dnsUpdate(c *cli.Context) error { return err } - record := cloudflare.DNSRecord{ + record := cloudflare.UpdateDNSRecordParams{ ID: recordID, Name: name, Type: strings.ToUpper(rtype), @@ -171,7 +178,7 @@ func dnsUpdate(c *cli.Context) error { Proxied: &proxy, Priority: &priority, } - err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), recordID, record) + err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) if err != nil { fmt.Fprintln(os.Stderr, "Error updating DNS record: ", err) return err diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index 662cdb2aef..19915185ce 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -280,7 +280,7 @@ func zoneRecords(c *cli.Context) error { } // Create an empty record for searching for records - rr := cloudflare.DNSRecord{} + rr := cloudflare.ListDNSRecordsParams{} var records []cloudflare.DNSRecord if c.String("id") != "" { rec, err := api.GetDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), c.String("id")) @@ -300,7 +300,7 @@ func zoneRecords(c *cli.Context) error { rr.Content = c.String("content") } var err error - records, _, err = api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr, cloudflare.ListDNSParameters{}) + records, _, err = api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) if err != nil { fmt.Println(err) return err diff --git a/dns.go b/dns.go index bb8776fcf5..9e1d767f81 100644 --- a/dns.go +++ b/dns.go @@ -12,11 +12,11 @@ import ( // DNSRecord represents a DNS record in a zone. type DNSRecord struct { - CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` - Type string `json:"type,omitempty" url:"type,omitempty"` - Name string `json:"name,omitempty" url:"name,omitempty"` - Content string `json:"content,omitempty" url:"content,omitempty"` + CreatedOn time.Time `json:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Content string `json:"content,omitempty"` Meta interface{} `json:"meta,omitempty"` Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC ID string `json:"id,omitempty"` @@ -24,10 +24,10 @@ type DNSRecord struct { ZoneName string `json:"zone_name,omitempty"` Priority *uint16 `json:"priority,omitempty"` TTL int `json:"ttl,omitempty"` - Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` + Proxied *bool `json:"proxied,omitempty"` Proxiable bool `json:"proxiable,omitempty"` Locked bool `json:"locked,omitempty"` - Comment string `json:"comment,omitempty" url:"comment,omitempty"` + Comment string `json:"comment,omitempty"` Tags []string `json:"tags,omitempty"` } @@ -38,22 +38,6 @@ type DNSRecordResponse struct { ResultInfo `json:"result_info"` } -//type TagQueryParameter string -// -//const ( -// TagQueryPresent TagQueryParameter = "present" -// TagQueryAbsent TagQueryParameter = "absent" -// TagQueryExact TagQueryParameter = "exact" -// TagQueryContains TagQueryParameter = "contains" -// TagQueryStartsWith TagQueryParameter = "startswith" -// TagQueryEndsWith TagQueryParameter = "endswith" -//) -// -//type TagSearch struct { -// Tag string -// Query TagQueryParameter -//} - type ListDirection string const ( @@ -61,19 +45,40 @@ const ( ListDirectionDesc ListDirection = "desc" ) -type ListDNSParameters struct { - //TagSearch []TagSearch `url:"-"` - Order string `url:"order,omitempty"` - //TagMatch string `url:"tag-match,omitempty"` - Direction ListDirection `url:"direction,omitempty"` - //TagQuery string `url:"-"` - Match string `url:"match,omitempty"` +type ListDNSRecordsParams struct { + CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` + Type string `json:"type,omitempty" url:"type,omitempty"` + Name string `json:"name,omitempty" url:"name,omitempty"` + Content string `json:"content,omitempty" url:"content,omitempty"` + Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` + Comment string `json:"comment,omitempty" url:"comment,omitempty"` + Tags []string `json:"tags,omitempty"` + Order string `url:"order,omitempty"` + Direction ListDirection `url:"direction,omitempty"` + Match string `url:"match,omitempty"` + ResultInfo } -type listDNSRecordsCombined struct { - DNSRecord - ListDNSParameters +type UpdateDNSRecordParams struct { + CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` + Type string `json:"type,omitempty" url:"type,omitempty"` + Name string `json:"name,omitempty" url:"name,omitempty"` + Content string `json:"content,omitempty" url:"content,omitempty"` + Meta interface{} `json:"meta,omitempty"` + Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC + ID string `json:"id,omitempty"` + ZoneID string `json:"zone_id,omitempty"` + ZoneName string `json:"zone_name,omitempty"` + Priority *uint16 `json:"priority,omitempty"` + TTL int `json:"ttl,omitempty"` + Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` + Proxiable bool `json:"proxiable,omitempty"` + Locked bool `json:"locked,omitempty"` + Comment string `json:"comment,omitempty" url:"comment,omitempty"` + Tags []string `json:"tags,omitempty"` } // DNSListResponse represents the response from the list DNS records endpoint. @@ -102,17 +107,37 @@ func toUTS46ASCII(name string) string { return name } +type CreateDNSRecordParams struct { + CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` + Type string `json:"type,omitempty" url:"type,omitempty"` + Name string `json:"name,omitempty" url:"name,omitempty"` + Content string `json:"content,omitempty" url:"content,omitempty"` + Meta interface{} `json:"meta,omitempty"` + Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC + ID string `json:"id,omitempty"` + ZoneID string `json:"zone_id,omitempty"` + ZoneName string `json:"zone_name,omitempty"` + Priority *uint16 `json:"priority,omitempty"` + TTL int `json:"ttl,omitempty"` + Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` + Proxiable bool `json:"proxiable,omitempty"` + Locked bool `json:"locked,omitempty"` + Comment string `json:"comment,omitempty" url:"comment,omitempty"` + Tags []string `json:"tags,omitempty"` +} + // CreateDNSRecord creates a DNS record for the zone identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record -func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, rr DNSRecord) (*DNSRecordResponse, error) { +func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, params CreateDNSRecordParams) (*DNSRecordResponse, error) { if rc.Identifier == "" { return nil, ErrMissingZoneID } - rr.Name = toUTS46ASCII(rr.Name) + params.Name = toUTS46ASCII(params.Name) uri := fmt.Sprintf("/zones/%s/dns_records", rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, rr) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return nil, err } @@ -128,16 +153,14 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, rr D // ListDNSRecords returns a slice of DNS records for the given zone identifier. // -// This takes a DNSRecord to allow filtering of the results returned. -// // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records -func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DNSRecord, params ListDNSParameters) ([]DNSRecord, *ResultInfo, error) { +func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, params ListDNSRecordsParams) ([]DNSRecord, *ResultInfo, error) { if rc.Identifier == "" { return nil, nil, ErrMissingZoneID } - if rr.Name != "" { - rr.Name = toUTS46ASCII(rr.Name) + if params.Name != "" { + params.Name = toUTS46ASCII(params.Name) } autoPaginate := true @@ -156,9 +179,8 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, rr DN var records []DNSRecord var listResponse DNSListResponse - // Loop over makeRequest until what we've fetched all records for { - uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), listDNSRecordsCombined{rr, params}) + uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []DNSRecord{}, &ResultInfo{}, err @@ -201,29 +223,31 @@ func (api *API) GetDNSRecord(ctx context.Context, rc *ResourceContainer, recordI // identifiers. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record -func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, recordID string, rr DNSRecord) error { +func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, params UpdateDNSRecordParams) error { if rc.Identifier == "" { return ErrMissingZoneID } - rr.Name = toUTS46ASCII(rr.Name) + + params.Name = toUTS46ASCII(params.Name) // Populate the record name from the existing one if the update didn't // specify it. - if rr.Name == "" || rr.Type == "" { - rec, err := api.GetDNSRecord(ctx, rc, recordID) + if params.Name == "" || params.Type == "" { + rec, err := api.GetDNSRecord(ctx, rc, params.ID) if err != nil { return err } - if rr.Name == "" { - rr.Name = rec.Name + if params.Name == "" { + params.Name = rec.Name } - if rr.Type == "" { - rr.Type = rec.Type + if params.Type == "" { + params.Type = rec.Type } } - uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, rr) + + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, params.ID) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return err } diff --git a/dns_example_test.go b/dns_example_test.go index b84d558050..e864a16fea 100644 --- a/dns_example_test.go +++ b/dns_example_test.go @@ -20,7 +20,7 @@ func ExampleAPI_ListDNSRecords_all() { } // Fetch all records for a zone - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.ListDNSParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{}) if err != nil { log.Fatal(err) } @@ -41,9 +41,7 @@ func ExampleAPI_ListDNSRecords_filterByContent() { log.Fatal(err) } - // Fetch only records whose content is 198.51.100.1 - localhost := cloudflare.DNSRecord{Content: "198.51.100.1"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), localhost, cloudflare.ListDNSParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Content: "198.51.100.1"}) if err != nil { log.Fatal(err) } @@ -64,10 +62,7 @@ func ExampleAPI_ListDNSRecords_filterByName() { log.Fatal(err) } - // Fetch records of any type with name "foo.example.com" - // The name must be fully-qualified - foo := cloudflare.DNSRecord{Name: "foo.example.com"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), foo, cloudflare.ListDNSParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: "foo.example.com"}) if err != nil { log.Fatal(err) } @@ -88,9 +83,7 @@ func ExampleAPI_ListDNSRecords_filterByType() { log.Fatal(err) } - // Fetch only AAAA type records - aaaa := cloudflare.DNSRecord{Type: "AAAA"} - recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), aaaa, cloudflare.ListDNSParameters{}) + recs, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Type: "AAAA"}) if err != nil { log.Fatal(err) } diff --git a/dns_test.go b/dns_test.go index e317366b34..08a55e4eb8 100644 --- a/dns_test.go +++ b/dns_test.go @@ -68,14 +68,6 @@ func TestCreateDNSRecord(t *testing.T) { priority := uint16(10) proxied := false - unicodeInput := DNSRecord{ - Type: "A", - Name: "😺.example.com", - Content: "198.51.100.4", - TTL: 120, - Priority: &priority, - Proxied: &proxied, - } asciiInput := DNSRecord{ Type: "A", Name: "xn--138h.example.com", @@ -146,9 +138,16 @@ func TestCreateDNSRecord(t *testing.T) { Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, } - _, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(""), unicodeInput) + _, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(""), CreateDNSRecordParams{}) assert.Equal(t, ErrMissingZoneID, err) - actual, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), unicodeInput) + + actual, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), CreateDNSRecordParams{ + Type: "A", + Name: "😺.example.com", + Content: "198.51.100.4", + TTL: 120, + Priority: &priority, + Proxied: &proxied}) require.NoError(t, err) assert.Equal(t, want, actual) @@ -158,11 +157,6 @@ func TestDNSRecords(t *testing.T) { setup() defer teardown() - unicodeInput := DNSRecord{ - Name: "😺.example.com", - Type: "A", - Content: "198.51.100.4", - } asciiInput := DNSRecord{ Name: "xn--138h.example.com", Type: "A", @@ -235,10 +229,14 @@ func TestDNSRecords(t *testing.T) { }, }} - _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), unicodeInput, ListDNSParameters{}) + _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), ListDNSRecordsParams{}) assert.Equal(t, ErrMissingZoneID, err) - actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), unicodeInput, ListDNSParameters{}) + actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), ListDNSRecordsParams{ + Name: "😺.example.com", + Type: "A", + Content: "198.51.100.4", + }) require.NoError(t, err) assert.Equal(t, want, actual) @@ -326,13 +324,16 @@ func TestDNSRecordsSearch(t *testing.T) { Tags: []string{"tag1", "tag2extended"}, }} - actual, resultInfo, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), recordInput, ListDNSParameters{ + actual, resultInfo, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), ListDNSRecordsParams{ ResultInfo: ResultInfo{ Page: 1, }, Match: "all", Order: "type", Direction: ListDirectionAsc, + Name: "example.com", + Type: "A", + Content: "198.51.100.4", }) require.NoError(t, err) assert.Equal(t, 2000, resultInfo.Total) @@ -419,6 +420,7 @@ func TestUpdateDNSRecord(t *testing.T) { proxied := false input := DNSRecord{ + ID: "372e67954025e0ba6aaa6d586b9e0b59", Type: "A", Name: "example.com", Content: "198.51.100.4", @@ -465,10 +467,17 @@ func TestUpdateDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID, input) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{}) assert.Equal(t, ErrMissingZoneID, err) - err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, input) + err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + ID: dnsRecordID, + Type: "A", + Name: "example.com", + Content: "198.51.100.4", + TTL: 120, + Proxied: &proxied, + }) require.NoError(t, err) } @@ -479,6 +488,7 @@ func TestUpdateDNSRecordWithoutName(t *testing.T) { proxied := false asciiInput := DNSRecord{ + ID: "372e67954025e0ba6aaa6d586b9e0b59", Name: "xn--138h.example.com", Type: "A", Content: "198.51.100.4", @@ -486,14 +496,6 @@ func TestUpdateDNSRecordWithoutName(t *testing.T) { Proxied: &proxied, } - unicodeInput := DNSRecord{ - Name: "😺.example.com", - Type: "A", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - } - handleUpdateDNSRecord := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) @@ -577,10 +579,17 @@ func TestUpdateDNSRecordWithoutName(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID, unicodeInput) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{}) assert.Equal(t, ErrMissingZoneID, err) - err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, unicodeInput) + err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + ID: dnsRecordID, + Type: "A", + Name: "xn--138h.example.com", + Content: "198.51.100.4", + TTL: 120, + Proxied: &proxied, + }) require.NoError(t, err) } @@ -590,19 +599,13 @@ func TestUpdateDNSRecordWithoutType(t *testing.T) { proxied := false - unicodeInput := DNSRecord{ - Name: "😺.example.com", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - } - completedASCIIInput := DNSRecord{ Name: "xn--138h.example.com", Type: "A", Content: "198.51.100.4", TTL: 120, Proxied: &proxied, + ID: "372e67954025e0ba6aaa6d586b9e0b59", } handleUpdateDNSRecord := func(w http.ResponseWriter, r *http.Request) { @@ -688,7 +691,13 @@ func TestUpdateDNSRecordWithoutType(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID, unicodeInput) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + ID: dnsRecordID, + Name: "😺.example.com", + Content: "198.51.100.4", + TTL: 120, + Proxied: &proxied, + }) require.NoError(t, err) } diff --git a/example_test.go b/example_test.go index 43e41ea608..5c6cc83e4f 100644 --- a/example_test.go +++ b/example_test.go @@ -28,7 +28,7 @@ func Example() { } // Fetch all DNS records for example.org - records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.DNSRecord{}, cloudflare.ListDNSParameters{}) + records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{}) if err != nil { fmt.Println(err) return From 6295645726a80ef4cec79c29b0a92f9ebd7347d6 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 28 Dec 2022 00:42:30 +0000 Subject: [PATCH 055/370] Update CHANGELOG.md for #1151 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b7bfc9ca8..337260217f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## 0.58.0 (Unreleased) +BREAKING CHANGES: + +* dns: `DNSRecord` has been renamed to `GetDNSRecord` ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) +* dns: `DNSRecords` has been renamed to `ListDNSRecords` ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) +* dns: method signatures have been updated to align with the upcoming client conventions ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) + +ENHANCEMENTS: + +* dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) + ## 0.57.1 (December 23rd, 2022) ENHANCEMENTS: From 7467300bfbb395becc7df3f007b2e52e213abb2d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Dec 2022 13:05:03 +1100 Subject: [PATCH 056/370] mtls_certificate: update struct names --- mtls_certificates.go | 146 ++++++++++++++++++++++---------------- mtls_certificates_test.go | 16 +++-- 2 files changed, 94 insertions(+), 68 deletions(-) diff --git a/mtls_certificates.go b/mtls_certificates.go index ca20eb75f9..5d92bd2dd5 100644 --- a/mtls_certificates.go +++ b/mtls_certificates.go @@ -9,20 +9,23 @@ import ( "time" ) -// MTLSAssociationDetails represents the metadata for an existing association between a user-uploaded mTLS certificate and a Cloudflare service. -type MTLSAssociationDetails struct { +// MTLSAssociation represents the metadata for an existing association +// between a user-uploaded mTLS certificate and a Cloudflare service. +type MTLSAssociation struct { Service string `json:"service"` Status string `json:"status"` } -// MTLSAssociationResponse represents the response from the retrieval endpoint for mTLS certificate associations. +// MTLSAssociationResponse represents the response from the retrieval endpoint +// for mTLS certificate associations. type MTLSAssociationResponse struct { Response - Result []MTLSAssociationDetails `json:"result"` + Result []MTLSAssociation `json:"result"` } -// MTLSCertificateDetails represents the metadata for a user-uploaded mTLS certificate. -type MTLSCertificateDetails struct { +// MTLSCertificate represents the metadata for a user-uploaded mTLS +// certificate. +type MTLSCertificate struct { ID string `json:"id"` Name string `json:"name"` Issuer string `json:"issuer"` @@ -35,20 +38,23 @@ type MTLSCertificateDetails struct { ExpiresOn time.Time `json:"expires_on"` } -// MTLSCertificateResponse represents the response from endpoints relating to retrieving, creating, and deleting an mTLS certificate. +// MTLSCertificateResponse represents the response from endpoints relating to +// retrieving, creating, and deleting an mTLS certificate. type MTLSCertificateResponse struct { Response - Result MTLSCertificateDetails `json:"result"` + Result MTLSCertificate `json:"result"` } -// MTLSCertificatesResponse represents the response from the mTLS certificate list endpoint. +// MTLSCertificatesResponse represents the response from the mTLS certificate +// list endpoint. type MTLSCertificatesResponse struct { Response - Result []MTLSCertificateDetails `json:"result"` + Result []MTLSCertificate `json:"result"` ResultInfo `json:"result_info"` } -// MTLSCertificateParams represents the data related to the mTLS certificate being uploaded. Name is an optional field. +// MTLSCertificateParams represents the data related to the mTLS certificate +// being uploaded. Name is an optional field. type CreateMTLSCertificateParams struct { Name string `json:"name"` Certificates string `json:"certificates"` @@ -64,6 +70,10 @@ type ListMTLSCertificatesParams struct { CA bool `url:"ca,omitempty"` } +type ListMTLSCertificateAssociationsParams struct { + CertificateID string +} + var ( ErrMissingCertificateID = errors.New("missing required certificate ID") ) @@ -71,95 +81,106 @@ var ( // ListMTLSCertificates returns a list of all user-uploaded mTLS certificates. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificates -func (api *API) ListMTLSCertificates(ctx context.Context, rc *ResourceContainer, params ListMTLSCertificatesParams) ([]MTLSCertificateDetails, ResultInfo, error) { - switch { - case rc.Level != AccountRouteLevel: - return []MTLSCertificateDetails{}, ResultInfo{}, ErrRequiredAccountLevelResourceContainer - case rc.Identifier == "": - return []MTLSCertificateDetails{}, ResultInfo{}, ErrMissingAccountID +func (api *API) ListMTLSCertificates(ctx context.Context, rc *ResourceContainer, params ListMTLSCertificatesParams) ([]MTLSCertificate, ResultInfo, error) { + if rc.Level != AccountRouteLevel { + return []MTLSCertificate{}, ResultInfo{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []MTLSCertificate{}, ResultInfo{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/mtls_certificates", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, params) if err != nil { - return []MTLSCertificateDetails{}, ResultInfo{}, err + return []MTLSCertificate{}, ResultInfo{}, err } var r MTLSCertificatesResponse if err := json.Unmarshal(res, &r); err != nil { - return []MTLSCertificateDetails{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []MTLSCertificate{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, r.ResultInfo, err } -// GetMTLSCertificateDetails returns the metadata associated with a user-uploaded mTLS certificate. +// GetMTLSCertificate returns the metadata associated with a user-uploaded mTLS +// certificate. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-get-mtls-certificate -func (api *API) GetMTLSCertificateDetails(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificateDetails, error) { - switch { - case rc.Level != AccountRouteLevel: - return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer - case rc.Identifier == "": - return MTLSCertificateDetails{}, ErrMissingAccountID - case certificateID == "": - return MTLSCertificateDetails{}, ErrMissingCertificateID +func (api *API) GetMTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificate, error) { + if rc.Level != AccountRouteLevel { + return MTLSCertificate{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return MTLSCertificate{}, ErrMissingAccountID + } + + if certificateID == "" { + return MTLSCertificate{}, ErrMissingCertificateID } uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", rc.Identifier, certificateID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return MTLSCertificateDetails{}, err + return MTLSCertificate{}, err } var r MTLSCertificateResponse if err := json.Unmarshal(res, &r); err != nil { - return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return MTLSCertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// ListMTLSCertificateAssociations returns a list of all existing associations between the mTLS certificate and Cloudflare services. +// ListMTLSCertificateAssociations returns a list of all existing associations +// between the mTLS certificate and Cloudflare services. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-list-mtls-certificate-associations -func (api *API) ListMTLSCertificateAssociations(ctx context.Context, rc *ResourceContainer, certificateID string) ([]MTLSAssociationDetails, error) { - switch { - case rc.Level != AccountRouteLevel: - return []MTLSAssociationDetails{}, ErrRequiredAccountLevelResourceContainer - case rc.Identifier == "": - return []MTLSAssociationDetails{}, ErrMissingAccountID - case certificateID == "": - return []MTLSAssociationDetails{}, ErrMissingCertificateID +func (api *API) ListMTLSCertificateAssociations(ctx context.Context, rc *ResourceContainer, params ListMTLSCertificateAssociationsParams) ([]MTLSAssociation, error) { + if rc.Level != AccountRouteLevel { + return []MTLSAssociation{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return []MTLSAssociation{}, ErrMissingAccountID + } + + if params.CertificateID == "" { + return []MTLSAssociation{}, ErrMissingCertificateID } - uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s/associations", rc.Identifier, certificateID) + uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s/associations", rc.Identifier, params.CertificateID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []MTLSAssociationDetails{}, err + return []MTLSAssociation{}, err } var r MTLSAssociationResponse if err := json.Unmarshal(res, &r); err != nil { - return []MTLSAssociationDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []MTLSAssociation{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// CreateMTLSCertificate will create the provided certificate for use with mTLS enabled Cloudflare services. +// CreateMTLSCertificate will create the provided certificate for use with mTLS +// enabled Cloudflare services. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-upload-mtls-certificate -func (api *API) CreateMTLSCertificate(ctx context.Context, rc *ResourceContainer, params CreateMTLSCertificateParams) (MTLSCertificateDetails, error) { - switch { - case rc.Level != AccountRouteLevel: - return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer - case rc.Identifier == "": - return MTLSCertificateDetails{}, ErrMissingAccountID +func (api *API) CreateMTLSCertificate(ctx context.Context, rc *ResourceContainer, params CreateMTLSCertificateParams) (MTLSCertificate, error) { + if rc.Level != AccountRouteLevel { + return MTLSCertificate{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return MTLSCertificate{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/mtls_certificates", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { - return MTLSCertificateDetails{}, err + return MTLSCertificate{}, err } var r MTLSCertificateResponse if err := json.Unmarshal(res, &r); err != nil { - return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return MTLSCertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } @@ -167,24 +188,27 @@ func (api *API) CreateMTLSCertificate(ctx context.Context, rc *ResourceContainer // DeleteMTLSCertificate will delete the specified mTLS certificate. // // API reference: https://api.cloudflare.com/#mtls-certificate-management-delete-mtls-certificate -func (api *API) DeleteMTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificateDetails, error) { - switch { - case rc.Level != AccountRouteLevel: - return MTLSCertificateDetails{}, ErrRequiredAccountLevelResourceContainer - case rc.Identifier == "": - return MTLSCertificateDetails{}, ErrMissingAccountID - case certificateID == "": - return MTLSCertificateDetails{}, ErrMissingCertificateID +func (api *API) DeleteMTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (MTLSCertificate, error) { + if rc.Level != AccountRouteLevel { + return MTLSCertificate{}, ErrRequiredAccountLevelResourceContainer + } + + if rc.Identifier == "" { + return MTLSCertificate{}, ErrMissingAccountID + } + + if certificateID == "" { + return MTLSCertificate{}, ErrMissingCertificateID } uri := fmt.Sprintf("/accounts/%s/mtls_certificates/%s", rc.Identifier, certificateID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return MTLSCertificateDetails{}, err + return MTLSCertificate{}, err } var r MTLSCertificateResponse if err := json.Unmarshal(res, &r); err != nil { - return MTLSCertificateDetails{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return MTLSCertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } diff --git a/mtls_certificates_test.go b/mtls_certificates_test.go index 30156d0ef4..2652eae7b0 100644 --- a/mtls_certificates_test.go +++ b/mtls_certificates_test.go @@ -37,7 +37,7 @@ func TestGetMTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", handler) expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") - want := MTLSCertificateDetails{ + want := MTLSCertificate{ ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", Name: "example_ca_cert_5", Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", @@ -49,7 +49,7 @@ func TestGetMTLSCertificate(t *testing.T) { ExpiresOn: expiresOn, } - actual, err := client.GetMTLSCertificateDetails(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + actual, err := client.GetMTLSCertificate(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -91,7 +91,7 @@ func TestListMTLSCertificates(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates", handler) expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") - want := []MTLSCertificateDetails{ + want := []MTLSCertificate{ { ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", Name: "example_ca_cert_5", @@ -131,14 +131,16 @@ func TestListCertificateAssociations(t *testing.T) { } mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60/associations", handler) - want := []MTLSAssociationDetails{ + want := []MTLSAssociation{ { Service: "gateway", Status: "pending_deployment", }, } - actual, err := client.ListMTLSCertificateAssociations(context.Background(), AccountIdentifier(testAccountID), "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60") + actual, err := client.ListMTLSCertificateAssociations(context.Background(), AccountIdentifier(testAccountID), ListMTLSCertificateAssociationsParams{ + CertificateID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -172,7 +174,7 @@ func TestUploadMTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates", handler) expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") - want := MTLSCertificateDetails{ + want := MTLSCertificate{ ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", Name: "example_ca_cert_5", Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", @@ -224,7 +226,7 @@ func TestDeleteMTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/mtls_certificates/2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", handler) expiresOn, _ := time.Parse(time.RFC3339, "2122-10-29T16:59:47Z") uploadedOn, _ := time.Parse(time.RFC3339, "2022-11-22T17:32:30.467938Z") - want := MTLSCertificateDetails{ + want := MTLSCertificate{ ID: "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60", Name: "example_ca_cert_5", Issuer: "O=Example Inc.,L=California,ST=San Francisco,C=US", From 857104a925d8cd07fae9fc141a8f1f9069c1c571 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 28 Dec 2022 13:07:36 +1100 Subject: [PATCH 057/370] add CHANGELOG entry --- .changelog/1150.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1150.txt diff --git a/.changelog/1150.txt b/.changelog/1150.txt new file mode 100644 index 0000000000..ef7d48cd3c --- /dev/null +++ b/.changelog/1150.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +mtls_certificate: add support for managing mTLS certificates and assocations +``` From ef3d061e59ef7100d41f1877fe9dd0702881ce3d Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 28 Dec 2022 02:13:41 +0000 Subject: [PATCH 058/370] Update CHANGELOG.md for #1150 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 337260217f..e93bc6ed8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ BREAKING CHANGES: ENHANCEMENTS: * dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) +* mtls_certificate: add support for managing mTLS certificates and assocations ([#1150](https://github.com/cloudflare/cloudflare-go/issues/1150)) ## 0.57.1 (December 23rd, 2022) From 11efaeb1438227064ef37efb8c748c9578251cb7 Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Wed, 28 Dec 2022 15:22:17 -0600 Subject: [PATCH 059/370] Add user_seat_expiration_inactive_time field to Access org --- access_organization.go | 13 +++++++------ access_organization_test.go | 4 +++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/access_organization.go b/access_organization.go index dbebdca7ea..35c9e9e378 100644 --- a/access_organization.go +++ b/access_organization.go @@ -10,12 +10,13 @@ import ( // AccessOrganization represents an Access organization. type AccessOrganization struct { - CreatedAt *time.Time `json:"created_at"` - UpdatedAt *time.Time `json:"updated_at"` - Name string `json:"name"` - AuthDomain string `json:"auth_domain"` - LoginDesign AccessOrganizationLoginDesign `json:"login_design"` - IsUIReadOnly *bool `json:"is_ui_read_only,omitempty"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` + Name string `json:"name"` + AuthDomain string `json:"auth_domain"` + LoginDesign AccessOrganizationLoginDesign `json:"login_design"` + IsUIReadOnly *bool `json:"is_ui_read_only,omitempty"` + UserSeatExpirationInactiveTime string `json:"user_seat_expiration_inactive_time,omitempty"` } // AccessOrganizationLoginDesign represents the login design options. diff --git a/access_organization_test.go b/access_organization_test.go index 0e1cede85d..f09a0a37ed 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -27,6 +27,7 @@ func TestAccessOrganization(t *testing.T) { "name": "Widget Corps Internal Applications", "auth_domain": "test.cloudflareaccess.com", "is_ui_read_only": false, + "user_seat_expiration_inactive_time": "720h", "login_design": { "background_color": "#c5ed1b", "logo_path": "https://example.com/logo.png", @@ -54,7 +55,8 @@ func TestAccessOrganization(t *testing.T) { HeaderText: "Widget Corp", FooterText: "© Widget Corp", }, - IsUIReadOnly: BoolPtr(false), + IsUIReadOnly: BoolPtr(false), + UserSeatExpirationInactiveTime: "720h", } mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) From 0a8c1009c740fadc7311367ed51069223890dab7 Mon Sep 17 00:00:00 2001 From: Jacob Fowler Date: Wed, 28 Dec 2022 09:15:57 -0500 Subject: [PATCH 060/370] do the same interface reset for more paginated calls --- email_routing_destination.go | 1 + email_routing_rules.go | 1 + lockdown.go | 1 + queue.go | 2 ++ teams_list.go | 1 + workers_kv.go | 1 + 6 files changed, 7 insertions(+) diff --git a/email_routing_destination.go b/email_routing_destination.go index e9705e5590..cb9e30a945 100644 --- a/email_routing_destination.go +++ b/email_routing_destination.go @@ -61,6 +61,7 @@ func (api *API) ListEmailRoutingDestinationAddresses(ctx context.Context, rc *Re var addresses []EmailRoutingDestinationAddress var eResponse ListEmailRoutingAddressResponse for { + eResponse = ListEmailRoutingAddressResponse{} uri := buildURI(fmt.Sprintf("/accounts/%s/email/routing/addresses", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) diff --git a/email_routing_rules.go b/email_routing_rules.go index 22101b6245..a6c075f826 100644 --- a/email_routing_rules.go +++ b/email_routing_rules.go @@ -103,6 +103,7 @@ func (api *API) ListEmailRoutingRules(ctx context.Context, rc *ResourceContainer var rules []EmailRoutingRule var rResponse ListEmailRoutingRuleResponse for { + rResponse = ListEmailRoutingRuleResponse{} uri := buildURI(fmt.Sprintf("/zones/%s/email/routing/rules", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) diff --git a/lockdown.go b/lockdown.go index 2a2f744647..a946e5a219 100644 --- a/lockdown.go +++ b/lockdown.go @@ -166,6 +166,7 @@ func (api *API) ListZoneLockdowns(ctx context.Context, rc *ResourceContainer, pa var zoneLockdowns []ZoneLockdown var zResponse ZoneLockdownListResponse for { + zResponse = ZoneLockdownListResponse{} uri := buildURI(fmt.Sprintf("/zones/%s/firewall/lockdowns", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) diff --git a/queue.go b/queue.go index 0bd5a4dfa6..3b9aa5e90a 100644 --- a/queue.go +++ b/queue.go @@ -129,6 +129,7 @@ func (api *API) ListQueues(ctx context.Context, rc *ResourceContainer, params Li var queues []Queue var qResponse QueueListResponse for { + qResponse = QueueListResponse{} uri := buildURI(fmt.Sprintf("/accounts/%s/workers/queues", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -276,6 +277,7 @@ func (api *API) ListQueueConsumers(ctx context.Context, rc *ResourceContainer, p var queuesConsumers []QueueConsumer var qResponse ListQueueConsumersResponse for { + qResponse = ListQueueConsumersResponse{} uri := buildURI(fmt.Sprintf("/accounts/%s/workers/queues/%s/consumers", rc.Identifier, params.QueueName), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) diff --git a/teams_list.go b/teams_list.go index 2f43001569..30c21d9d2d 100644 --- a/teams_list.go +++ b/teams_list.go @@ -172,6 +172,7 @@ func (api *API) ListTeamsListItems(ctx context.Context, rc *ResourceContainer, p var teamListItems []TeamsListItem var lResponse TeamsListItemsListResponse for { + lResponse = TeamsListItemsListResponse{} uri := buildURI( fmt.Sprintf("/%s/%s/gateway/lists/%s/items", rc.Level, rc.Identifier, params.ListID), params, diff --git a/workers_kv.go b/workers_kv.go index 7cdf30e3c6..8a62924b63 100644 --- a/workers_kv.go +++ b/workers_kv.go @@ -153,6 +153,7 @@ func (api *API) ListWorkersKVNamespaces(ctx context.Context, rc *ResourceContain var namespaces []WorkersKVNamespace var nsResponse ListWorkersKVNamespacesResponse for { + nsResponse = ListWorkersKVNamespacesResponse{} uri := buildURI(fmt.Sprintf("/accounts/%s/storage/kv/namespaces", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) From 50908bb00e8fef97cadb028c11cc5f7c806a6da3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Dec 2022 08:28:30 +1100 Subject: [PATCH 061/370] update CHANGELOG --- .changelog/1156.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.changelog/1156.txt b/.changelog/1156.txt index b93b0d8789..2a19167b7d 100644 --- a/.changelog/1156.txt +++ b/.changelog/1156.txt @@ -1,6 +1,31 @@ ```release-note:bug firewall_rules: use empty reponse struct on each page call ``` + ```release-note:bug filter: use empty reponse struct on each page call ``` + +```release-note:bug +email_routing_destination: use empty reponse struct on each page call +``` + +```release-note:bug +email_routing_rules: use empty reponse struct on each page call +``` + +```release-note:bug +lockdown: use empty reponse struct on each page call +``` + +```release-note:bug +queue: use empty reponse struct on each page call +``` + +```release-note:bug +teams_list: use empty reponse struct on each page call +``` + +```release-note:bug +workers_kv: use empty reponse struct on each page call +``` From 72e77953a7fddd697d5c8d360ead23ba47e38e5e Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 29 Dec 2022 21:46:24 +0000 Subject: [PATCH 062/370] Update CHANGELOG.md for #1156 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e93bc6ed8b..b9ee5e9b2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ ENHANCEMENTS: * dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) * mtls_certificate: add support for managing mTLS certificates and assocations ([#1150](https://github.com/cloudflare/cloudflare-go/issues/1150)) +BUG FIXES: + +* email_routing_destination: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* email_routing_rules: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* filter: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* firewall_rules: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* lockdown: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* queue: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* teams_list: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +* workers_kv: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) + ## 0.57.1 (December 23rd, 2022) ENHANCEMENTS: From fc25ece5cd7dba368bf287cb3bb74226469d044f Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Fri, 30 Dec 2022 09:21:34 -0600 Subject: [PATCH 063/370] Add changelog entry --- .changelog/1161.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1161.txt diff --git a/.changelog/1161.txt b/.changelog/1161.txt new file mode 100644 index 0000000000..5aca5dc5ba --- /dev/null +++ b/.changelog/1161.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access_organization: add user_seat_expiration_inactive_time field +``` From c071c00470ddeabd8cd9df4576cab11022be4622 Mon Sep 17 00:00:00 2001 From: Nathan Disidore Date: Thu, 29 Dec 2022 13:38:11 -0600 Subject: [PATCH 064/370] feat(workers): allow enabling logpush on worker uploads --- .changelog/1160.txt | 3 +++ workers.go | 8 +++++++- workers_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .changelog/1160.txt diff --git a/.changelog/1160.txt b/.changelog/1160.txt new file mode 100644 index 0000000000..5264f36df8 --- /dev/null +++ b/.changelog/1160.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +workers-upload: Add support for workers logpush enablement on script upload +``` \ No newline at end of file diff --git a/workers.go b/workers.go index b1b3ed7f59..b834c58b17 100644 --- a/workers.go +++ b/workers.go @@ -28,6 +28,10 @@ type CreateWorkerParams struct { // ES Module syntax script. Module bool + // Logpush opts the worker into Workers Logpush logging. A nil value leaves the current setting unchanged. + // https://developers.cloudflare.com/workers/platform/logpush/ + Logpush *bool + // Bindings should be a map where the keys are the binding name, and the // values are the binding content Bindings map[string]WorkerBinding @@ -220,7 +224,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params err error ) - if params.Module || len(params.Bindings) > 0 { + if params.Module || params.Logpush != nil || len(params.Bindings) > 0 { contentType, body, err = formatMultipartBody(params) if err != nil { return WorkerScriptResponse{}, err @@ -257,8 +261,10 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) { BodyPart string `json:"body_part,omitempty"` MainModule string `json:"main_module,omitempty"` Bindings []workerBindingMeta `json:"bindings"` + Logpush *bool `json:"logpush,omitempty"` }{ Bindings: make([]workerBindingMeta, 0, len(params.Bindings)), + Logpush: params.Logpush, } if params.Module { diff --git a/workers_test.go b/workers_test.go index 647f1af327..c76b7d053d 100644 --- a/workers_test.go +++ b/workers_test.go @@ -277,6 +277,7 @@ func getFileDetails(r *http.Request, key string) (*multipart.FileHeader, error) type multipartUpload struct { Script string BindingMeta map[string]workerBindingMeta + Logpush *bool } func parseMultipartUpload(r *http.Request) (multipartUpload, error) { @@ -290,6 +291,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { BodyPart string `json:"body_part,omitempty"` MainModule string `json:"main_module,omitempty"` Bindings []workerBindingMeta `json:"bindings"` + Logpush *bool `json:"logpush,omitempty"` } err = json.Unmarshal(mdBytes, &metadata) if err != nil { @@ -318,6 +320,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { return multipartUpload{ Script: string(script), BindingMeta: bindingMeta, + Logpush: metadata.Logpush, }, nil } @@ -823,3 +826,36 @@ func TestUploadWorker_WithServiceBinding(t *testing.T) { }) assert.NoError(t, err) } + +func TestUploadWorker_WithLogpush(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", 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) + + expected := true + assert.Equal(t, &expected, mpUpload.Logpush) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, uploadWorkerResponseData) + }) + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript, Logpush: BoolPtr(true)}) + formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") + want := WorkerScriptResponse{ + successResponse, + false, + WorkerScript{ + Script: workerScript, + WorkerMetaData: WorkerMetaData{ + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + ModifiedOn: formattedTime, + }, + }} + if assert.NoError(t, err) { + assert.Equal(t, want, res) + } +} From 75a0b0efac5affb3b65ea7a9b2c5d070ce11978a Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 3 Jan 2023 09:26:55 +1100 Subject: [PATCH 065/370] Rename 1161.txt to 1159.txt --- .changelog/{1161.txt => 1159.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1161.txt => 1159.txt} (100%) diff --git a/.changelog/1161.txt b/.changelog/1159.txt similarity index 100% rename from .changelog/1161.txt rename to .changelog/1159.txt From 6ba86da9682034b67c274770982c1a3bead7ce20 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 3 Jan 2023 10:48:20 +1100 Subject: [PATCH 066/370] Update 1160.txt --- .changelog/1160.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changelog/1160.txt b/.changelog/1160.txt index 5264f36df8..b4893dc46b 100644 --- a/.changelog/1160.txt +++ b/.changelog/1160.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -workers-upload: Add support for workers logpush enablement on script upload -``` \ No newline at end of file +workers: Add support for workers logpush enablement on script upload +``` From c4ab0b6da6e055ab8c7ed8b2573341e55eb43c72 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 2 Jan 2023 23:53:28 +0000 Subject: [PATCH 067/370] Update CHANGELOG.md for #1160 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9ee5e9b2b..db7b01fd2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ENHANCEMENTS: * dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) * mtls_certificate: add support for managing mTLS certificates and assocations ([#1150](https://github.com/cloudflare/cloudflare-go/issues/1150)) +* workers: Add support for workers logpush enablement on script upload ([#1160](https://github.com/cloudflare/cloudflare-go/issues/1160)) BUG FIXES: From 8802b7fedcb914b8eec37d6795efaa1624bda763 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 3 Jan 2023 14:28:01 +1100 Subject: [PATCH 068/370] origin_ca: remove the restriction of using API service keys The team has made strides in removing the restriction of only using the API user service keys for origin CA requests so we can now pass in any auth scheme the end user requires. --- .changelog/1161.txt | 23 ++++++++++++++++ cmd/flarectl/misc.go | 2 +- origin_ca.go | 64 +++++++++++++++++++++----------------------- origin_ca_test.go | 22 ++++++++++----- 4 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 .changelog/1161.txt diff --git a/.changelog/1161.txt b/.changelog/1161.txt new file mode 100644 index 0000000000..5578937b36 --- /dev/null +++ b/.changelog/1161.txt @@ -0,0 +1,23 @@ +```release-note:enhancement +origin_ca: add support for using API keys, API tokens or API User service keys for interacting with Origin CA endpoints +``` + +```release-note:breaking-change +origin_ca: renamed to `CreateOriginCertificate` to `CreateOriginCACertificate` +``` + +```release-note:breaking-change +origin_ca: renamed to `OriginCertificates` to `ListOriginCACertificates` +``` + +```release-note:breaking-change +origin_ca: renamed to `OriginCertificate` to `GetOriginCACertificate` +``` + +```release-note:breaking-change +origin_ca: renamed to `RevokeOriginCertificate` to `RevokeOriginCACertificate` +``` + +```release-note:breaking-change +origin_ca: renamed to `OriginCARootCertificate` to `GetOriginCARootCertificate` +``` diff --git a/cmd/flarectl/misc.go b/cmd/flarectl/misc.go index edad3d9803..ddfeeb6cfb 100644 --- a/cmd/flarectl/misc.go +++ b/cmd/flarectl/misc.go @@ -203,7 +203,7 @@ func pageRules(c *cli.Context) error { } func originCARootCertificate(c *cli.Context) error { - cert, err := cloudflare.OriginCARootCertificate(c.String("algorithm")) + cert, err := cloudflare.GetOriginCARootCertificate(c.String("algorithm")) if err != nil { return err } diff --git a/origin_ca.go b/origin_ca.go index a7eaea7240..45c8951570 100644 --- a/origin_ca.go +++ b/origin_ca.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "net/http" - "net/url" "time" ) @@ -25,6 +24,17 @@ type OriginCACertificate struct { CSR string `json:"csr"` } +type CreateOriginCertificateParams struct { + ID string `json:"id"` + Certificate string `json:"certificate"` + Hostnames []string `json:"hostnames"` + ExpiresOn time.Time `json:"expires_on"` + RequestType string `json:"request_type"` + RequestValidity int `json:"requested_validity"` + RevokedAt time.Time `json:"revoked_at,omitempty"` + CSR string `json:"csr"` +} + // UnmarshalJSON handles custom parsing from an API response to an OriginCACertificate // http://choly.ca/post/go-json-marshalling/ func (c *OriginCACertificate) UnmarshalJSON(data []byte) error { @@ -57,9 +67,10 @@ func (c *OriginCACertificate) UnmarshalJSON(data []byte) error { return nil } -// OriginCACertificateListOptions represents the parameters used to list Cloudflare-issued certificates. -type OriginCACertificateListOptions struct { - ZoneID string +// ListOriginCertificatesParams represents the parameters used to list +// Cloudflare-issued certificates. +type ListOriginCertificatesParams struct { + ZoneID string `url:"zone_id,omitempty"` } // OriginCACertificateID represents the ID of the revoked certificate from the Revoke Certificate endpoint. @@ -86,17 +97,13 @@ type originCACertificateResponseRevoke struct { Result OriginCACertificateID `json:"result"` } -// CreateOriginCertificate creates a Cloudflare-signed certificate. -// -// This function requires api.APIUserServiceKey be set to your Certificates API key. +// CreateOriginCACertificate creates a Cloudflare-signed certificate. // // API reference: https://api.cloudflare.com/#cloudflare-ca-create-certificate -func (api *API) CreateOriginCertificate(ctx context.Context, certificate OriginCACertificate) (*OriginCACertificate, error) { - uri := "/certificates" - res, err := api.makeRequestWithAuthType(ctx, http.MethodPost, uri, certificate, AuthUserService) - +func (api *API) CreateOriginCACertificate(ctx context.Context, params CreateOriginCertificateParams) (*OriginCACertificate, error) { + res, err := api.makeRequestContext(ctx, http.MethodPost, "/certificates", params) if err != nil { - return nil, err + return &OriginCACertificate{}, err } var originResponse *originCACertificateResponse @@ -114,18 +121,12 @@ func (api *API) CreateOriginCertificate(ctx context.Context, certificate OriginC return &originResponse.Result, nil } -// OriginCertificates lists all Cloudflare-issued certificates. -// -// This function requires api.APIUserServiceKey be set to your Certificates API key. +// ListOriginCACertificates lists all Cloudflare-issued certificates. // // API reference: https://api.cloudflare.com/#cloudflare-ca-list-certificates -func (api *API) OriginCertificates(ctx context.Context, options OriginCACertificateListOptions) ([]OriginCACertificate, error) { - v := url.Values{} - if options.ZoneID != "" { - v.Set("zone_id", options.ZoneID) - } - uri := fmt.Sprintf("/certificates?%s", v.Encode()) - res, err := api.makeRequestWithAuthType(ctx, http.MethodGet, uri, nil, AuthUserService) +func (api *API) ListOriginCACertificates(ctx context.Context, params ListOriginCertificatesParams) ([]OriginCACertificate, error) { + uri := buildURI("/certificates", params) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err @@ -146,14 +147,13 @@ func (api *API) OriginCertificates(ctx context.Context, options OriginCACertific return originResponse.Result, nil } -// OriginCertificate returns the details for a Cloudflare-issued certificate. -// -// This function requires api.APIUserServiceKey be set to your Certificates API key. +// GetOriginCACertificate returns the details for a Cloudflare-issued +// certificate. // // API reference: https://api.cloudflare.com/#cloudflare-ca-certificate-details -func (api *API) OriginCertificate(ctx context.Context, certificateID string) (*OriginCACertificate, error) { +func (api *API) GetOriginCACertificate(ctx context.Context, certificateID string) (*OriginCACertificate, error) { uri := fmt.Sprintf("/certificates/%s", certificateID) - res, err := api.makeRequestWithAuthType(ctx, http.MethodGet, uri, nil, AuthUserService) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err @@ -174,14 +174,12 @@ func (api *API) OriginCertificate(ctx context.Context, certificateID string) (*O return &originResponse.Result, nil } -// RevokeOriginCertificate revokes a created certificate for a zone. -// -// This function requires api.APIUserServiceKey be set to your Certificates API key. +// RevokeOriginCACertificate revokes a created certificate for a zone. // // API reference: https://api.cloudflare.com/#cloudflare-ca-revoke-certificate -func (api *API) RevokeOriginCertificate(ctx context.Context, certificateID string) (*OriginCACertificateID, error) { +func (api *API) RevokeOriginCACertificate(ctx context.Context, certificateID string) (*OriginCACertificateID, error) { uri := fmt.Sprintf("/certificates/%s", certificateID) - res, err := api.makeRequestWithAuthType(ctx, http.MethodDelete, uri, nil, AuthUserService) + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return nil, err @@ -204,7 +202,7 @@ func (api *API) RevokeOriginCertificate(ctx context.Context, certificateID strin // Gets the Cloudflare Origin CA Root Certificate for a given algorithm in PEM format. // Algorithm must be one of ['ecc', 'rsa']. -func OriginCARootCertificate(algorithm string) ([]byte, error) { +func GetOriginCARootCertificate(algorithm string) ([]byte, error) { var url string switch algorithm { case "ecc": diff --git a/origin_ca_test.go b/origin_ca_test.go index 00510804ac..855472b9c5 100644 --- a/origin_ca_test.go +++ b/origin_ca_test.go @@ -74,7 +74,7 @@ func TestOriginCA_CreateOriginCertificate(t *testing.T) { expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - testCertificate := OriginCACertificate{ + testCertificate := CreateOriginCertificateParams{ ID: "0x47530d8f561faa08", Certificate: "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----", Hostnames: []string{"example.com", "*.another.com"}, @@ -84,10 +84,18 @@ func TestOriginCA_CreateOriginCertificate(t *testing.T) { CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----", } - createdCertificate, err := client.CreateOriginCertificate(context.Background(), testCertificate) + createdCertificate, err := client.CreateOriginCACertificate(context.Background(), testCertificate) if assert.NoError(t, err) { - assert.Equal(t, createdCertificate, &testCertificate) + assert.Equal(t, &OriginCACertificate{ + ID: "0x47530d8f561faa08", + Certificate: "-----BEGIN CERTIFICATE-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE-----", + Hostnames: []string{"example.com", "*.another.com"}, + ExpiresOn: expiresOn, + RequestType: "origin-rsa", + RequestValidity: 5475, + CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----", + }, createdCertificate) } } @@ -138,7 +146,7 @@ func TestOriginCA_OriginCertificates(t *testing.T) { CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----", } - certs, err := client.OriginCertificates(context.Background(), OriginCACertificateListOptions{ZoneID: testZoneID}) + certs, err := client.ListOriginCACertificates(context.Background(), ListOriginCertificatesParams{ZoneID: testZoneID}) if assert.NoError(t, err) { assert.IsType(t, []OriginCACertificate{}, certs, "Expected type []OriginCACertificate and got %v", certs) @@ -187,7 +195,7 @@ func TestOriginCA_OriginCertificate(t *testing.T) { CSR: "-----BEGIN CERTIFICATE REQUEST-----MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDzANBgNVBAcMBkxpbmRvbjEWMBQGA1UECgwNRGlnaUNlcnQgSW5jLjERMA8GA1UECwwIRGlnaUNlcnQxHTAbBgNVBAMMFGV4YW1wbGUuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8+To7d+2kPWeBv/orU3LVbJwDrSQbeKamCmowp5bqDxIwV20zqRb7APUOKYoVEFFOEQs6T6gImnIolhbiH6m4zgZ/CPvWBOkZc+c1Po2EmvBz+AD5sBdT5kzGQA6NbWyZGldxRthNLOs1efOhdnWFuhI162qmcflgpiIWDuwq4C9f+YkeJhNn9dF5+owm8cOQmDrV8NNdiTqin8q3qYAHHJRW28glJUCZkTZwIaSR6crBQ8TbYNE0dc+Caa3DOIkz1EOsHWzTx+n0zKfqcbgXi4DJx+C1bjptYPRBPZL8DAeWuA8ebudVT44yEp82G96/Ggcf7F33xMxe0yc+Xa6owIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAB0kcrFccSmFDmxox0Ne01UIqSsDqHgL+XmHTXJwre6DhJSZwbvEtOK0G3+dr4Fs11WuUNt5qcLsx5a8uk4G6AKHMzuhLsJ7XZjgmQXGECpYQ4mC3yT3ZoCGpIXbw+iP3lmEEXgaQL0Tx5LFl/okKbKYwIqNiyKWOMj7ZR/wxWg/ZDGRs55xuoeLDJ/ZRFf9bI+IaCUd1YrfYcHIl3G87Av+r49YVwqRDT0VDV7uLgqn29XI1PpVUNCPQGn9p/eX6Qo7vpDaPybRtA2R7XLKjQaF9oXWeCUqy1hvJac9QFO297Ob1alpHPoZ7mWiEuJwjBPii6a9M9G30nUo39lBi1w=-----END CERTIFICATE REQUEST-----", } - cert, err := client.OriginCertificate(context.Background(), testCertificate.ID) + cert, err := client.GetOriginCACertificate(context.Background(), testCertificate.ID) if assert.NoError(t, err) { assert.IsType(t, &OriginCACertificate{}, cert, "Expected type &OriginCACertificate and got %v", cert) @@ -216,7 +224,7 @@ func TestOriginCA_RevokeCertificate(t *testing.T) { ID: "0x47530d8f561faa08", } - cert, err := client.RevokeOriginCertificate(context.Background(), testCertificate.ID) + cert, err := client.RevokeOriginCACertificate(context.Background(), testCertificate.ID) if assert.NoError(t, err) { assert.IsType(t, &OriginCACertificateID{}, cert, "Expected type &OriginCACertificateID and got %v", cert) @@ -237,7 +245,7 @@ func TestOriginCA_OriginCARootCertificate(t *testing.T) { for _, algorithm := range algorithms { t.Logf("get origin CA root certificate for algorithm %s", algorithm) - rootCACert, err := OriginCARootCertificate(algorithm) + rootCACert, err := GetOriginCARootCertificate(algorithm) if assert.NoError(t, err) { assert.NotNil(t, rootCACert) From d95d01b121dbac55a1431d48eff36dff079fb155 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 16:00:54 +0000 Subject: [PATCH 069/370] build(deps): bump github.com/hashicorp/go-retryablehttp Bumps [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp) from 0.7.1 to 0.7.2. - [Release notes](https://github.com/hashicorp/go-retryablehttp/releases) - [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.1...v0.7.2) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-retryablehttp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index e1025876d6..3de4049dfb 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/google/go-querystring v1.1.0 - github.com/hashicorp/go-retryablehttp v0.7.1 + github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 github.com/urfave/cli/v2 v2.23.7 diff --git a/go.sum b/go.sum index 35c42f5773..ca36a2231b 100644 --- a/go.sum +++ b/go.sum @@ -13,14 +13,13 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= -github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= +github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= From b77c9f92b9b9e2794c380c0fc3e839db7007efe0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 3 Jan 2023 16:05:01 +0000 Subject: [PATCH 070/370] add CHANGELOG for #1162 --- .changelog/1162.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1162.txt diff --git a/.changelog/1162.txt b/.changelog/1162.txt new file mode 100644 index 0000000000..871465c057 --- /dev/null +++ b/.changelog/1162.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 +``` From 9f773b1d9314071e2b5545f45454b6100193fe29 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 3 Jan 2023 19:07:25 +0000 Subject: [PATCH 071/370] Update CHANGELOG.md for #1162 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db7b01fd2d..cb467f87d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ BUG FIXES: * teams_list: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) * workers_kv: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156)) +DEPENDENCIES: + +* deps: bumps github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 ([#1162](https://github.com/cloudflare/cloudflare-go/issues/1162)) + ## 0.57.1 (December 23rd, 2022) ENHANCEMENTS: From e2a4e000360f1ef3429ffd3bf3c2cbdca9492418 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 4 Jan 2023 00:37:36 +0000 Subject: [PATCH 072/370] Update CHANGELOG.md for #1161 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb467f87d2..1bcb99fe71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,17 @@ BREAKING CHANGES: * dns: `DNSRecord` has been renamed to `GetDNSRecord` ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) * dns: `DNSRecords` has been renamed to `ListDNSRecords` ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) * dns: method signatures have been updated to align with the upcoming client conventions ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) +* origin_ca: renamed to `CreateOriginCertificate` to `CreateOriginCACertificate` ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) +* origin_ca: renamed to `OriginCARootCertificate` to `GetOriginCARootCertificate` ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) +* origin_ca: renamed to `OriginCertificate` to `GetOriginCACertificate` ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) +* origin_ca: renamed to `OriginCertificates` to `ListOriginCACertificates` ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) +* origin_ca: renamed to `RevokeOriginCertificate` to `RevokeOriginCACertificate` ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) ENHANCEMENTS: * dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151)) * mtls_certificate: add support for managing mTLS certificates and assocations ([#1150](https://github.com/cloudflare/cloudflare-go/issues/1150)) +* origin_ca: add support for using API keys, API tokens or API User service keys for interacting with Origin CA endpoints ([#1161](https://github.com/cloudflare/cloudflare-go/issues/1161)) * workers: Add support for workers logpush enablement on script upload ([#1160](https://github.com/cloudflare/cloudflare-go/issues/1160)) BUG FIXES: From 19b3f7ab6a6f268ce5c322a56b8a674808677474 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 4 Jan 2023 12:02:53 +1100 Subject: [PATCH 073/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bcb99fe71..e3cf3516f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.58.0 (Unreleased) +## 0.59.0 (Unreleased) + +## 0.58.0 (January 4th, 2023) BREAKING CHANGES: From fdc3a7d100c8a2c79097df798e73e2b308625720 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 5 Jan 2023 07:08:39 +1100 Subject: [PATCH 074/370] cloudflare: move HTTP request debugging to `httputil` Within the library, we provide a way to output the HTTP interactions that the library makes. We previously used a custom approach and format the output. Even though it works, there are better approaches using `httputil.DumpRequestOut` and `httputil.DumpResponseOut` for dumping the HTTP interactions. Alongside this work, we're adding support for redacting sensitive values in the HTTP interactions. This is useful for both this library and the consumers of this library (like the Terraform Provider) to prevent leaking sensitive information in logs. Closes #1143 --- .changelog/1164.txt | 3 +++ cloudflare.go | 48 ++++++++++++++++++++++++-------------- cloudflare_experimental.go | 45 ++++++++++++++++++++++++----------- 3 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 .changelog/1164.txt diff --git a/.changelog/1164.txt b/.changelog/1164.txt new file mode 100644 index 0000000000..72272d5df3 --- /dev/null +++ b/.changelog/1164.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cloudflare: automatically redact sensitive values from HTTP interactions +``` diff --git a/cloudflare.go b/cloudflare.go index adf63b9419..5b0c220fcf 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -11,7 +11,9 @@ import ( "log" "math" "net/http" + "net/http/httputil" "net/url" + "regexp" "strconv" "strings" "time" @@ -250,20 +252,6 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m return nil, fmt.Errorf("error caused by request rate limiting: %w", err) } - if api.Debug { - if method == http.MethodPost || method == http.MethodPut || method == http.MethodPatch { - buf := &bytes.Buffer{} - tee := io.TeeReader(reqBody, buf) - debugBody, _ := io.ReadAll(tee) - payloadBody, _ := io.ReadAll(buf) - fmt.Printf("cloudflare-go [DEBUG] REQUEST Method:%v URI:%s Headers:%#v Body:%v\n", method, api.BaseURL+uri, headers, string(debugBody)) - // ensure we recreate the io.Reader for use - reqBody = bytes.NewReader(payloadBody) - } else { - fmt.Printf("cloudflare-go [DEBUG] REQUEST Method:%v URI:%s Headers:%#v Body:%v\n", method, api.BaseURL+uri, headers, nil) - } - } - resp, respErr = api.request(ctx, method, uri, reqBody, authType, headers) // short circuit processing on context timeouts @@ -307,10 +295,6 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m return nil, respErr } - if api.Debug { - fmt.Printf("cloudflare-go [DEBUG] RESPONSE StatusCode:%d RayID:%s ContentType:%s Body:%#v\n", resp.StatusCode, resp.Header.Get("cf-ray"), resp.Header.Get("content-type"), string(respBody)) - } - if resp.StatusCode >= http.StatusBadRequest { if strings.HasSuffix(resp.Request.URL.Path, "/filters/validate-expr") { return nil, fmt.Errorf("%s", respBody) @@ -379,6 +363,9 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m // *http.Response, or an error if one occurred. The caller is responsible for // closing the response body. func (api *API) request(ctx context.Context, method, uri string, reqBody io.Reader, authType int, headers http.Header) (*http.Response, error) { + log.SetPrefix(time.Now().Format(time.RFC3339Nano) + " [DEBUG] cloudflare") + log.SetFlags(0) + req, err := http.NewRequestWithContext(ctx, method, api.BaseURL+uri, reqBody) if err != nil { return nil, fmt.Errorf("HTTP request creation failed: %w", err) @@ -408,11 +395,36 @@ func (api *API) request(ctx context.Context, method, uri string, reqBody io.Read req.Header.Set("Content-Type", "application/json") } + if api.Debug { + dump, err := httputil.DumpRequestOut(req, true) + if err != nil { + return nil, err + } + + // Strip out any sensitive information from the request payload. + sensitiveKeys := []string{api.APIKey, api.APIEmail, api.APIToken, api.APIUserServiceKey} + for _, key := range sensitiveKeys { + if key != "" { + valueRegex := regexp.MustCompile(fmt.Sprintf("(?m)%s", key)) + dump = valueRegex.ReplaceAll(dump, []byte("[redacted]")) + } + } + log.Printf("\n%s", string(dump)) + } + resp, err := api.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("HTTP request failed: %w", err) } + if api.Debug { + dump, err := httputil.DumpResponse(resp, true) + if err != nil { + return resp, err + } + log.Printf("\n%s", string(dump)) + } + return resp, nil } diff --git a/cloudflare_experimental.go b/cloudflare_experimental.go index 8856643b5b..e01c7a60d0 100644 --- a/cloudflare_experimental.go +++ b/cloudflare_experimental.go @@ -6,8 +6,11 @@ import ( "encoding/json" "fmt" "io" + "log" "net/http" + "net/http/httputil" "net/url" + "regexp" "strings" "sync" "time" @@ -158,6 +161,9 @@ func NewExperimental(config *ClientParams) (*Client, error) { // *http.Response, or an error if one occurred. The caller is responsible for // closing the response body. func (c *Client) request(ctx context.Context, method, uri string, reqBody io.Reader, headers http.Header) (*http.Response, error) { + log.SetPrefix(time.Now().Format(time.RFC3339Nano) + " [DEBUG] cloudflare") + log.SetFlags(0) + req, err := http.NewRequestWithContext(ctx, method, c.BaseURL.String()+uri, reqBody) if err != nil { return nil, fmt.Errorf("HTTP request creation failed: %w", err) @@ -193,11 +199,36 @@ func (c *Client) request(ctx context.Context, method, uri string, reqBody io.Rea req.Header.Set("Content-Type", "application/json") } + if c.Debug { + dump, err := httputil.DumpRequestOut(req, true) + if err != nil { + return nil, err + } + + // Strip out any sensitive information from the request payload. + sensitiveKeys := []string{c.Key, c.Email, c.Token, c.UserServiceKey} + for _, key := range sensitiveKeys { + if key != "" { + valueRegex := regexp.MustCompile(fmt.Sprintf("(?m)%s", key)) + dump = valueRegex.ReplaceAll(dump, []byte("[redacted]")) + } + } + log.Printf("\n%s", string(dump)) + } + resp, err := c.HTTPClient.Do(req) if err != nil { return nil, fmt.Errorf("HTTP request failed: %w", err) } + if c.Debug { + dump, err := httputil.DumpResponse(resp, true) + if err != nil { + return resp, err + } + log.Printf("\n%s", string(dump)) + } + return resp, nil } @@ -224,25 +255,11 @@ func (c *Client) makeRequest(ctx context.Context, method, uri string, params int var respErr error var respBody []byte - if method == http.MethodPost || method == http.MethodPut || method == http.MethodPatch { - buf := &bytes.Buffer{} - tee := io.TeeReader(reqBody, buf) - debugBody, _ := io.ReadAll(tee) - payloadBody, _ := io.ReadAll(buf) - c.Logger.Debugf("REQUEST Method:%v URI:%s Headers:%#v Body:%v\n", method, c.BaseURL.String()+uri, headers, string(debugBody)) - // ensure we recreate the io.Reader for use - reqBody = bytes.NewReader(payloadBody) - } else { - c.Logger.Debugf("REQUEST Method:%v URI:%s Headers:%#v Body:%v\n", method, c.BaseURL.String()+uri, headers, nil) //) - } - resp, respErr = c.request(ctx, method, uri, reqBody, headers) if respErr != nil { return nil, respErr } - c.Logger.Debugf("RESPONSE URI:%s StatusCode:%d Body:%#v RayID:%s\n", c.BaseURL.String()+uri, resp.StatusCode, string(respBody), resp.Header.Get("cf-ray")) - respBody, err = io.ReadAll(resp.Body) resp.Body.Close() if err != nil { From 4cc044180a432056852ee740a8d20d6bff851f2b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 4 Jan 2023 20:43:26 +0000 Subject: [PATCH 075/370] Update CHANGELOG.md for #1164 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3cf3516f6..30673d7286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.59.0 (Unreleased) +ENHANCEMENTS: + +* cloudflare: automatically redact sensitive values from HTTP interactions ([#1164](https://github.com/cloudflare/cloudflare-go/issues/1164)) + ## 0.58.0 (January 4th, 2023) BREAKING CHANGES: From a7b8640f01d3f4c54eb9c929d7596b0540a9841e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 5 Jan 2023 09:46:56 +1100 Subject: [PATCH 076/370] dns: allow filtering `ListDNSRecord` calls by `priority` Even though this doesn't make it to the API, we still use it internally for filtering. --- dns.go | 1 + 1 file changed, 1 insertion(+) diff --git a/dns.go b/dns.go index 9e1d767f81..aa96e8a10c 100644 --- a/dns.go +++ b/dns.go @@ -57,6 +57,7 @@ type ListDNSRecordsParams struct { Order string `url:"order,omitempty"` Direction ListDirection `url:"direction,omitempty"` Match string `url:"match,omitempty"` + Priority *uint16 `json:"priority,omitempty"` ResultInfo } From 46d12ba52acd07bd0f533f083f930182238a6090 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 5 Jan 2023 09:53:21 +1100 Subject: [PATCH 077/370] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30673d7286..e70a9ec9be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## 0.59.0 (Unreleased) +## 0.58.1 (January 5th, 2023) + ENHANCEMENTS: * cloudflare: automatically redact sensitive values from HTTP interactions ([#1164](https://github.com/cloudflare/cloudflare-go/issues/1164)) From d1bf0c1b780d590f491fb2711c731d0543e7ed52 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 5 Jan 2023 22:36:50 +0000 Subject: [PATCH 078/370] Update CHANGELOG.md for #1159 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e70a9ec9be..45255e0b76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.59.0 (Unreleased) +ENHANCEMENTS: + +* access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) + ## 0.58.1 (January 5th, 2023) ENHANCEMENTS: From db0830c5bd7804e8656d046c4dd76eeb7e28eae5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 6 Jan 2023 11:58:45 +1100 Subject: [PATCH 079/370] dns: don't send unsupported "priority" field for list operations --- .changelog/1167.txt | 3 +++ dns.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/1167.txt diff --git a/.changelog/1167.txt b/.changelog/1167.txt new file mode 100644 index 0000000000..6dacacf5e7 --- /dev/null +++ b/.changelog/1167.txt @@ -0,0 +1,3 @@ +```release-note:bug +dns: don't send "priority" for list operations as it isn't supported and is only used for internal filtering +``` diff --git a/dns.go b/dns.go index aa96e8a10c..473f9ae7de 100644 --- a/dns.go +++ b/dns.go @@ -57,7 +57,7 @@ type ListDNSRecordsParams struct { Order string `url:"order,omitempty"` Direction ListDirection `url:"direction,omitempty"` Match string `url:"match,omitempty"` - Priority *uint16 `json:"priority,omitempty"` + Priority *uint16 `url:"-"` ResultInfo } From 63d7aa85c4216e423033ce2f3315a672b657afd6 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 6 Jan 2023 01:07:33 +0000 Subject: [PATCH 080/370] Update CHANGELOG.md for #1167 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45255e0b76..d18b0239a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ENHANCEMENTS: * access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) +BUG FIXES: + +* dns: don't send "priority" for list operations as it isn't supported and is only used for internal filtering ([#1167](https://github.com/cloudflare/cloudflare-go/issues/1167)) + ## 0.58.1 (January 5th, 2023) ENHANCEMENTS: From ba553a9d8ba676dc181c2633bb1bb9f9e9a93487 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Mon, 9 Jan 2023 12:08:38 -0500 Subject: [PATCH 081/370] WDAPI-1221 Fix Update Method to be PUT from PATCH --- devices_managed_networks.go | 2 +- devices_managed_networks_test.go | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/devices_managed_networks.go b/devices_managed_networks.go index 1f6129a6a9..2e308eb213 100644 --- a/devices_managed_networks.go +++ b/devices_managed_networks.go @@ -103,7 +103,7 @@ func (api *API) UpdateDeviceManagedNetwork(ctx context.Context, rc *ResourceCont uri := fmt.Sprintf("/%s/%s/devices/networks/%s", rc.Level, rc.Identifier, params.NetworkID) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return DeviceManagedNetwork{}, err } diff --git a/devices_managed_networks_test.go b/devices_managed_networks_test.go index 7f2f4bb6b7..c62c7c6792 100644 --- a/devices_managed_networks_test.go +++ b/devices_managed_networks_test.go @@ -149,6 +149,57 @@ func TestCreateDeviceManagedNetwork(t *testing.T) { } } +func TestUpdateDeviceManagedNetwork(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": + { + "network_id": "%s", + "type": "tls", + "name": "managed-network-1", + "config": { + "tls_sockaddr": "foobar:1234", + "sha256": "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" + } + } + }`, testNetworkID) + } + + want := DeviceManagedNetwork{ + NetworkID: testNetworkID, + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/networks/"+testNetworkID, handler) + + actual, err := client.UpdateDeviceManagedNetwork(context.Background(), AccountIdentifier(testAccountID), UpdateDeviceManagedNetworkParams{ + NetworkID: testNetworkID, + Type: "tls", + Name: "managed-network-1", + Config: &Config{ + TlsSockAddr: "foobar:1234", + Sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c", + }, + }) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestDeleteDeviceManagedNetwork(t *testing.T) { setup() defer teardown() From 866845a94d38c930fa4fa400309c6d65632f5d35 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Mon, 9 Jan 2023 12:13:10 -0500 Subject: [PATCH 082/370] change log added --- .changelog/1172.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1172.txt diff --git a/.changelog/1172.txt b/.changelog/1172.txt new file mode 100644 index 0000000000..9b4a5bff22 --- /dev/null +++ b/.changelog/1172.txt @@ -0,0 +1,3 @@ +```release-note:bug +managednetworks: Update should be PUT +``` From f0f163bcc884a4caa652e4f3d93306ecabf2967e Mon Sep 17 00:00:00 2001 From: Artur Rodrigues Date: Mon, 9 Jan 2023 09:48:12 +0000 Subject: [PATCH 083/370] Match ListDNSRecords per_page value to the API's As outlined in github.com/cloudflare/cloudflare-go/pull/1169, when no pagination options are passed in to ListDNSRecords, autopagination is performed. However, the current PerPage value doesn't match that of the official API. This commit makes both values match. A new test is also implemented that more explicitly tests the auto pagination behaviour. Signed-off-by: Artur Rodrigues --- dns.go | 10 +++++-- dns_test.go | 37 ++++++++++++++++++++++++-- testdata/fixtures/dns/list_page_1.json | 37 ++++++++++++++++++++++++++ testdata/fixtures/dns/list_page_2.json | 37 ++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 testdata/fixtures/dns/list_page_1.json create mode 100644 testdata/fixtures/dns/list_page_2.json diff --git a/dns.go b/dns.go index 473f9ae7de..99aec41ded 100644 --- a/dns.go +++ b/dns.go @@ -89,6 +89,9 @@ type DNSListResponse struct { ResultInfo `json:"result_info"` } +// listDNSRecordsDefaultPageSize represents the default per_page size of the API. +var listDNSRecordsDefaultPageSize int = 100 + // nontransitionalLookup implements the nontransitional processing as specified in // Unicode Technical Standard 46 with almost all checkings off to maximize user freedom. var nontransitionalLookup = idna.New( @@ -152,7 +155,10 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, para return recordResp, nil } -// ListDNSRecords returns a slice of DNS records for the given zone identifier. +// ListDNSRecords returns a slice of DNS records for the given zone +// identifier. If params doesn't include any pagination (ResultInfo) +// options, auto pagination is performed with the default page size +// of 100 records per request. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, params ListDNSRecordsParams) ([]DNSRecord, *ResultInfo, error) { @@ -170,7 +176,7 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, param } if params.PerPage < 1 { - params.PerPage = 50 + params.PerPage = listDNSRecordsDefaultPageSize } if params.Page < 1 { diff --git a/dns_test.go b/dns_test.go index 08a55e4eb8..4c2fb94957 100644 --- a/dns_test.go +++ b/dns_test.go @@ -153,7 +153,7 @@ func TestCreateDNSRecord(t *testing.T) { assert.Equal(t, want, actual) } -func TestDNSRecords(t *testing.T) { +func TestListDNSRecords(t *testing.T) { setup() defer teardown() @@ -242,7 +242,7 @@ func TestDNSRecords(t *testing.T) { assert.Equal(t, want, actual) } -func TestDNSRecordsSearch(t *testing.T) { +func TestListDNSRecordsSearch(t *testing.T) { setup() defer teardown() @@ -341,6 +341,39 @@ func TestDNSRecordsSearch(t *testing.T) { assert.Equal(t, want, actual) } +func TestListDNSRecordsPagination(t *testing.T) { + // change listDNSRecordsDefaultPageSize value to 1 to force pagination + listDNSRecordsDefaultPageSize = 1 + + setup() + defer teardown() + + var page1Called, page2Called bool + handler := func(w http.ResponseWriter, r *http.Request) { + page := r.URL.Query().Get("page") + w.Header().Set("content-type", "application/json") + + var response string + switch page { + case "1": + response = loadFixture("dns", "list_page_1") + page1Called = true + case "2": + response = loadFixture("dns", "list_page_2") + page2Called = true + } + fmt.Fprint(w, response) + } + + mux.HandleFunc("/zones/"+testZoneID+"/dns_records", handler) + + actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), ListDNSRecordsParams{}) + require.NoError(t, err) + assert.True(t, page1Called) + assert.True(t, page2Called) + assert.Len(t, actual, 2) +} + func TestDNSRecord(t *testing.T) { setup() defer teardown() diff --git a/testdata/fixtures/dns/list_page_1.json b/testdata/fixtures/dns/list_page_1.json new file mode 100644 index 0000000000..15acc55332 --- /dev/null +++ b/testdata/fixtures/dns/list_page_1.json @@ -0,0 +1,37 @@ +{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "type": "A", + "name": "example.com", + "content": "198.51.100.4", + "proxiable": true, + "proxied": true, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": [ + "tag1", + "tag2extended" + ] + } + ], + "result_info": { + "count": 1, + "page": 1, + "per_page": 1, + "total_count": 2, + "total_pages": 2 + } +} diff --git a/testdata/fixtures/dns/list_page_2.json b/testdata/fixtures/dns/list_page_2.json new file mode 100644 index 0000000000..b7836c01c3 --- /dev/null +++ b/testdata/fixtures/dns/list_page_2.json @@ -0,0 +1,37 @@ +{ + "success": true, + "errors": [], + "messages": [], + "result": [ + { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "type": "A", + "name": "www.example.com", + "content": "198.51.100.4", + "proxiable": true, + "proxied": true, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": [ + "tag1", + "tag2extended" + ] + } + ], + "result_info": { + "count": 1, + "page": 2, + "per_page": 1, + "total_count": 2, + "total_pages": 2 + } +} From ff35c3cb230279bdce8ec157112155a9668e0dfe Mon Sep 17 00:00:00 2001 From: Artur Rodrigues Date: Mon, 9 Jan 2023 10:01:59 +0000 Subject: [PATCH 084/370] Add changelog entry Signed-off-by: Artur Rodrigues --- .changelog/1171.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1171.txt diff --git a/.changelog/1171.txt b/.changelog/1171.txt new file mode 100644 index 0000000000..020c63e977 --- /dev/null +++ b/.changelog/1171.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dns: Match ListDNSRecords per_page value to the API's (100) +``` From e99afaef54fedb6fa919abd8da6048410fe617a3 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 9 Jan 2023 23:17:02 +0000 Subject: [PATCH 085/370] Update CHANGELOG.md for #1172 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d18b0239a0..8768ba6a58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ENHANCEMENTS: BUG FIXES: * dns: don't send "priority" for list operations as it isn't supported and is only used for internal filtering ([#1167](https://github.com/cloudflare/cloudflare-go/issues/1167)) +* managednetworks: Update should be PUT ([#1172](https://github.com/cloudflare/cloudflare-go/issues/1172)) ## 0.58.1 (January 5th, 2023) From 99374ea5d23b4d061878202a86d628a069c23209 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 10 Jan 2023 14:09:06 +1100 Subject: [PATCH 086/370] comments cleanup --- .changelog/1171.txt | 2 +- dns.go | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.changelog/1171.txt b/.changelog/1171.txt index 020c63e977..174071f005 100644 --- a/.changelog/1171.txt +++ b/.changelog/1171.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -dns: Match ListDNSRecords per_page value to the API's (100) +dns: update default `per_page` attribute to 100 records ``` diff --git a/dns.go b/dns.go index 99aec41ded..7f86733a97 100644 --- a/dns.go +++ b/dns.go @@ -156,9 +156,7 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, para } // ListDNSRecords returns a slice of DNS records for the given zone -// identifier. If params doesn't include any pagination (ResultInfo) -// options, auto pagination is performed with the default page size -// of 100 records per request. +// identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, params ListDNSRecordsParams) ([]DNSRecord, *ResultInfo, error) { From 283c70fd50903bb4139ca52d7d73e10eb7004194 Mon Sep 17 00:00:00 2001 From: favonia Date: Sun, 8 Jan 2023 15:56:19 -0600 Subject: [PATCH 087/370] dns: clean up UpdateDNSRecordParams and avoid record lookup This commit does not mean all the remaining fields should be there; I did not touch the ones I do not understand. --- cmd/flarectl/dns.go | 14 ++- dns.go | 43 ++------- dns_test.go | 223 +------------------------------------------- 3 files changed, 18 insertions(+), 262 deletions(-) diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index aa7617e022..fd5a528163 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -112,14 +112,12 @@ func dnsCreateOrUpdate(c *cli.Context) error { } resp = &cloudflare.DNSRecordResponse{ Result: cloudflare.DNSRecord{ - ID: rr.ID, - Name: rr.Name, - Type: rr.Type, - Content: rr.Content, - TTL: rr.TTL, - Proxiable: rr.Proxiable, - Proxied: &proxy, - Locked: rr.Locked, + ID: rr.ID, + Name: rr.Name, + Type: rr.Type, + Content: rr.Content, + TTL: rr.TTL, + Proxied: &proxy, }, } } diff --git a/dns.go b/dns.go index 473f9ae7de..5407a29d48 100644 --- a/dns.go +++ b/dns.go @@ -63,23 +63,16 @@ type ListDNSRecordsParams struct { } type UpdateDNSRecordParams struct { - CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` - Type string `json:"type,omitempty" url:"type,omitempty"` - Name string `json:"name,omitempty" url:"name,omitempty"` - Content string `json:"content,omitempty" url:"content,omitempty"` - Meta interface{} `json:"meta,omitempty"` - Data interface{} `json:"data,omitempty"` // data returned by: SRV, LOC - ID string `json:"id,omitempty"` - ZoneID string `json:"zone_id,omitempty"` - ZoneName string `json:"zone_name,omitempty"` - Priority *uint16 `json:"priority,omitempty"` - TTL int `json:"ttl,omitempty"` - Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` - Proxiable bool `json:"proxiable,omitempty"` - Locked bool `json:"locked,omitempty"` - Comment string `json:"comment,omitempty" url:"comment,omitempty"` - Tags []string `json:"tags,omitempty"` + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` + Content string `json:"content,omitempty"` + Data interface{} `json:"data,omitempty"` // data for: SRV, LOC + ID string `json:"-"` + Priority *uint16 `json:"-"` // internal use only + TTL int `json:"ttl,omitempty"` + Proxied *bool `json:"proxied,omitempty"` + Comment string `json:"comment,omitempty"` + Tags []string `json:"tags,omitempty"` } // DNSListResponse represents the response from the list DNS records endpoint. @@ -231,22 +224,6 @@ func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, para params.Name = toUTS46ASCII(params.Name) - // Populate the record name from the existing one if the update didn't - // specify it. - if params.Name == "" || params.Type == "" { - rec, err := api.GetDNSRecord(ctx, rc, params.ID) - if err != nil { - return err - } - - if params.Name == "" { - params.Name = rec.Name - } - if params.Type == "" { - params.Type = rec.Type - } - } - uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, params.ID) res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { diff --git a/dns_test.go b/dns_test.go index 08a55e4eb8..06e676d00c 100644 --- a/dns_test.go +++ b/dns_test.go @@ -422,7 +422,7 @@ func TestUpdateDNSRecord(t *testing.T) { input := DNSRecord{ ID: "372e67954025e0ba6aaa6d586b9e0b59", Type: "A", - Name: "example.com", + Name: "xn--138h.example.com", Content: "198.51.100.4", TTL: 120, Proxied: &proxied, @@ -434,6 +434,7 @@ func TestUpdateDNSRecord(t *testing.T) { var v DNSRecord err := json.NewDecoder(r.Body).Decode(&v) require.NoError(t, err) + v.ID = "372e67954025e0ba6aaa6d586b9e0b59" assert.Equal(t, input, v) w.Header().Set("content-type", "application/json") @@ -473,226 +474,6 @@ func TestUpdateDNSRecord(t *testing.T) { err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ ID: dnsRecordID, Type: "A", - Name: "example.com", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - }) - require.NoError(t, err) -} - -func TestUpdateDNSRecordWithoutName(t *testing.T) { - setup() - defer teardown() - - proxied := false - - asciiInput := DNSRecord{ - ID: "372e67954025e0ba6aaa6d586b9e0b59", - Name: "xn--138h.example.com", - Type: "A", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - } - - handleUpdateDNSRecord := func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) - - var v DNSRecord - err := json.NewDecoder(r.Body).Decode(&v) - require.NoError(t, err) - assert.Equal(t, asciiInput, v) - - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "372e67954025e0ba6aaa6d586b9e0b59", - "type": "A", - "name": "xn--138h.example.com", - "content": "198.51.100.4", - "proxiable": true, - "proxied": false, - "ttl": 120, - "locked": false, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z", - "data": {}, - "meta": { - "auto_added": true, - "source": "primary" - } - } - }`) - } - - handleDNSRecord := 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.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "372e67954025e0ba6aaa6d586b9e0b59", - "type": "A", - "name": "xn--138h.example.com", - "content": "198.51.100.4", - "proxiable": true, - "proxied": false, - "ttl": 120, - "locked": false, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z", - "data": {}, - "meta": { - "auto_added": true, - "source": "primary" - } - } - }`) - } - - handler := func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { - handleDNSRecord(w, r) - return - } - - if r.Method == http.MethodPatch { - handleUpdateDNSRecord(w, r) - return - } - - assert.Failf(t, "Expected method 'GET' or `PATCH`, got %s", r.Method) - } - - dnsRecordID := "372e67954025e0ba6aaa6d586b9e0b59" - - mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{}) - assert.Equal(t, ErrMissingZoneID, err) - - err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ - ID: dnsRecordID, - Type: "A", - Name: "xn--138h.example.com", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - }) - require.NoError(t, err) -} - -func TestUpdateDNSRecordWithoutType(t *testing.T) { - setup() - defer teardown() - - proxied := false - - completedASCIIInput := DNSRecord{ - Name: "xn--138h.example.com", - Type: "A", - Content: "198.51.100.4", - TTL: 120, - Proxied: &proxied, - ID: "372e67954025e0ba6aaa6d586b9e0b59", - } - - handleUpdateDNSRecord := func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) - - var v DNSRecord - err := json.NewDecoder(r.Body).Decode(&v) - require.NoError(t, err) - assert.Equal(t, completedASCIIInput, v) - - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "372e67954025e0ba6aaa6d586b9e0b59", - "type": "A", - "name": "example.com", - "content": "198.51.100.4", - "proxiable": true, - "proxied": false, - "ttl": 120, - "locked": false, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z", - "data": {}, - "meta": { - "auto_added": true, - "source": "primary" - } - } - }`) - } - - handleDNSRecord := 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.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "372e67954025e0ba6aaa6d586b9e0b59", - "type": "A", - "name": "example.com", - "content": "198.51.100.4", - "proxiable": true, - "proxied": false, - "ttl": 120, - "locked": false, - "zone_id": "d56084adb405e0b7e32c52321bf07be6", - "zone_name": "example.com", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z", - "data": {}, - "meta": { - "auto_added": true, - "source": "primary" - } - } - }`) - } - - handler := func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { - handleDNSRecord(w, r) - return - } - - if r.Method == http.MethodPatch { - handleUpdateDNSRecord(w, r) - return - } - - assert.Failf(t, "Expected method 'GET' or `PATCH`, got %s", r.Method) - } - - dnsRecordID := "372e67954025e0ba6aaa6d586b9e0b59" - - mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ - ID: dnsRecordID, Name: "😺.example.com", Content: "198.51.100.4", TTL: 120, From c22a79b3cccff59bf3a90457e4d6544290b12f81 Mon Sep 17 00:00:00 2001 From: favonia Date: Sun, 8 Jan 2023 16:44:36 -0600 Subject: [PATCH 088/370] dns: add changelog entry --- .changelog/1170.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/1170.txt diff --git a/.changelog/1170.txt b/.changelog/1170.txt new file mode 100644 index 0000000000..73133dadcd --- /dev/null +++ b/.changelog/1170.txt @@ -0,0 +1,7 @@ +```release-note:note +dns: clean up UpdateDNSRecordParams and skip record lookup +``` + +```release-note:breaking-change +dns: many fields have been removed from UpdateDNSRecordParams +``` From 672d41e39cc1cc81a9665c8bd298e8d0324be057 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 10 Jan 2023 14:11:23 +1100 Subject: [PATCH 089/370] update CHANGELOG message --- .changelog/1170.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1170.txt b/.changelog/1170.txt index 73133dadcd..76763b01a1 100644 --- a/.changelog/1170.txt +++ b/.changelog/1170.txt @@ -1,5 +1,5 @@ ```release-note:note -dns: clean up UpdateDNSRecordParams and skip record lookup +dns: remove additional lookup from `Update` operations when `Name` or `Type` was omitted ``` ```release-note:breaking-change From 095641ffb4c607f4f950812046eec4685814ebbb Mon Sep 17 00:00:00 2001 From: favonia Date: Mon, 9 Jan 2023 22:12:11 -0600 Subject: [PATCH 090/370] update CHANGELOG message --- .changelog/1170.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1170.txt b/.changelog/1170.txt index 76763b01a1..0a3b278ea8 100644 --- a/.changelog/1170.txt +++ b/.changelog/1170.txt @@ -3,5 +3,5 @@ dns: remove additional lookup from `Update` operations when `Name` or `Type` was ``` ```release-note:breaking-change -dns: many fields have been removed from UpdateDNSRecordParams +dns: remove these read-only fields from `UpdateDNSRecordParams`: `CreatedOn`, `ModifiedOn`, `Meta`, `ZoneID`, `ZoneName`, `Proxiable`, and `Locked` ``` From c58af05f2dd1995a0df99c18cc6f686277823730 Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 02:01:18 -0600 Subject: [PATCH 091/370] dns: return a dedicated error when record ID is empty --- dns.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dns.go b/dns.go index 5407a29d48..df3f8b99dc 100644 --- a/dns.go +++ b/dns.go @@ -3,6 +3,7 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" "time" @@ -192,6 +193,9 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, param return records, &listResponse.ResultInfo, nil } +// ErrMissingDNSRecordID is for when DNS record ID is needed but not given. +var ErrMissingDNSRecordID = errors.New("required DNS record ID missing") + // GetDNSRecord returns a single DNS record for the given zone & record // identifiers. // @@ -200,6 +204,10 @@ func (api *API) GetDNSRecord(ctx context.Context, rc *ResourceContainer, recordI if rc.Identifier == "" { return DNSRecord{}, ErrMissingZoneID } + if recordID == "" { + return DNSRecord{}, ErrMissingDNSRecordID + } + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -221,6 +229,9 @@ func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, para if rc.Identifier == "" { return ErrMissingZoneID } + if params.ID == "" { + return ErrMissingDNSRecordID + } params.Name = toUTS46ASCII(params.Name) From ff642228fb83a44428b699e25fdb330c176187a8 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 10 Jan 2023 08:13:22 +0000 Subject: [PATCH 092/370] Update CHANGELOG.md for #1170 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8768ba6a58..21fb72a9f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## 0.59.0 (Unreleased) +BREAKING CHANGES: + +* dns: remove these read-only fields from `UpdateDNSRecordParams`: `CreatedOn`, `ModifiedOn`, `Meta`, `ZoneID`, `ZoneName`, `Proxiable`, and `Locked` ([#1170](https://github.com/cloudflare/cloudflare-go/issues/1170)) + +NOTES: + +* dns: remove additional lookup from `Update` operations when `Name` or `Type` was omitted ([#1170](https://github.com/cloudflare/cloudflare-go/issues/1170)) + ENHANCEMENTS: * access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) From cf51b38ad2e7402bf872d3513738d18029e5c2c8 Mon Sep 17 00:00:00 2001 From: Artur Rodrigues Date: Tue, 10 Jan 2023 08:55:56 +0000 Subject: [PATCH 093/370] dns_test: default case for unexpected pages As per @favonia suggestion --- dns_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dns_test.go b/dns_test.go index 4c2fb94957..8e81159e71 100644 --- a/dns_test.go +++ b/dns_test.go @@ -361,6 +361,9 @@ func TestListDNSRecordsPagination(t *testing.T) { case "2": response = loadFixture("dns", "list_page_2") page2Called = true + default: + assert.Failf(t, "Unexpeted page requested: %s", page) + return } fmt.Fprint(w, response) } From 40468f73361d625db653600274ecca2ff2731b8a Mon Sep 17 00:00:00 2001 From: Artur Rodrigues Date: Tue, 10 Jan 2023 08:57:13 +0000 Subject: [PATCH 094/370] Got fmt --- dns.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns.go b/dns.go index 7f86733a97..eaad5250cf 100644 --- a/dns.go +++ b/dns.go @@ -156,7 +156,7 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, para } // ListDNSRecords returns a slice of DNS records for the given zone -// identifier. +// identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, params ListDNSRecordsParams) ([]DNSRecord, *ResultInfo, error) { From f59c0fcdcda5c1511b5b02a72397bb18ac8de786 Mon Sep 17 00:00:00 2001 From: Artur Rodrigues Date: Tue, 10 Jan 2023 09:04:50 +0000 Subject: [PATCH 095/370] dns: Shorten docstring --- dns.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dns.go b/dns.go index eaad5250cf..c2e8b886e6 100644 --- a/dns.go +++ b/dns.go @@ -155,8 +155,7 @@ func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, para return recordResp, nil } -// ListDNSRecords returns a slice of DNS records for the given zone -// identifier. +// ListDNSRecords returns a slice of DNS records for the given zone identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, params ListDNSRecordsParams) ([]DNSRecord, *ResultInfo, error) { From 64070013c67d0a535836398d7364c17ba87a1ceb Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 10 Jan 2023 09:32:05 +0000 Subject: [PATCH 096/370] Update CHANGELOG.md for #1171 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21fb72a9f7..ce76453a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ NOTES: ENHANCEMENTS: * access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) +* dns: update default `per_page` attribute to 100 records ([#1171](https://github.com/cloudflare/cloudflare-go/issues/1171)) BUG FIXES: From 62176334bb56c37f5f050822a50f500a16af8e93 Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 08:15:10 -0600 Subject: [PATCH 097/370] dns: check whether recordID is empty in DeleteDNSRecord --- dns.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dns.go b/dns.go index ba582532d3..c2943ed230 100644 --- a/dns.go +++ b/dns.go @@ -259,6 +259,10 @@ func (api *API) DeleteDNSRecord(ctx context.Context, rc *ResourceContainer, reco if rc.Identifier == "" { return ErrMissingZoneID } + if recordID == "" { + return ErrMissingDNSRecordID + } + uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, recordID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { From 15bbe0ffcaa0bf0922bd8dac07f0f727bb25fc3b Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 08:25:07 -0600 Subject: [PATCH 098/370] dns: test empty DNS record IDs and use ErrorIs for comparing errors --- dns_test.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/dns_test.go b/dns_test.go index d0a301939d..8cd08386ce 100644 --- a/dns_test.go +++ b/dns_test.go @@ -139,7 +139,7 @@ func TestCreateDNSRecord(t *testing.T) { } _, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(""), CreateDNSRecordParams{}) - assert.Equal(t, ErrMissingZoneID, err) + assert.ErrorIs(t, err, ErrMissingZoneID) actual, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), CreateDNSRecordParams{ Type: "A", @@ -230,7 +230,7 @@ func TestListDNSRecords(t *testing.T) { }} _, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(""), ListDNSRecordsParams{}) - assert.Equal(t, ErrMissingZoneID, err) + assert.ErrorIs(t, err, ErrMissingZoneID) actual, _, err := client.ListDNSRecords(context.Background(), ZoneIdentifier(testZoneID), ListDNSRecordsParams{ Name: "😺.example.com", @@ -377,7 +377,7 @@ func TestListDNSRecordsPagination(t *testing.T) { assert.Len(t, actual, 2) } -func TestDNSRecord(t *testing.T) { +func TestGetDNSRecord(t *testing.T) { setup() defer teardown() @@ -442,7 +442,10 @@ func TestDNSRecord(t *testing.T) { } _, err := client.GetDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID) - assert.Equal(t, ErrMissingZoneID, err) + assert.ErrorIs(t, err, ErrMissingZoneID) + + _, err = client.GetDNSRecord(context.Background(), ZoneIdentifier(testZoneID), "") + assert.ErrorIs(t, err, ErrMissingDNSRecordID) actual, err := client.GetDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID) require.NoError(t, err) @@ -504,8 +507,11 @@ func TestUpdateDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{}) - assert.Equal(t, ErrMissingZoneID, err) + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{ID: dnsRecordID}) + assert.ErrorIs(t, err, ErrMissingZoneID) + + err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{}) + assert.ErrorIs(t, err, ErrMissingDNSRecordID) err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ ID: dnsRecordID, @@ -541,7 +547,10 @@ func TestDeleteDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) err := client.DeleteDNSRecord(context.Background(), ZoneIdentifier(""), dnsRecordID) - assert.Equal(t, ErrMissingZoneID, err) + assert.ErrorIs(t, err, ErrMissingZoneID) + + err = client.DeleteDNSRecord(context.Background(), ZoneIdentifier(testZoneID), "") + assert.ErrorIs(t, err, ErrMissingDNSRecordID) err = client.DeleteDNSRecord(context.Background(), ZoneIdentifier(testZoneID), dnsRecordID) require.NoError(t, err) From 78aba93f93f936fbde5f29c9ec9138d118521824 Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 08:34:37 -0600 Subject: [PATCH 099/370] add CHANGELOG message --- .changelog/1174.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1174.txt diff --git a/.changelog/1174.txt b/.changelog/1174.txt new file mode 100644 index 0000000000..686be2ad19 --- /dev/null +++ b/.changelog/1174.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dns: `GetDNSRecord`, `UpdateDNSRecord` and `DeleteDNSRecord` now return the new, dedicated error `ErrMissingDNSRecordID` when an empty DNS record ID is given. +``` From ff07123e6808e8c0ed8c1ce070d9e5932340e82e Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 10 Jan 2023 20:43:27 +0000 Subject: [PATCH 100/370] Update CHANGELOG.md for #1174 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce76453a81..683c5514d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ NOTES: ENHANCEMENTS: * access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) +* dns: `GetDNSRecord`, `UpdateDNSRecord` and `DeleteDNSRecord` now return the new, dedicated error `ErrMissingDNSRecordID` when an empty DNS record ID is given. ([#1174](https://github.com/cloudflare/cloudflare-go/issues/1174)) * dns: update default `per_page` attribute to 100 records ([#1171](https://github.com/cloudflare/cloudflare-go/issues/1171)) BUG FIXES: From 82578fbf1c4801bae147eaaef98bca0d6fa15d33 Mon Sep 17 00:00:00 2001 From: favonia Date: Mon, 9 Jan 2023 22:07:27 -0600 Subject: [PATCH 101/370] dns: clean up ListDNSRecordsParams --- dns.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/dns.go b/dns.go index c2943ed230..9eaa52dc14 100644 --- a/dns.go +++ b/dns.go @@ -47,18 +47,17 @@ const ( ) type ListDNSRecordsParams struct { - CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` - Type string `json:"type,omitempty" url:"type,omitempty"` - Name string `json:"name,omitempty" url:"name,omitempty"` - Content string `json:"content,omitempty" url:"content,omitempty"` - Proxied *bool `json:"proxied,omitempty" url:"proxied,omitempty"` - Comment string `json:"comment,omitempty" url:"comment,omitempty"` - Tags []string `json:"tags,omitempty"` - Order string `url:"order,omitempty"` - Direction ListDirection `url:"direction,omitempty"` - Match string `url:"match,omitempty"` - Priority *uint16 `url:"-"` + Type string `url:"type,omitempty"` + Name string `url:"name,omitempty"` + Content string `url:"content,omitempty"` + Proxied *bool `url:"proxied,omitempty"` + Comment string `url:"comment,omitempty"` + Tags []string `url:"tag,omitempty"` // potentially multiple `tag=` + TagMatch string `url:"tag-match,omitempty"` + Order string `url:"order,omitempty"` + Direction ListDirection `url:"direction,omitempty"` + Match string `url:"match,omitempty"` + Priority *uint16 `url:"-"` ResultInfo } @@ -157,9 +156,7 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, param return nil, nil, ErrMissingZoneID } - if params.Name != "" { - params.Name = toUTS46ASCII(params.Name) - } + params.Name = toUTS46ASCII(params.Name) autoPaginate := true if params.PerPage >= 1 || params.Page >= 1 { From 970fb2141e1ca55a6d68688fdb7c1bfded2e0b59 Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 02:48:00 -0600 Subject: [PATCH 102/370] dns: add CHANGELOG messages --- .changelog/1173.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changelog/1173.txt diff --git a/.changelog/1173.txt b/.changelog/1173.txt new file mode 100644 index 0000000000..403a2feff3 --- /dev/null +++ b/.changelog/1173.txt @@ -0,0 +1,11 @@ +```release-note:bug +dns: the field `Tags` in `ListDNSRecordsParams` was not correctly serialized into URL queries +``` + +```release-note:enhancement +dns: the URL parameter `tag-match` for listing DNS records is now supported as the field `TagMatch` in `ListDNSRecordsParams` +``` + +```release-note:breaking-change +dns: the fields `CreatedOn` and `ModifiedOn` are removed from `ListDNSRecordsParams` +``` From 15b15452e4030120c02d03d3344a9b0814573317 Mon Sep 17 00:00:00 2001 From: favonia Date: Tue, 10 Jan 2023 08:01:48 -0600 Subject: [PATCH 103/370] dns: add test cases for tags --- dns_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dns_test.go b/dns_test.go index 8cd08386ce..086f32adee 100644 --- a/dns_test.go +++ b/dns_test.go @@ -261,6 +261,8 @@ func TestListDNSRecordsSearch(t *testing.T) { assert.Equal(t, "1", r.URL.Query().Get("page")) assert.Equal(t, "type", r.URL.Query().Get("order")) assert.Equal(t, "asc", r.URL.Query().Get("direction")) + assert.Equal(t, "any", r.URL.Query().Get("tag-match")) + assert.ElementsMatch(t, []string{"tag1", "tag2"}, r.URL.Query()["tag"]) w.Header().Set("content-type", "application/json") fmt.Fprint(w, `{ @@ -334,6 +336,8 @@ func TestListDNSRecordsSearch(t *testing.T) { Name: "example.com", Type: "A", Content: "198.51.100.4", + TagMatch: "any", + Tags: []string{"tag1", "tag2"}, }) require.NoError(t, err) assert.Equal(t, 2000, resultInfo.Total) From fd77811d728750ea5295235298e35b01a99ab15b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 11 Jan 2023 22:09:10 +0000 Subject: [PATCH 104/370] Update CHANGELOG.md for #1173 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 683c5514d0..385b6ab0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ BREAKING CHANGES: * dns: remove these read-only fields from `UpdateDNSRecordParams`: `CreatedOn`, `ModifiedOn`, `Meta`, `ZoneID`, `ZoneName`, `Proxiable`, and `Locked` ([#1170](https://github.com/cloudflare/cloudflare-go/issues/1170)) +* dns: the fields `CreatedOn` and `ModifiedOn` are removed from `ListDNSRecordsParams` ([#1173](https://github.com/cloudflare/cloudflare-go/issues/1173)) NOTES: @@ -12,11 +13,14 @@ ENHANCEMENTS: * access_organization: add user_seat_expiration_inactive_time field ([#1159](https://github.com/cloudflare/cloudflare-go/issues/1159)) * dns: `GetDNSRecord`, `UpdateDNSRecord` and `DeleteDNSRecord` now return the new, dedicated error `ErrMissingDNSRecordID` when an empty DNS record ID is given. ([#1174](https://github.com/cloudflare/cloudflare-go/issues/1174)) +* dns: the URL parameter `tag-match` for listing DNS records is now supported as the field `TagMatch` in `ListDNSRecordsParams` ([#1173](https://github.com/cloudflare/cloudflare-go/issues/1173)) * dns: update default `per_page` attribute to 100 records ([#1171](https://github.com/cloudflare/cloudflare-go/issues/1171)) +* teams_rules: adds support for Egress Policies ([#1142](https://github.com/cloudflare/cloudflare-go/issues/1142)) BUG FIXES: * dns: don't send "priority" for list operations as it isn't supported and is only used for internal filtering ([#1167](https://github.com/cloudflare/cloudflare-go/issues/1167)) +* dns: the field `Tags` in `ListDNSRecordsParams` was not correctly serialized into URL queries ([#1173](https://github.com/cloudflare/cloudflare-go/issues/1173)) * managednetworks: Update should be PUT ([#1172](https://github.com/cloudflare/cloudflare-go/issues/1172)) ## 0.58.1 (January 5th, 2023) From 06e2a47ba57ce7fd25a36c57b85de1b84ba827dd Mon Sep 17 00:00:00 2001 From: "S. Brent Faulkner" Date: Thu, 12 Jan 2023 10:42:19 -0500 Subject: [PATCH 105/370] Add support for compatibility flags when uploading worker --- workers.go | 19 +++++++++++------- workers_test.go | 51 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/workers.go b/workers.go index b834c58b17..0f7e24c158 100644 --- a/workers.go +++ b/workers.go @@ -35,6 +35,9 @@ type CreateWorkerParams struct { // Bindings should be a map where the keys are the binding name, and the // values are the binding content Bindings map[string]WorkerBinding + + // CompatibilityFlags are the names of features from upcoming features of the Workers runtime. + CompatibilityFlags []string } // WorkerScriptParams provides a worker script and the associated bindings. @@ -224,7 +227,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params err error ) - if params.Module || params.Logpush != nil || len(params.Bindings) > 0 { + if params.Module || params.Logpush != nil || len(params.Bindings) > 0 || len(params.CompatibilityFlags) > 0 { contentType, body, err = formatMultipartBody(params) if err != nil { return WorkerScriptResponse{}, err @@ -258,13 +261,15 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) { // Write metadata part var scriptPartName string meta := struct { - BodyPart string `json:"body_part,omitempty"` - MainModule string `json:"main_module,omitempty"` - Bindings []workerBindingMeta `json:"bindings"` - Logpush *bool `json:"logpush,omitempty"` + BodyPart string `json:"body_part,omitempty"` + MainModule string `json:"main_module,omitempty"` + Bindings []workerBindingMeta `json:"bindings"` + Logpush *bool `json:"logpush,omitempty"` + CompatibilityFlags []string `json:"compatibility_flags,omitempty"` }{ - Bindings: make([]workerBindingMeta, 0, len(params.Bindings)), - Logpush: params.Logpush, + Bindings: make([]workerBindingMeta, 0, len(params.Bindings)), + Logpush: params.Logpush, + CompatibilityFlags: params.CompatibilityFlags, } if params.Module { diff --git a/workers_test.go b/workers_test.go index c76b7d053d..af9b4ed561 100644 --- a/workers_test.go +++ b/workers_test.go @@ -275,9 +275,10 @@ func getFileDetails(r *http.Request, key string) (*multipart.FileHeader, error) } type multipartUpload struct { - Script string - BindingMeta map[string]workerBindingMeta - Logpush *bool + Script string + BindingMeta map[string]workerBindingMeta + Logpush *bool + CompatibilityFlags []string } func parseMultipartUpload(r *http.Request) (multipartUpload, error) { @@ -288,10 +289,11 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { } var metadata struct { - BodyPart string `json:"body_part,omitempty"` - MainModule string `json:"main_module,omitempty"` - Bindings []workerBindingMeta `json:"bindings"` - Logpush *bool `json:"logpush,omitempty"` + BodyPart string `json:"body_part,omitempty"` + MainModule string `json:"main_module,omitempty"` + Bindings []workerBindingMeta `json:"bindings"` + Logpush *bool `json:"logpush,omitempty"` + CompatibilityFlags []string `json:"compatibility_flags,omitempty"` } err = json.Unmarshal(mdBytes, &metadata) if err != nil { @@ -318,9 +320,10 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { } return multipartUpload{ - Script: string(script), - BindingMeta: bindingMeta, - Logpush: metadata.Logpush, + Script: string(script), + BindingMeta: bindingMeta, + Logpush: metadata.Logpush, + CompatibilityFlags: metadata.CompatibilityFlags, }, nil } @@ -859,3 +862,31 @@ func TestUploadWorker_WithLogpush(t *testing.T) { assert.Equal(t, want, res) } } + +func TestUploadWorker_WithCompatibilityFlags(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) + + mpUpload, err := parseMultipartUpload(r) + assert.NoError(t, err) + + expectedCompatibilityFlags := []string{"formdata_parser_supports_files"} + + assert.Equal(t, workerScript, mpUpload.Script) + assert.Equal(t, expectedCompatibilityFlags, mpUpload.CompatibilityFlags) + + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, uploadWorkerResponseData) + } + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) + + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + ScriptName: "bar", + Script: workerScript, + CompatibilityFlags: []string{"formdata_parser_supports_files"}, + }) + assert.NoError(t, err) +} From 468a02dae4c1b32fd05ddeca3ee18fa7d204cbda Mon Sep 17 00:00:00 2001 From: "S. Brent Faulkner" Date: Thu, 12 Jan 2023 10:56:23 -0500 Subject: [PATCH 106/370] Add support for compatibility date --- workers.go | 13 +++++++++++-- workers_test.go | 14 ++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/workers.go b/workers.go index 0f7e24c158..0a983bdc3c 100644 --- a/workers.go +++ b/workers.go @@ -36,7 +36,14 @@ type CreateWorkerParams struct { // values are the binding content Bindings map[string]WorkerBinding - // CompatibilityFlags are the names of features from upcoming features of the Workers runtime. + // CompatibilityDate is a date in the form yyyy-mm-dd, + // which will be used to determine which version of the Workers runtime is used. + // https://developers.cloudflare.com/workers/platform/compatibility-dates/ + CompatibilityDate string + + // CompatibilityFlags are the names of features of the Workers runtime to be enabled or disabled, + // usually used together with CompatibilityDate. + // https://developers.cloudflare.com/workers/platform/compatibility-dates/#compatibility-flags CompatibilityFlags []string } @@ -227,7 +234,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params err error ) - if params.Module || params.Logpush != nil || len(params.Bindings) > 0 || len(params.CompatibilityFlags) > 0 { + if params.Module || params.Logpush != nil || len(params.Bindings) > 0 || params.CompatibilityDate != "" || len(params.CompatibilityFlags) > 0 { contentType, body, err = formatMultipartBody(params) if err != nil { return WorkerScriptResponse{}, err @@ -265,10 +272,12 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) { MainModule string `json:"main_module,omitempty"` Bindings []workerBindingMeta `json:"bindings"` Logpush *bool `json:"logpush,omitempty"` + CompatibilityDate string `json:"compatibility_date,omitempty"` CompatibilityFlags []string `json:"compatibility_flags,omitempty"` }{ Bindings: make([]workerBindingMeta, 0, len(params.Bindings)), Logpush: params.Logpush, + CompatibilityDate: params.CompatibilityDate, CompatibilityFlags: params.CompatibilityFlags, } diff --git a/workers_test.go b/workers_test.go index af9b4ed561..d04cbef50c 100644 --- a/workers_test.go +++ b/workers_test.go @@ -278,6 +278,7 @@ type multipartUpload struct { Script string BindingMeta map[string]workerBindingMeta Logpush *bool + CompatibilityDate string CompatibilityFlags []string } @@ -293,6 +294,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { MainModule string `json:"main_module,omitempty"` Bindings []workerBindingMeta `json:"bindings"` Logpush *bool `json:"logpush,omitempty"` + CompatibilityDate string `json:"compatibility_date,omitempty"` CompatibilityFlags []string `json:"compatibility_flags,omitempty"` } err = json.Unmarshal(mdBytes, &metadata) @@ -323,6 +325,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) { Script: string(script), BindingMeta: bindingMeta, Logpush: metadata.Logpush, + CompatibilityDate: metadata.CompatibilityDate, CompatibilityFlags: metadata.CompatibilityFlags, }, nil } @@ -867,16 +870,18 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) { setup() defer teardown() + compatibilityDate := time.Now().Format("2006-01-02") + compatibilityFlags := []string{"formdata_parser_supports_files"} + 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) - expectedCompatibilityFlags := []string{"formdata_parser_supports_files"} - assert.Equal(t, workerScript, mpUpload.Script) - assert.Equal(t, expectedCompatibilityFlags, mpUpload.CompatibilityFlags) + assert.Equal(t, compatibilityDate, mpUpload.CompatibilityDate) + assert.Equal(t, compatibilityFlags, mpUpload.CompatibilityFlags) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, uploadWorkerResponseData) @@ -886,7 +891,8 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) { _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ ScriptName: "bar", Script: workerScript, - CompatibilityFlags: []string{"formdata_parser_supports_files"}, + CompatibilityDate: compatibilityDate, + CompatibilityFlags: compatibilityFlags, }) assert.NoError(t, err) } From 5161538b3b812854523902ad6545e2173178ee5b Mon Sep 17 00:00:00 2001 From: "S. Brent Faulkner" Date: Thu, 12 Jan 2023 12:00:30 -0500 Subject: [PATCH 107/370] add changelog --- .changelog/1177.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1177.txt diff --git a/.changelog/1177.txt b/.changelog/1177.txt new file mode 100644 index 0000000000..bb9f8d81e3 --- /dev/null +++ b/.changelog/1177.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +workers: Add support for compatibility_date and compatibility_flags when upoading a worker script +``` From 09767265edf6a24848bf4890557caf64f08dee55 Mon Sep 17 00:00:00 2001 From: "S. Brent Faulkner" Date: Thu, 12 Jan 2023 12:02:51 -0500 Subject: [PATCH 108/370] lint --- workers_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers_test.go b/workers_test.go index d04cbef50c..b9b7fc2d65 100644 --- a/workers_test.go +++ b/workers_test.go @@ -884,7 +884,7 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) { assert.Equal(t, compatibilityFlags, mpUpload.CompatibilityFlags) w.Header().Set("content-type", "application/json") - fmt.Fprintf(w, uploadWorkerResponseData) + fmt.Fprint(w, uploadWorkerResponseData) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) From 80e24909d758c4d7f864fa5557106b8b190d38b2 Mon Sep 17 00:00:00 2001 From: Russell Kerns Date: Thu, 12 Jan 2023 14:26:30 -0600 Subject: [PATCH 109/370] AUTH-4867 add scim_config to IDPs --- .changelog/1178.txt | 3 +++ access_identity_provider.go | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 .changelog/1178.txt diff --git a/.changelog/1178.txt b/.changelog/1178.txt new file mode 100644 index 0000000000..08101c917d --- /dev/null +++ b/.changelog/1178.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access_identity_provider: add scim_config field +``` \ No newline at end of file diff --git a/access_identity_provider.go b/access_identity_provider.go index fb986b4b23..0b61ea9eee 100644 --- a/access_identity_provider.go +++ b/access_identity_provider.go @@ -9,10 +9,11 @@ import ( // AccessIdentityProvider is the structure of the provider object. type AccessIdentityProvider struct { - ID string `json:"id,omitempty"` - Name string `json:"name"` - Type string `json:"type"` - Config AccessIdentityProviderConfiguration `json:"config"` + ID string `json:"id,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Config AccessIdentityProviderConfiguration `json:"config"` + ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"` } // AccessIdentityProviderConfiguration is the combined structure of *all* @@ -44,6 +45,14 @@ type AccessIdentityProviderConfiguration struct { PKCEEnabled *bool `json:"pkce_enabled,omitempty"` } +type AccessIdentityProviderScimConfiguration struct { + Enabled bool `json:"enabled,omitempty"` + Secret string `json:"secret,omitempty"` + UserDeprovision bool `json:"user_deprovision,omitempty"` + SeatDeprovision bool `json:"seat_deprovision,omitempty"` + GroupMemberDeprovision bool `json:"group_member_deprovision,omitempty"` +} + // AccessIdentityProvidersListResponse is the API response for multiple // Access Identity Providers. type AccessIdentityProvidersListResponse struct { From 4ec00432f931717f0c166c1962a2913d6947b33e Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 12 Jan 2023 23:51:16 +0000 Subject: [PATCH 110/370] Update CHANGELOG.md for #1177 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 385b6ab0b7..d11e636e98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ENHANCEMENTS: * dns: the URL parameter `tag-match` for listing DNS records is now supported as the field `TagMatch` in `ListDNSRecordsParams` ([#1173](https://github.com/cloudflare/cloudflare-go/issues/1173)) * dns: update default `per_page` attribute to 100 records ([#1171](https://github.com/cloudflare/cloudflare-go/issues/1171)) * teams_rules: adds support for Egress Policies ([#1142](https://github.com/cloudflare/cloudflare-go/issues/1142)) +* workers: Add support for compatibility_date and compatibility_flags when upoading a worker script ([#1177](https://github.com/cloudflare/cloudflare-go/issues/1177)) BUG FIXES: From f2c7757dc28bfde2e203fd991b3d58ae4d91d54d Mon Sep 17 00:00:00 2001 From: Josh Wheeler Date: Wed, 11 Jan 2023 15:02:15 -0600 Subject: [PATCH 111/370] Add queue binding type --- workers_bindings.go | 36 ++++++++++++++++++++++++++++++++++++ workers_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/workers_bindings.go b/workers_bindings.go index 9631065892..11f4ba7cd0 100644 --- a/workers_bindings.go +++ b/workers_bindings.go @@ -39,6 +39,8 @@ const ( WorkerR2BucketBindingType WorkerBindingType = "r2_bucket" // WorkerAnalyticsEngineBindingType is the type for Analytics Engine dataset bindings. WorkerAnalyticsEngineBindingType WorkerBindingType = "analytics_engine" + // WorkerQueueBindingType is the type for queue bindings. + WorkerQueueBindingType WorkerBindingType = "queue" ) type ListWorkerBindingsParams struct { @@ -309,6 +311,34 @@ func (b WorkerAnalyticsEngineBinding) serialize(bindingName string) (workerBindi }, nil, nil } +// WorkerQueueBinding is a binding to a Workers Queue. +// +// https://developers.cloudflare.com/workers/platform/bindings/#queue-bindings +type WorkerQueueBinding struct { + Binding string + Queue string +} + +// Type returns the type of the binding. +func (b WorkerQueueBinding) Type() WorkerBindingType { + return WorkerQueueBindingType +} + +func (b WorkerQueueBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) { + if b.Binding == "" { + return nil, nil, fmt.Errorf(`Binding name for binding "%s" cannot be empty`, bindingName) + } + if b.Queue == "" { + return nil, nil, fmt.Errorf(`Queue name for binding "%s" cannot be empty`, bindingName) + } + + return workerBindingMeta{ + "type": b.Type(), + "name": b.Binding, + "queue_name": b.Queue, + }, nil, nil +} + // Each binding that adds a part to the multipart form body will need // a unique part name so we just generate a random 128bit hex string. func getRandomPartName() string { @@ -377,6 +407,12 @@ func (api *API) ListWorkerBindings(ctx context.Context, rc *ResourceContainer, p bindingListItem.Binding = WorkerKvNamespaceBinding{ NamespaceID: namespaceID, } + case WorkerQueueBindingType: + queueName := jsonBinding["queue_name"].(string) + bindingListItem.Binding = WorkerQueueBinding{ + Binding: name, + Queue: queueName, + } case WorkerWebAssemblyBindingType: bindingListItem.Binding = WorkerWebAssemblyBinding{ Module: &bindingContentReader{ diff --git a/workers_test.go b/workers_test.go index b9b7fc2d65..348abed24a 100644 --- a/workers_test.go +++ b/workers_test.go @@ -896,3 +896,40 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) { }) assert.NoError(t, err) } + +func TestUploadWorker_WithQueueBinding(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) + + mpUpload, err := parseMultipartUpload(r) + assert.NoError(t, err) + + expectedBindings := map[string]workerBindingMeta{ + "b1": { + "name": "b1", + "type": "queue", + "queue_name": "test-queue", + }, + } + assert.Equal(t, workerScript, mpUpload.Script) + assert.Equal(t, expectedBindings, mpUpload.BindingMeta) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, uploadWorkerResponseData) + } + mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) + + _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + ScriptName: "bar", + Script: workerScript, + Bindings: map[string]WorkerBinding{ + "b1": WorkerQueueBinding{ + Binding: "b1", + Queue: "test-queue", + }, + }}) + assert.NoError(t, err) +} From d95c40c52c0fdbfe5beb8070128d4a66bdb604a1 Mon Sep 17 00:00:00 2001 From: Josh Wheeler Date: Thu, 12 Jan 2023 11:33:34 -0600 Subject: [PATCH 112/370] Add changelog entry for queues bindings --- .changelog/1176.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1176.txt diff --git a/.changelog/1176.txt b/.changelog/1176.txt new file mode 100644 index 0000000000..4d3e6d894d --- /dev/null +++ b/.changelog/1176.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +workers: script upload now supports Queues bindings +``` \ No newline at end of file From 4fd6abdecbd4ea21ac2d049a5126b738efd584d3 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sun, 15 Jan 2023 23:30:20 +0000 Subject: [PATCH 113/370] Update CHANGELOG.md for #1176 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d11e636e98..16293cdcc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ENHANCEMENTS: * dns: update default `per_page` attribute to 100 records ([#1171](https://github.com/cloudflare/cloudflare-go/issues/1171)) * teams_rules: adds support for Egress Policies ([#1142](https://github.com/cloudflare/cloudflare-go/issues/1142)) * workers: Add support for compatibility_date and compatibility_flags when upoading a worker script ([#1177](https://github.com/cloudflare/cloudflare-go/issues/1177)) +* workers: script upload now supports Queues bindings ([#1176](https://github.com/cloudflare/cloudflare-go/issues/1176)) BUG FIXES: From 2855fd429a31f71d1fe010f3403e52a297307961 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 18 Jan 2023 09:38:52 +1100 Subject: [PATCH 114/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16293cdcc1..dcaa147100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.59.0 (Unreleased) +## 0.60.0 (Unreleased) + +## 0.59.0 (January 18th, 2023) BREAKING CHANGES: From a100c1a42eea71307acafef88cddfa8fdd8a7f2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 16:01:37 +0000 Subject: [PATCH 115/370] build(deps): bump github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.23.7 to 2.24.1. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.23.7...v2.24.1) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3de4049dfb..2c79c061bb 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.23.7 + github.com/urfave/cli/v2 v2.24.1 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index ca36a2231b..f2d0e8d739 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= -github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= +github.com/urfave/cli/v2 v2.24.1/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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 475f508063f49d02d42c2230e98ed7ac1105dbba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Jan 2023 17:01:20 +0000 Subject: [PATCH 116/370] add CHANGELOG for #1180 --- .changelog/1180.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1180.txt diff --git a/.changelog/1180.txt b/.changelog/1180.txt new file mode 100644 index 0000000000..8d21a99d74 --- /dev/null +++ b/.changelog/1180.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 +``` From 64b9c7fd274244b63d91808c41a4946bc0f91593 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 23 Jan 2023 19:22:05 +0000 Subject: [PATCH 117/370] Update CHANGELOG.md for #1180 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcaa147100..d918244b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.60.0 (Unreleased) +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 ([#1180](https://github.com/cloudflare/cloudflare-go/issues/1180)) + ## 0.59.0 (January 18th, 2023) BREAKING CHANGES: From f72f8e939c13601376b6fb47d8c6e129ded7b260 Mon Sep 17 00:00:00 2001 From: Justin Holmes Date: Mon, 23 Jan 2023 14:09:00 -0600 Subject: [PATCH 118/370] Add ui_read_only_toggle_reason to Access organization --- .changelog/1182.txt | 3 +++ access_organization.go | 1 + access_organization_test.go | 6 ++++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changelog/1182.txt diff --git a/.changelog/1182.txt b/.changelog/1182.txt new file mode 100644 index 0000000000..355b67584b --- /dev/null +++ b/.changelog/1182.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access_organization: add ui_read_only_toggle_reason field +``` diff --git a/access_organization.go b/access_organization.go index 35c9e9e378..f4de4a7b68 100644 --- a/access_organization.go +++ b/access_organization.go @@ -16,6 +16,7 @@ type AccessOrganization struct { AuthDomain string `json:"auth_domain"` LoginDesign AccessOrganizationLoginDesign `json:"login_design"` IsUIReadOnly *bool `json:"is_ui_read_only,omitempty"` + UIReadOnlyToggleReason string `json:"ui_read_only_toggle_reason,omitempty"` UserSeatExpirationInactiveTime string `json:"user_seat_expiration_inactive_time,omitempty"` } diff --git a/access_organization_test.go b/access_organization_test.go index f09a0a37ed..7d6cfa60e3 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -163,7 +163,8 @@ func TestUpdateAccessOrganization(t *testing.T) { "header_text": "Widget Corp", "footer_text": "© Widget Corp" }, - "is_ui_read_only": false + "is_ui_read_only": false, + "ui_read_only_toggle_reason": "this is my reason" } } `) @@ -184,7 +185,8 @@ func TestUpdateAccessOrganization(t *testing.T) { HeaderText: "Widget Corp", FooterText: "© Widget Corp", }, - IsUIReadOnly: BoolPtr(false), + IsUIReadOnly: BoolPtr(false), + UIReadOnlyToggleReason: "this is my reason", } mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) From 23e7315274a3f6d8a8395bdc8d41a97659977d06 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 24 Jan 2023 13:09:46 +1100 Subject: [PATCH 119/370] Rename 1182.txt to 1181.txt --- .changelog/{1182.txt => 1181.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1182.txt => 1181.txt} (100%) diff --git a/.changelog/1182.txt b/.changelog/1181.txt similarity index 100% rename from .changelog/1182.txt rename to .changelog/1181.txt From 252311c837a68e92b46064e733258f528957f40a Mon Sep 17 00:00:00 2001 From: Troy Jones Date: Mon, 23 Jan 2023 21:53:24 -0700 Subject: [PATCH 120/370] Add support for score_per_period in RulesetRuleRateLimit --- rulesets.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/rulesets.go b/rulesets.go index 1f18d64a7a..3a3b2e1d63 100644 --- a/rulesets.go +++ b/rulesets.go @@ -643,12 +643,14 @@ type RulesetRule struct { // RulesetRuleRateLimit contains the structure of a HTTP rate limit Ruleset Rule. type RulesetRuleRateLimit struct { - Characteristics []string `json:"characteristics,omitempty"` - RequestsPerPeriod int `json:"requests_per_period,omitempty"` - Period int `json:"period,omitempty"` - MitigationTimeout int `json:"mitigation_timeout,omitempty"` - CountingExpression string `json:"counting_expression,omitempty"` - RequestsToOrigin bool `json:"requests_to_origin,omitempty"` + Characteristics []string `json:"characteristics,omitempty"` + RequestsPerPeriod int `json:"requests_per_period,omitempty"` + ScorePerPeriod int `json:"score_per_period,omitempty"` + ScoreResponseHeaderName string `json:"score_response_header_name,omitempty"` + Period int `json:"period,omitempty"` + MitigationTimeout int `json:"mitigation_timeout,omitempty"` + CountingExpression string `json:"counting_expression,omitempty"` + RequestsToOrigin bool `json:"requests_to_origin,omitempty"` } // RulesetRuleExposedCredentialCheck contains the structure of an exposed From 0b30ff99fd5f6e6bb50ef37806d427baa1c27f0a Mon Sep 17 00:00:00 2001 From: Troy Jones Date: Mon, 23 Jan 2023 22:39:29 -0700 Subject: [PATCH 121/370] Add enhancement to changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d918244b2d..e21d7da352 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 ([#1180](https://github.com/cloudflare/cloudflare-go/issues/1180)) +ENHANCEMENTS: + +* rulesets: add support for `score_per_period` and `score_response_header_name` ([#1182](https://github.com/cloudflare/cloudflare-go/issues/1182)) + ## 0.59.0 (January 18th, 2023) BREAKING CHANGES: From 15951ef65481c3fc2e5b39fc88bbd51832229e77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 16:01:28 +0000 Subject: [PATCH 122/370] build(deps): bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.3.5 to 1.3.6. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/v1.3.5...v1.3.6) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependabot-changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-changelog.yml b/.github/workflows/dependabot-changelog.yml index 88e6036bc4..8219a4ac6a 100644 --- a/.github/workflows/dependabot-changelog.yml +++ b/.github/workflows/dependabot-changelog.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Fetch dependabot metadata id: dependabot-metadata - uses: dependabot/fetch-metadata@v1.3.5 + uses: dependabot/fetch-metadata@v1.3.6 - uses: actions/checkout@v3 - run: | gh pr checkout $PR_URL From cb55a7416f7e76fc5f924d17f9ab75af83b5ecfe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Jan 2023 16:02:35 +0000 Subject: [PATCH 123/370] add CHANGELOG for #1184 --- .changelog/1184.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1184.txt diff --git a/.changelog/1184.txt b/.changelog/1184.txt new file mode 100644 index 0000000000..7e721c577b --- /dev/null +++ b/.changelog/1184.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps dependabot/fetch-metadata from 1.3.5 to 1.3.6 +``` From f9e18edd60af3384e4f00478bb5ca23ccdef99a7 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 24 Jan 2023 18:40:20 +0000 Subject: [PATCH 124/370] Update CHANGELOG.md for #1184 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d918244b2d..0e011f7e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ DEPENDENCIES: +* deps: bumps dependabot/fetch-metadata from 1.3.5 to 1.3.6 ([#1184](https://github.com/cloudflare/cloudflare-go/issues/1184)) * deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 ([#1180](https://github.com/cloudflare/cloudflare-go/issues/1180)) ## 0.59.0 (January 18th, 2023) From c7d9206ea1b6c6a3dba813562870b8188b00d476 Mon Sep 17 00:00:00 2001 From: Troy Jones Date: Tue, 24 Jan 2023 21:21:42 -0700 Subject: [PATCH 125/370] Fix changelog entry to match changelog process --- .changelog/1183.txt | 3 +++ CHANGELOG.md | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 .changelog/1183.txt diff --git a/.changelog/1183.txt b/.changelog/1183.txt new file mode 100644 index 0000000000..01e3947686 --- /dev/null +++ b/.changelog/1183.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +rulesets: add support for `score_per_period` and `score_response_header_name` +``` diff --git a/CHANGELOG.md b/CHANGELOG.md index e21d7da352..d918244b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,6 @@ DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 ([#1180](https://github.com/cloudflare/cloudflare-go/issues/1180)) -ENHANCEMENTS: - -* rulesets: add support for `score_per_period` and `score_response_header_name` ([#1182](https://github.com/cloudflare/cloudflare-go/issues/1182)) - ## 0.59.0 (January 18th, 2023) BREAKING CHANGES: From b8e43c2affb04dd0557deebbc3ed2280aa9d7a59 Mon Sep 17 00:00:00 2001 From: Troy Jones Date: Tue, 24 Jan 2023 22:07:17 -0700 Subject: [PATCH 126/370] Fix lint issues --- rulesets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rulesets.go b/rulesets.go index 3a3b2e1d63..27521b024c 100644 --- a/rulesets.go +++ b/rulesets.go @@ -645,7 +645,7 @@ type RulesetRule struct { type RulesetRuleRateLimit struct { Characteristics []string `json:"characteristics,omitempty"` RequestsPerPeriod int `json:"requests_per_period,omitempty"` - ScorePerPeriod int `json:"score_per_period,omitempty"` + ScorePerPeriod int `json:"score_per_period,omitempty"` ScoreResponseHeaderName string `json:"score_response_header_name,omitempty"` Period int `json:"period,omitempty"` MitigationTimeout int `json:"mitigation_timeout,omitempty"` From ac283d8803ca823fed99fde4c9b53be2d29eef6d Mon Sep 17 00:00:00 2001 From: Jonathan Kunder Date: Wed, 25 Jan 2023 15:19:33 -0800 Subject: [PATCH 127/370] Make Customer Endpoint optional in IPSEC tunnel config In Magic Transit IPSEC Tunnel config API, the customer endpoint IP is optional Verified tunnel setup without specifying Customer endpoint IP in local setup --- magic_transit_ipsec_tunnel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magic_transit_ipsec_tunnel.go b/magic_transit_ipsec_tunnel.go index cf9076a518..6ac5f22c2c 100644 --- a/magic_transit_ipsec_tunnel.go +++ b/magic_transit_ipsec_tunnel.go @@ -32,7 +32,7 @@ type MagicTransitIPsecTunnel struct { CreatedOn *time.Time `json:"created_on,omitempty"` ModifiedOn *time.Time `json:"modified_on,omitempty"` Name string `json:"name"` - CustomerEndpoint string `json:"customer_endpoint"` + CustomerEndpoint string `json:"customer_endpoint,omitempty"` CloudflareEndpoint string `json:"cloudflare_endpoint"` InterfaceAddress string `json:"interface_address"` Description string `json:"description,omitempty"` From fbc791dc7692071b72ea062134b6398f9688dafd Mon Sep 17 00:00:00 2001 From: Jonathan Kunder Date: Wed, 25 Jan 2023 15:58:03 -0800 Subject: [PATCH 128/370] Add changelog --- .changelog/1185.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1185.txt diff --git a/.changelog/1185.txt b/.changelog/1185.txt new file mode 100644 index 0000000000..5cf8562005 --- /dev/null +++ b/.changelog/1185.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +magic_transit_ipsec_tunnel: makes customer endpoint an optional field for ipsec tunnel creation +``` From 88db12a26b863ba0c44a65283182dd91d8886d8e Mon Sep 17 00:00:00 2001 From: Manolis Tzanidakis Date: Thu, 26 Jan 2023 14:11:54 +0200 Subject: [PATCH 129/370] remove leftover debug log overrides --- cloudflare.go | 3 --- cloudflare_experimental.go | 3 --- 2 files changed, 6 deletions(-) diff --git a/cloudflare.go b/cloudflare.go index 5b0c220fcf..5d69043257 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -363,9 +363,6 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m // *http.Response, or an error if one occurred. The caller is responsible for // closing the response body. func (api *API) request(ctx context.Context, method, uri string, reqBody io.Reader, authType int, headers http.Header) (*http.Response, error) { - log.SetPrefix(time.Now().Format(time.RFC3339Nano) + " [DEBUG] cloudflare") - log.SetFlags(0) - req, err := http.NewRequestWithContext(ctx, method, api.BaseURL+uri, reqBody) if err != nil { return nil, fmt.Errorf("HTTP request creation failed: %w", err) diff --git a/cloudflare_experimental.go b/cloudflare_experimental.go index e01c7a60d0..c4bc4934ea 100644 --- a/cloudflare_experimental.go +++ b/cloudflare_experimental.go @@ -161,9 +161,6 @@ func NewExperimental(config *ClientParams) (*Client, error) { // *http.Response, or an error if one occurred. The caller is responsible for // closing the response body. func (c *Client) request(ctx context.Context, method, uri string, reqBody io.Reader, headers http.Header) (*http.Response, error) { - log.SetPrefix(time.Now().Format(time.RFC3339Nano) + " [DEBUG] cloudflare") - log.SetFlags(0) - req, err := http.NewRequestWithContext(ctx, method, c.BaseURL.String()+uri, reqBody) if err != nil { return nil, fmt.Errorf("HTTP request creation failed: %w", err) From 9344d5775f9e818d7aeaffee542b0e7abe9f1594 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 26 Jan 2023 22:15:10 +0000 Subject: [PATCH 130/370] Update CHANGELOG.md for #1185 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e011f7e6a..d5301a4c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.60.0 (Unreleased) +ENHANCEMENTS: + +* magic_transit_ipsec_tunnel: makes customer endpoint an optional field for ipsec tunnel creation ([#1185](https://github.com/cloudflare/cloudflare-go/issues/1185)) + DEPENDENCIES: * deps: bumps dependabot/fetch-metadata from 1.3.5 to 1.3.6 ([#1184](https://github.com/cloudflare/cloudflare-go/issues/1184)) From 9452119cec6ea0ecaf2b8c76177adf08d629359a Mon Sep 17 00:00:00 2001 From: Josh Wheeler Date: Fri, 27 Jan 2023 09:10:49 -0600 Subject: [PATCH 131/370] UpdateQueue function now matches API docs and allows a Queue's name to be updated --- queue.go | 15 ++++----------- queue_test.go | 6 +++--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/queue.go b/queue.go index 3b9aa5e90a..59f9a10a8c 100644 --- a/queue.go +++ b/queue.go @@ -78,14 +78,7 @@ type QueueConsumerResponse struct { } type UpdateQueueParams struct { - ID string `json:"queue_id,omitempty"` - Name string `json:"queue_name,omitempty"` - CreatedOn *time.Time `json:"created_on,omitempty"` - ModifiedOn *time.Time `json:"modified_on,omitempty"` - ProducersTotalCount int `json:"producers_total_count,omitempty"` - Producers []QueueProducer `json:"producers,omitempty"` - ConsumersTotalCount int `json:"consumers_total_count,omitempty"` - Consumers []QueueConsumer `json:"consumers,omitempty"` + Name string `json:"queue_name,omitempty"` } type ListQueueConsumersParams struct { @@ -228,7 +221,7 @@ func (api *API) GetQueue(ctx context.Context, rc *ResourceContainer, queueName s // UpdateQueue updates a queue. // // API reference: https://api.cloudflare.com/#queue-update-queue -func (api *API) UpdateQueue(ctx context.Context, rc *ResourceContainer, params UpdateQueueParams) (Queue, error) { +func (api *API) UpdateQueue(ctx context.Context, rc *ResourceContainer, queueName string, params UpdateQueueParams) (Queue, error) { if rc.Identifier == "" { return Queue{}, ErrMissingAccountID } @@ -237,8 +230,8 @@ func (api *API) UpdateQueue(ctx context.Context, rc *ResourceContainer, params U return Queue{}, ErrMissingQueueName } - uri := fmt.Sprintf("/accounts/%s/workers/queues/%s", rc.Identifier, params.Name) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil) + uri := fmt.Sprintf("/accounts/%s/workers/queues/%s", rc.Identifier, queueName) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return Queue{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } diff --git a/queue_test.go b/queue_test.go index 5485b354ca..d15e3923f5 100644 --- a/queue_test.go +++ b/queue_test.go @@ -272,17 +272,17 @@ func TestQueue_Update(t *testing.T) { } }`) }) - _, err := client.UpdateQueue(context.Background(), AccountIdentifier(""), UpdateQueueParams{}) + _, err := client.UpdateQueue(context.Background(), AccountIdentifier(""), testQueueName, UpdateQueueParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), UpdateQueueParams{}) + _, err = client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), testQueueName, UpdateQueueParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingQueueName, err) } - results, err := client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), UpdateQueueParams{Name: "example-queue"}) + results, err := client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), testQueueName, UpdateQueueParams{Name: "renamed-example-queue"}) if assert.NoError(t, err) { CreatedOn, _ := time.Parse(time.RFC3339, "2023-01-01T00:00:00Z") ModifiedOn, _ := time.Parse(time.RFC3339, "2023-01-01T00:00:00Z") From 8fe759465a12c5afd6ad2c12f05cb0c015b2d663 Mon Sep 17 00:00:00 2001 From: Josh Wheeler Date: Fri, 27 Jan 2023 09:35:15 -0600 Subject: [PATCH 132/370] Add changelog for UpdateQueue changes --- .changelog/1188.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1188.txt diff --git a/.changelog/1188.txt b/.changelog/1188.txt new file mode 100644 index 0000000000..b478f060d3 --- /dev/null +++ b/.changelog/1188.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +queues: UpdateQueue has been updated to match the API and now correctly updates a Queue's name +``` \ No newline at end of file From 3fd40f1a841c70c4eae772b65d32e5cdbdd7ec7c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 30 Jan 2023 12:55:20 +1100 Subject: [PATCH 133/370] ci: remove mac + windows jobs We added MacOS and Windows runners after we had a dependency library incompatible upgrade occur. We haven't seen anything like this recently so let's remove it for now given our tight budget on GitHub Action runners. --- .github/workflows/changelog-check.yml | 7 ++----- .github/workflows/coverage.yml | 6 +++--- .github/workflows/generate-changelog.yml | 6 +++--- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 3 +-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml index dba1a7f545..45b8c408be 100644 --- a/.github/workflows/changelog-check.yml +++ b/.github/workflows/changelog-check.yml @@ -3,16 +3,13 @@ on: [pull_request_target] jobs: changelog-check: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest] + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v3 with: - go-version: ^1.17 + go-version-file: 'internal/tools/go.mod' - run: go generate -tags tools internal/tools/tools.go - run: go run cmd/changelog-check/main.go ${{ github.event.pull_request.number }} working-directory: ./internal/tools diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7dfe116df9..57870aa4a8 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -4,11 +4,11 @@ jobs: coverage: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.18 - name: Checkout code uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version-file: 'go.mod' - uses: actions/cache@v3 with: path: ~/go/pkg/mod diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml index 341cf5c9d9..b8029ae782 100644 --- a/.github/workflows/generate-changelog.yml +++ b/.github/workflows/generate-changelog.yml @@ -8,12 +8,12 @@ jobs: if: github.event.pull_request.merged || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 - with: - go-version: 1.18 - uses: actions/checkout@v3 with: fetch-depth: 0 + - uses: actions/setup-go@v3 + with: + go-version-file: 'internal/tools/go.mod' - run: go generate -tags tools internal/tools/tools.go - run: ./scripts/generate-changelog.sh - run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7063c4e377..0830c1050c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v3 with: - go-version: ^1.17 + go-version-file: 'go.mod' - name: Run GoReleaser uses: goreleaser/goreleaser-action@v4.1.0 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7cfdd13f0..087d4c4aa3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,8 +5,7 @@ jobs: strategy: matrix: go-version: [1.17, 1.18, 1.19] - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 with: From 480957e04eab1e380a51012bd4e339212cae5d87 Mon Sep 17 00:00:00 2001 From: Josh Wheeler Date: Mon, 30 Jan 2023 09:44:36 -0600 Subject: [PATCH 134/370] UpdateQueue follows three parameter pattern --- queue.go | 9 +++++---- queue_test.go | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/queue.go b/queue.go index 59f9a10a8c..771a1f1482 100644 --- a/queue.go +++ b/queue.go @@ -78,7 +78,8 @@ type QueueConsumerResponse struct { } type UpdateQueueParams struct { - Name string `json:"queue_name,omitempty"` + Name string `json:"-"` + UpdatedName string `json:"queue_name,omitempty"` } type ListQueueConsumersParams struct { @@ -221,16 +222,16 @@ func (api *API) GetQueue(ctx context.Context, rc *ResourceContainer, queueName s // UpdateQueue updates a queue. // // API reference: https://api.cloudflare.com/#queue-update-queue -func (api *API) UpdateQueue(ctx context.Context, rc *ResourceContainer, queueName string, params UpdateQueueParams) (Queue, error) { +func (api *API) UpdateQueue(ctx context.Context, rc *ResourceContainer, params UpdateQueueParams) (Queue, error) { if rc.Identifier == "" { return Queue{}, ErrMissingAccountID } - if params.Name == "" { + if params.Name == "" || params.UpdatedName == "" { return Queue{}, ErrMissingQueueName } - uri := fmt.Sprintf("/accounts/%s/workers/queues/%s", rc.Identifier, queueName) + uri := fmt.Sprintf("/accounts/%s/workers/queues/%s", rc.Identifier, params.Name) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return Queue{}, fmt.Errorf("%s: %w", errMakeRequestError, err) diff --git a/queue_test.go b/queue_test.go index d15e3923f5..b175a7045d 100644 --- a/queue_test.go +++ b/queue_test.go @@ -272,17 +272,17 @@ func TestQueue_Update(t *testing.T) { } }`) }) - _, err := client.UpdateQueue(context.Background(), AccountIdentifier(""), testQueueName, UpdateQueueParams{}) + _, err := client.UpdateQueue(context.Background(), AccountIdentifier(""), UpdateQueueParams{Name: testQueueName}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), testQueueName, UpdateQueueParams{}) + _, err = client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), UpdateQueueParams{Name: testQueueName}) if assert.Error(t, err) { assert.Equal(t, ErrMissingQueueName, err) } - results, err := client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), testQueueName, UpdateQueueParams{Name: "renamed-example-queue"}) + results, err := client.UpdateQueue(context.Background(), AccountIdentifier(testAccountID), UpdateQueueParams{Name: testQueueName, UpdatedName: "renamed-example-queue"}) if assert.NoError(t, err) { CreatedOn, _ := time.Parse(time.RFC3339, "2023-01-01T00:00:00Z") ModifiedOn, _ := time.Parse(time.RFC3339, "2023-01-01T00:00:00Z") From 76352df0af0050466a19d9cc184e9b90d1768155 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:01:03 +0000 Subject: [PATCH 135/370] build(deps): bump github.com/urfave/cli/v2 from 2.24.1 to 2.24.2 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.1 to 2.24.2. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.1...v2.24.2) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2c79c061bb..c17990053b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.24.1 + github.com/urfave/cli/v2 v2.24.2 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index f2d0e8d739..086e241bc1 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.24.1 h1:/QYYr7g0EhwXEML8jO+8OYt5trPnLHS0p3mrgExJ5NU= -github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.24.2 h1:q1VA+ofZ8SWfEKB9xXHUD4QZaeI9e+ItEqSbfH2JBXk= +github.com/urfave/cli/v2 v2.24.2/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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 414d446d3be67478aa1e933c3dfb010279470d76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Jan 2023 16:01:28 +0000 Subject: [PATCH 136/370] add CHANGELOG for #1191 --- .changelog/1191.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1191.txt diff --git a/.changelog/1191.txt b/.changelog/1191.txt new file mode 100644 index 0000000000..f42bc3663c --- /dev/null +++ b/.changelog/1191.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.24.1 to 2.24.2 +``` From f1b941aebcdd6cf69b0727502b03ca3071b906b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:02:22 +0000 Subject: [PATCH 137/370] build(deps): bump goreleaser/goreleaser-action from 4.1.0 to 4.2.0 Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v4.1.0...v4.2.0) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0830c1050c..1a6351cfb1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: with: go-version-file: 'go.mod' - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4.1.0 + uses: goreleaser/goreleaser-action@v4.2.0 with: version: latest args: release --rm-dist From fb61c636ff3d299368ed095c63faa6625d39c192 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Jan 2023 16:03:04 +0000 Subject: [PATCH 138/370] add CHANGELOG for #1192 --- .changelog/1192.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1192.txt diff --git a/.changelog/1192.txt b/.changelog/1192.txt new file mode 100644 index 0000000000..23cd06d801 --- /dev/null +++ b/.changelog/1192.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps goreleaser/goreleaser-action from 4.1.0 to 4.2.0 +``` From af4b4f19f27f2b75902a1efb49409ff514a47f31 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 30 Jan 2023 20:50:51 +0000 Subject: [PATCH 139/370] Update CHANGELOG.md for #1192 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5301a4c32..3ad9a03c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,20 @@ ## 0.60.0 (Unreleased) +BREAKING CHANGES: + +* queues: UpdateQueue has been updated to match the API and now correctly updates a Queue's name ([#1188](https://github.com/cloudflare/cloudflare-go/issues/1188)) + ENHANCEMENTS: * magic_transit_ipsec_tunnel: makes customer endpoint an optional field for ipsec tunnel creation ([#1185](https://github.com/cloudflare/cloudflare-go/issues/1185)) +* rulesets: add support for `score_per_period` and `score_response_header_name` ([#1183](https://github.com/cloudflare/cloudflare-go/issues/1183)) DEPENDENCIES: * deps: bumps dependabot/fetch-metadata from 1.3.5 to 1.3.6 ([#1184](https://github.com/cloudflare/cloudflare-go/issues/1184)) * deps: bumps github.com/urfave/cli/v2 from 2.23.7 to 2.24.1 ([#1180](https://github.com/cloudflare/cloudflare-go/issues/1180)) +* deps: bumps github.com/urfave/cli/v2 from 2.24.1 to 2.24.2 ([#1191](https://github.com/cloudflare/cloudflare-go/issues/1191)) +* deps: bumps goreleaser/goreleaser-action from 4.1.0 to 4.2.0 ([#1192](https://github.com/cloudflare/cloudflare-go/issues/1192)) ## 0.59.0 (January 18th, 2023) From ab54637f4d0c063c6c34b80632ae5d64ee26639b Mon Sep 17 00:00:00 2001 From: Pierre Cauchois Date: Mon, 30 Jan 2023 12:51:27 -0800 Subject: [PATCH 140/370] Add allowed_match_count to DLP profiles --- dlp_profile.go | 9 +++--- dlp_profile_test.go | 67 ++++++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/dlp_profile.go b/dlp_profile.go index 94202842ee..c08a6aa4d6 100644 --- a/dlp_profile.go +++ b/dlp_profile.go @@ -37,10 +37,11 @@ type DLPEntry struct { // DLPProfile represents a DLP Profile, which contains a set // of entries. type DLPProfile struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Description string `json:"description,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Description string `json:"description,omitempty"` + AllowedMatchCount uint `json:"allowed_match_count"` // The following fields are omitted for predefined DLP // profiles diff --git a/dlp_profile_test.go b/dlp_profile_test.go index d7c88f5718..20b4aa86c1 100644 --- a/dlp_profile_test.go +++ b/dlp_profile_test.go @@ -43,7 +43,8 @@ func TestDLPProfiles(t *testing.T) { "type": "predefined" } ], - "type": "predefined" + "type": "predefined", + "allowed_match_count": 0 }, { "id": "29678c26-a191-428d-9f63-6e20a4a636a4", @@ -66,7 +67,8 @@ func TestDLPProfiles(t *testing.T) { "created_at": "2022-10-18T08:00:56Z", "updated_at": "2022-10-18T08:00:57Z", "type": "custom", - "description": "just a custom profile example" + "description": "just a custom profile example", + "allowed_match_count": 1 } ] } @@ -78,10 +80,11 @@ func TestDLPProfiles(t *testing.T) { want := []DLPProfile{ { - ID: "d658f520-6ecb-4a34-a725-ba37243c2d28", - Name: "U.S. Social Security Numbers", - Type: "predefined", - Description: "", + ID: "d658f520-6ecb-4a34-a725-ba37243c2d28", + Name: "U.S. Social Security Numbers", + Type: "predefined", + Description: "", + AllowedMatchCount: 0, Entries: []DLPEntry{ { ID: "111b9d4b-a5c6-40f0-957d-9d53b25dd84a", @@ -99,10 +102,11 @@ func TestDLPProfiles(t *testing.T) { }, }, { - ID: "29678c26-a191-428d-9f63-6e20a4a636a4", - Name: "Example Custom Profile", - Type: "custom", - Description: "just a custom profile example", + ID: "29678c26-a191-428d-9f63-6e20a4a636a4", + Name: "Example Custom Profile", + Type: "custom", + Description: "just a custom profile example", + AllowedMatchCount: 1, Entries: []DLPEntry{ { ID: "ef79b054-12d4-4067-bb30-b85f6267b91c", @@ -161,7 +165,8 @@ func TestGetDLPProfile(t *testing.T) { "created_at": "2022-10-18T08:00:56Z", "updated_at": "2022-10-18T08:00:57Z", "type": "custom", - "description": "just a custom profile example" + "description": "just a custom profile example", + "allowed_match_count": 42 } }`) } @@ -170,10 +175,11 @@ func TestGetDLPProfile(t *testing.T) { updatedAt, _ := time.Parse(time.RFC3339, "2022-10-18T08:00:57Z") want := DLPProfile{ - ID: "29678c26-a191-428d-9f63-6e20a4a636a4", - Name: "Example Custom Profile", - Type: "custom", - Description: "just a custom profile example", + ID: "29678c26-a191-428d-9f63-6e20a4a636a4", + Name: "Example Custom Profile", + Type: "custom", + Description: "just a custom profile example", + AllowedMatchCount: 42, Entries: []DLPEntry{ { ID: "ef79b054-12d4-4067-bb30-b85f6267b91c", @@ -238,7 +244,8 @@ func TestCreateDLPCustomProfiles(t *testing.T) { "created_at": "2022-10-18T08:00:56Z", "updated_at": "2022-10-18T08:00:57Z", "type": "custom", - "description": "`+requestProfile.Description+`" + "description": "`+requestProfile.Description+`", + "allowed_match_count": 0 }] }`) } @@ -267,8 +274,9 @@ func TestCreateDLPCustomProfiles(t *testing.T) { UpdatedAt: &updatedAt, }, }, - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + AllowedMatchCount: 0, }, } @@ -289,6 +297,7 @@ func TestCreateDLPCustomProfiles(t *testing.T) { }, }, }, + AllowedMatchCount: 0, }, } actual, err := client.CreateDLPProfiles(context.Background(), AccountIdentifier(testAccountID), CreateDLPProfilesParams{Profiles: profiles, Type: "custom"}) @@ -334,7 +343,8 @@ func TestCreateDLPCustomProfile(t *testing.T) { "created_at": "2022-10-18T08:00:56Z", "updated_at": "2022-10-18T08:00:57Z", "type": "custom", - "description": "`+requestProfile.Description+`" + "description": "`+requestProfile.Description+`", + "allowed_match_count": 0 }] }`) } @@ -363,8 +373,9 @@ func TestCreateDLPCustomProfile(t *testing.T) { UpdatedAt: &updatedAt, }, }, - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + AllowedMatchCount: 0, }} mux.HandleFunc("/accounts/"+testAccountID+"/dlp/profiles/custom", handler) @@ -382,6 +393,7 @@ func TestCreateDLPCustomProfile(t *testing.T) { }, }, }, + AllowedMatchCount: 0, }} actual, err := client.CreateDLPProfiles(context.Background(), AccountIdentifier(testAccountID), CreateDLPProfilesParams{ @@ -429,7 +441,8 @@ func TestUpdateDLPCustomProfile(t *testing.T) { "created_at": "2022-10-18T08:00:56Z", "updated_at": "2022-10-18T08:00:57Z", "type": "custom", - "description": "`+requestProfile.Description+`" + "description": "`+requestProfile.Description+`", + "allowed_match_count": 0 } }`) } @@ -458,8 +471,9 @@ func TestUpdateDLPCustomProfile(t *testing.T) { UpdatedAt: &updatedAt, }, }, - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + AllowedMatchCount: 0, } mux.HandleFunc("/accounts/"+testAccountID+"/dlp/profiles/custom/29678c26-a191-428d-9f63-6e20a4a636a4", handler) @@ -477,6 +491,7 @@ func TestUpdateDLPCustomProfile(t *testing.T) { }, }, }, + AllowedMatchCount: 0, } actual, err := client.UpdateDLPProfile(context.Background(), AccountIdentifier(testAccountID), UpdateDLPProfileParams{ ProfileID: "29678c26-a191-428d-9f63-6e20a4a636a4", @@ -516,7 +531,8 @@ func TestUpdateDLPPredefinedProfile(t *testing.T) { } ], "type": "predefined", - "description": "example predefined profile" + "description": "example predefined profile", + "allowed_match_count": 0 } }`) } @@ -535,6 +551,7 @@ func TestUpdateDLPPredefinedProfile(t *testing.T) { Enabled: BoolPtr(true), }, }, + AllowedMatchCount: 0, } mux.HandleFunc("/accounts/"+testAccountID+"/dlp/profiles/predefined/29678c26-a191-428d-9f63-6e20a4a636a4", handler) From 227f4ae10daab22c16ced9c86c249e9db5c5897f Mon Sep 17 00:00:00 2001 From: Pierre Cauchois Date: Mon, 30 Jan 2023 13:13:41 -0800 Subject: [PATCH 141/370] Add changelog entry --- .changelog/1193.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1193.txt diff --git a/.changelog/1193.txt b/.changelog/1193.txt new file mode 100644 index 0000000000..45d8b086f1 --- /dev/null +++ b/.changelog/1193.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +DLP: Add new allowed_match_count field to profiles +``` From c07adfcbb9bf76ec82d93e693842b4421d5cebfe Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 31 Jan 2023 08:47:57 +1100 Subject: [PATCH 142/370] Update .changelog/1193.txt --- .changelog/1193.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1193.txt b/.changelog/1193.txt index 45d8b086f1..461d746f78 100644 --- a/.changelog/1193.txt +++ b/.changelog/1193.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -DLP: Add new allowed_match_count field to profiles +dlp_profile: Add new allowed_match_count field to profiles ``` From fc27011e57c03a0d1a9247b20bb13a1acdd34418 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 30 Jan 2023 21:52:45 +0000 Subject: [PATCH 143/370] Update CHANGELOG.md for #1193 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad9a03c6b..8347e6428e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ BREAKING CHANGES: ENHANCEMENTS: +* dlp_profile: Add new allowed_match_count field to profiles ([#1193](https://github.com/cloudflare/cloudflare-go/issues/1193)) * magic_transit_ipsec_tunnel: makes customer endpoint an optional field for ipsec tunnel creation ([#1185](https://github.com/cloudflare/cloudflare-go/issues/1185)) * rulesets: add support for `score_per_period` and `score_response_header_name` ([#1183](https://github.com/cloudflare/cloudflare-go/issues/1183)) From ad39f9b3dc196b4d99ac1d423da4bafda90114a2 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 09:11:28 +1100 Subject: [PATCH 144/370] dns: allow sending empty strings Updates the SDK to allow sending empty strings to the API to clear DNS comment values. Fixes #1166 --- dns.go | 3 ++- dns_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/dns.go b/dns.go index 9eaa52dc14..061a9dee8b 100644 --- a/dns.go +++ b/dns.go @@ -71,7 +71,7 @@ type UpdateDNSRecordParams struct { Priority *uint16 `json:"-"` // internal use only TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty"` - Comment string `json:"comment,omitempty"` + Comment string `json:"comment"` Tags []string `json:"tags,omitempty"` } @@ -229,6 +229,7 @@ func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, para if rc.Identifier == "" { return ErrMissingZoneID } + if params.ID == "" { return ErrMissingDNSRecordID } diff --git a/dns_test.go b/dns_test.go index 086f32adee..41b7c33350 100644 --- a/dns_test.go +++ b/dns_test.go @@ -528,6 +528,64 @@ func TestUpdateDNSRecord(t *testing.T) { require.NoError(t, err) } +func TestUpdateDNSRecord_ClearComment(t *testing.T) { + setup() + defer teardown() + + input := DNSRecord{ + ID: "372e67954025e0ba6aaa6d586b9e0b59", + Comment: "", + } + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method) + + var v DNSRecord + err := json.NewDecoder(r.Body).Decode(&v) + require.NoError(t, err) + v.ID = "372e67954025e0ba6aaa6d586b9e0b59" + assert.Equal(t, input, v) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "372e67954025e0ba6aaa6d586b9e0b59", + "type": "A", + "name": "example.com", + "content": "198.51.100.4", + "proxiable": true, + "proxied": false, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "comment":null, + "tags":[], + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + } + } + }`) + } + + dnsRecordID := "372e67954025e0ba6aaa6d586b9e0b59" + + mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) + + err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + ID: dnsRecordID, + Comment: "", + }) + require.NoError(t, err) +} + func TestDeleteDNSRecord(t *testing.T) { setup() defer teardown() From 6bd0d08ccac8344c98e73786145d7ac86acfd9bd Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 09:15:26 +1100 Subject: [PATCH 145/370] add changelog entry --- .changelog/1195.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1195.txt diff --git a/.changelog/1195.txt b/.changelog/1195.txt new file mode 100644 index 0000000000..ec28f43c51 --- /dev/null +++ b/.changelog/1195.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dns: allow sending empty strings +``` From 74112f2f79b73ed733cf4830385359c7995e2a6d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 09:20:01 +1100 Subject: [PATCH 146/370] Update 1195.txt --- .changelog/1195.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1195.txt b/.changelog/1195.txt index ec28f43c51..4642d151ee 100644 --- a/.changelog/1195.txt +++ b/.changelog/1195.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -dns: allow sending empty strings +dns: allow sending empty strings to remove comments ``` From c01e0ef1e4ae81e4801756c8538e20a2199c23fe Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 31 Jan 2023 22:23:14 +0000 Subject: [PATCH 147/370] Update CHANGELOG.md (Manual Trigger) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8347e6428e..33461f341d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ BREAKING CHANGES: ENHANCEMENTS: * dlp_profile: Add new allowed_match_count field to profiles ([#1193](https://github.com/cloudflare/cloudflare-go/issues/1193)) +* dns: allow sending empty strings to remove comments ([#1195](https://github.com/cloudflare/cloudflare-go/issues/1195)) * magic_transit_ipsec_tunnel: makes customer endpoint an optional field for ipsec tunnel creation ([#1185](https://github.com/cloudflare/cloudflare-go/issues/1185)) * rulesets: add support for `score_per_period` and `score_response_header_name` ([#1183](https://github.com/cloudflare/cloudflare-go/issues/1183)) From 2c3166241b89cc44e4fff3b04ac2fd5957f9fc76 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 09:29:18 +1100 Subject: [PATCH 148/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33461f341d..8cd9c27659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.60.0 (Unreleased) +## 0.61.0 (Unreleased) + +## 0.60.0 (1st February, 2023) BREAKING CHANGES: From 3251e14dab23650b3850dff7894d79c256d832e3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 17:14:47 +1100 Subject: [PATCH 149/370] dns: always send tags to allow clearing --- dns.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns.go b/dns.go index 9eaa52dc14..4846201cce 100644 --- a/dns.go +++ b/dns.go @@ -72,7 +72,7 @@ type UpdateDNSRecordParams struct { TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty"` Comment string `json:"comment,omitempty"` - Tags []string `json:"tags,omitempty"` + Tags []string `json:"tags"` } // DNSListResponse represents the response from the list DNS records endpoint. From 39111606fb9916f93b812f8d60b809838497259d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Feb 2023 17:40:08 +1100 Subject: [PATCH 150/370] Create 1196.txt --- .changelog/1196.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1196.txt diff --git a/.changelog/1196.txt b/.changelog/1196.txt new file mode 100644 index 0000000000..fba5681f28 --- /dev/null +++ b/.changelog/1196.txt @@ -0,0 +1,3 @@ +```release-note:bug +dns: always send `tags` to allow clearing +``` From e4ad1e5936e20b5f2e4a437839982c1833ee1c14 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 1 Feb 2023 07:09:12 +0000 Subject: [PATCH 151/370] Update CHANGELOG.md for #1196 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd9c27659..46519f84c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.61.0 (Unreleased) +BUG FIXES: + +* dns: always send `tags` to allow clearing ([#1196](https://github.com/cloudflare/cloudflare-go/issues/1196)) + ## 0.60.0 (1st February, 2023) BREAKING CHANGES: From a96123f6b61edf03409711fa5cea97a6ac8f20d0 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 2 Feb 2023 07:39:09 +1100 Subject: [PATCH 152/370] add go1.20 to test matrix, remove go1.17 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 087d4c4aa3..5dcbe72fd8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.17, 1.18, 1.19] + go-version: [1.18, 1.19, 1.20] runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 From 7eff3aba6a027fbb39e655c6c714d4f25dac41b9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 2 Feb 2023 07:40:20 +1100 Subject: [PATCH 153/370] quote 1.20 to prevent from picking up 1.2 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5dcbe72fd8..69a0205b28 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.18, 1.19, 1.20] + go-version: [1.18, 1.19, "1.20"] runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 From c4faa10d8e6a8d77664a8755e52b53c4947c13a2 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 2 Feb 2023 07:40:59 +1100 Subject: [PATCH 154/370] quote all versions to prevent zeros missing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 69a0205b28..5ab9bcafbc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.18, 1.19, "1.20"] + go-version: ["1.18", "1.19", "1.20"] runs-on: ubuntu-latest steps: - uses: actions/setup-go@v3 From dd14318e5c72bb3d23a80fb91f07521afb7f14cd Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Wed, 1 Feb 2023 12:46:51 -0800 Subject: [PATCH 155/370] Add CheckDisks for disk encryption posture rule --- .changelog/1197.txt | 3 +++ device_posture_rule.go | 39 +++++++++++++++++++------------------ device_posture_rule_test.go | 4 +++- 3 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 .changelog/1197.txt diff --git a/.changelog/1197.txt b/.changelog/1197.txt new file mode 100644 index 0000000000..9535b0baeb --- /dev/null +++ b/.changelog/1197.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +teams_account: add support for `check_disks` +``` \ No newline at end of file diff --git a/device_posture_rule.go b/device_posture_rule.go index 288d5a2e53..83aedde75c 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -162,25 +162,26 @@ type DevicePostureRuleMatch struct { // DevicePostureRuleInput represents the value to be checked against. type DevicePostureRuleInput struct { - ID string `json:"id,omitempty"` - Path string `json:"path,omitempty"` - Exists bool `json:"exists,omitempty"` - Thumbprint string `json:"thumbprint,omitempty"` - Sha256 string `json:"sha256,omitempty"` - Running bool `json:"running,omitempty"` - RequireAll bool `json:"requireAll,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Version string `json:"version,omitempty"` - VersionOperator string `json:"versionOperator,omitempty"` - Overall string `json:"overall,omitempty"` - SensorConfig string `json:"sensor_config,omitempty"` - Os string `json:"os,omitempty"` - OsDistroName string `json:"os_distro_name,omitempty"` - OsDistroRevision string `json:"os_distro_revision,omitempty"` - Operator string `json:"operator,omitempty"` - Domain string `json:"domain,omitempty"` - ComplianceStatus string `json:"compliance_status,omitempty"` - ConnectionID string `json:"connection_id,omitempty"` + ID string `json:"id,omitempty"` + Path string `json:"path,omitempty"` + Exists bool `json:"exists,omitempty"` + Thumbprint string `json:"thumbprint,omitempty"` + Sha256 string `json:"sha256,omitempty"` + Running bool `json:"running,omitempty"` + RequireAll bool `json:"requireAll,omitempty"` + CheckDisks []string `json:"checkDisks,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Version string `json:"version,omitempty"` + VersionOperator string `json:"versionOperator,omitempty"` + Overall string `json:"overall,omitempty"` + SensorConfig string `json:"sensor_config,omitempty"` + Os string `json:"os,omitempty"` + OsDistroName string `json:"os_distro_name,omitempty"` + OsDistroRevision string `json:"os_distro_revision,omitempty"` + Operator string `json:"operator,omitempty"` + Domain string `json:"domain,omitempty"` + ComplianceStatus string `json:"compliance_status,omitempty"` + ConnectionID string `json:"connection_id,omitempty"` } // DevicePostureRuleListResponse represents the response from the list diff --git a/device_posture_rule_test.go b/device_posture_rule_test.go index 03be127215..c7ba0f4689 100644 --- a/device_posture_rule_test.go +++ b/device_posture_rule_test.go @@ -402,7 +402,8 @@ func TestDevicePostureDiskEncryptionRule(t *testing.T) { } ], "input": { - "requireAll": true + "requireAll": true, + "checkDisks": ["C", "D"] } } } @@ -419,6 +420,7 @@ func TestDevicePostureDiskEncryptionRule(t *testing.T) { Match: []DevicePostureRuleMatch{{Platform: "ios"}}, Input: DevicePostureRuleInput{ RequireAll: true, + CheckDisks: []string{"C", "D"}, }, } From bd092e4b0821a363d86e0fd9ca1d281a64fed9a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:00:54 +0000 Subject: [PATCH 156/370] build(deps): bump github.com/urfave/cli/v2 from 2.24.2 to 2.24.3 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.2 to 2.24.3. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.2...v2.24.3) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c17990053b..44c3b974d6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.24.2 + github.com/urfave/cli/v2 v2.24.3 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 086e241bc1..5cc537c34f 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.24.2 h1:q1VA+ofZ8SWfEKB9xXHUD4QZaeI9e+ItEqSbfH2JBXk= -github.com/urfave/cli/v2 v2.24.2/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.24.3 h1:7Q1w8VN8yE0MJEHP06bv89PjYsN4IHWED2s1v/Zlfm0= +github.com/urfave/cli/v2 v2.24.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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 669427c1f13a351202c50a2c37611f7cb0db0b62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 2 Feb 2023 16:01:10 +0000 Subject: [PATCH 157/370] add CHANGELOG for #1199 --- .changelog/1199.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1199.txt diff --git a/.changelog/1199.txt b/.changelog/1199.txt new file mode 100644 index 0000000000..f7cb743b3a --- /dev/null +++ b/.changelog/1199.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.24.2 to 2.24.3 +``` From 6b104674b1c20301148b35819981c5fc2b14461b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 2 Feb 2023 19:14:37 +0000 Subject: [PATCH 158/370] Update CHANGELOG.md for #1199 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46519f84c2..9a588d8c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ BUG FIXES: * dns: always send `tags` to allow clearing ([#1196](https://github.com/cloudflare/cloudflare-go/issues/1196)) +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.24.2 to 2.24.3 ([#1199](https://github.com/cloudflare/cloudflare-go/issues/1199)) + ## 0.60.0 (1st February, 2023) BREAKING CHANGES: From 84cd318d3842048f554295beff7fd6cdf3221132 Mon Sep 17 00:00:00 2001 From: Pierre Cauchois Date: Tue, 7 Feb 2023 13:03:44 -0800 Subject: [PATCH 159/370] Change allowed_match_count to int --- dlp_profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlp_profile.go b/dlp_profile.go index c08a6aa4d6..4eb0b5ff5c 100644 --- a/dlp_profile.go +++ b/dlp_profile.go @@ -41,7 +41,7 @@ type DLPProfile struct { Name string `json:"name,omitempty"` Type string `json:"type,omitempty"` Description string `json:"description,omitempty"` - AllowedMatchCount uint `json:"allowed_match_count"` + AllowedMatchCount int `json:"allowed_match_count"` // The following fields are omitted for predefined DLP // profiles From 775780c1afaf8035fab17d1da798cf29e0b3ba46 Mon Sep 17 00:00:00 2001 From: Pierre Cauchois Date: Tue, 7 Feb 2023 13:07:31 -0800 Subject: [PATCH 160/370] add changelog --- .changelog/1200.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1200.txt diff --git a/.changelog/1200.txt b/.changelog/1200.txt new file mode 100644 index 0000000000..40d4ec4b78 --- /dev/null +++ b/.changelog/1200.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dlp_profile: Use int rather than uint for allowed_match_count field +``` From a38234c1809b6cee06c2c22c2a6849cf0e9c0490 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 7 Feb 2023 21:25:44 +0000 Subject: [PATCH 161/370] Update CHANGELOG.md for #1200 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a588d8c25..0e2a58c999 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.61.0 (Unreleased) +ENHANCEMENTS: + +* dlp_profile: Use int rather than uint for allowed_match_count field ([#1200](https://github.com/cloudflare/cloudflare-go/issues/1200)) + BUG FIXES: * dns: always send `tags` to allow clearing ([#1196](https://github.com/cloudflare/cloudflare-go/issues/1196)) From edde9a58f3f1c59b891d016356c241daa561bb55 Mon Sep 17 00:00:00 2001 From: Lance726 <158132389@qq.com> Date: Wed, 8 Feb 2023 14:22:27 +0800 Subject: [PATCH 162/370] Fix typo --- stream.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stream.go b/stream.go index e12630495a..95edd6b5e7 100644 --- a/stream.go +++ b/stream.go @@ -101,7 +101,7 @@ type StreamUploadFromURLParameters struct { Creator string `json:"creator,omitempty"` ThumbnailTimestampPct float64 `json:"thumbnailTimestampPct,omitempty"` AllowedOrigins []string `json:"allowedOrigins,omitempty"` - RequiredSignedURLs bool `json:"requiredSignedURLs,omitempty"` + RequireSignedURLs bool `json:"requireSignedURLs,omitempty"` Watermark UploadVideoURLWatermark `json:"watermark,omitempty"` } @@ -113,7 +113,7 @@ type StreamCreateVideoParameters struct { Creator string `json:"creator,omitempty"` ThumbnailTimestampPct float64 `json:"thumbnailTimestampPct,omitempty"` AllowedOrigins []string `json:"allowedOrigins,omitempty"` - RequiredSignedURLs bool `json:"requiredSignedURLs,omitempty"` + RequireSignedURLs bool `json:"requireSignedURLs,omitempty"` Watermark UploadVideoURLWatermark `json:"watermark,omitempty"` } From 77e275bb755317a2ae323c76ed1136e8120cedf7 Mon Sep 17 00:00:00 2001 From: Lance726 <158132389@qq.com> Date: Wed, 8 Feb 2023 17:27:52 +0800 Subject: [PATCH 163/370] Add changelog --- .changelog/1202.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1202.txt diff --git a/.changelog/1202.txt b/.changelog/1202.txt new file mode 100644 index 0000000000..5ca3187ae7 --- /dev/null +++ b/.changelog/1202.txt @@ -0,0 +1,3 @@ +```release-note:bug +stream: fixed the RequiredSignedURLs field name errors +``` From dc841283dc5af6d7ba77999c8db4f86cb9e4c985 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Fri, 10 Feb 2023 12:57:32 -0500 Subject: [PATCH 164/370] Add new exclude_office_ips field to policy --- .changelog/1205.txt | 3 ++ devices_policy.go | 2 ++ devices_policy_test.go | 64 ++++++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 .changelog/1205.txt diff --git a/.changelog/1205.txt b/.changelog/1205.txt new file mode 100644 index 0000000000..2573522809 --- /dev/null +++ b/.changelog/1205.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +devices_policy: Add new exclude_office_ips field to policy +``` diff --git a/devices_policy.go b/devices_policy.go index 96d542125e..2e537757e1 100644 --- a/devices_policy.go +++ b/devices_policy.go @@ -42,6 +42,7 @@ type DeviceSettingsPolicy struct { Match *string `json:"match"` Precedence *int `json:"precedence"` Default bool `json:"default"` + ExcludeOfficeIps *bool `json:"exclude_office_ips"` } type DeviceSettingsPolicyResponse struct { @@ -68,6 +69,7 @@ type DeviceSettingsPolicyRequest struct { Name *string `json:"name,omitempty"` Match *string `json:"match,omitempty"` Enabled *bool `json:"enabled,omitempty"` + ExcludeOfficeIps *bool `json:"exclude_office_ips"` } // UpdateDeviceClientCertificates controls the zero trust zone used to provision client certificates. diff --git a/devices_policy_test.go b/devices_policy_test.go index 12bd073549..ac03a752c7 100644 --- a/devices_policy_test.go +++ b/devices_policy_test.go @@ -27,20 +27,21 @@ var ( {Address: "10.0.0.0/8"}, {Address: "100.64.0.0/10"}, }, - GatewayUniqueID: StringPtr("t1235"), - SupportURL: StringPtr(""), - CaptivePortal: IntPtr(180), - AllowModeSwitch: BoolPtr(false), - SwitchLocked: BoolPtr(false), - AllowUpdates: BoolPtr(false), - AutoConnect: IntPtr(0), - AllowedToLeave: BoolPtr(true), - Enabled: BoolPtr(true), - PolicyID: nil, - Name: nil, - Match: nil, - Precedence: nil, - Default: true, + GatewayUniqueID: StringPtr("t1235"), + SupportURL: StringPtr(""), + CaptivePortal: IntPtr(180), + AllowModeSwitch: BoolPtr(false), + SwitchLocked: BoolPtr(false), + AllowUpdates: BoolPtr(false), + AutoConnect: IntPtr(0), + AllowedToLeave: BoolPtr(true), + Enabled: BoolPtr(true), + PolicyID: nil, + Name: nil, + Match: nil, + Precedence: nil, + Default: true, + ExcludeOfficeIps: BoolPtr(false), } nonDefaultDeviceSettingsPolicy = DeviceSettingsPolicy{ @@ -56,20 +57,21 @@ var ( {Address: "10.0.0.0/8"}, {Address: "100.64.0.0/10"}, }, - GatewayUniqueID: StringPtr("t1235"), - SupportURL: StringPtr(""), - CaptivePortal: IntPtr(180), - AllowModeSwitch: BoolPtr(false), - SwitchLocked: BoolPtr(false), - AllowUpdates: BoolPtr(false), - AutoConnect: IntPtr(0), - AllowedToLeave: BoolPtr(true), - PolicyID: &deviceSettingsPolicyID, - Enabled: BoolPtr(true), - Name: StringPtr("test"), - Match: &deviceSettingsPolicyMatch, - Precedence: &deviceSettingsPolicyPrecedence, - Default: false, + GatewayUniqueID: StringPtr("t1235"), + SupportURL: StringPtr(""), + CaptivePortal: IntPtr(180), + AllowModeSwitch: BoolPtr(false), + SwitchLocked: BoolPtr(false), + AllowUpdates: BoolPtr(false), + AutoConnect: IntPtr(0), + AllowedToLeave: BoolPtr(true), + PolicyID: &deviceSettingsPolicyID, + Enabled: BoolPtr(true), + Name: StringPtr("test"), + Match: &deviceSettingsPolicyMatch, + Precedence: &deviceSettingsPolicyPrecedence, + Default: false, + ExcludeOfficeIps: BoolPtr(true), } defaultDeviceSettingsPolicyJson = `{ @@ -102,7 +104,8 @@ var ( "auto_connect": 0, "allowed_to_leave": true, "enabled": true, - "default": true + "default": true, + "exclude_office_ips":false }` nonDefaultDeviceSettingsPolicyJson = fmt.Sprintf(`{ @@ -139,7 +142,8 @@ var ( "name": "test", "match": %#v, "precedence": 10, - "default": false + "default": false, + "exclude_office_ips":true }`, deviceSettingsPolicyID, deviceSettingsPolicyMatch) ) From 112468accaa2aae0e08f2fdbfaf6810116dd435c Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 11:01:51 -0800 Subject: [PATCH 165/370] Add support for Pagination in Tunnels API Signed-off-by: Haytham Abuelfutuh --- tunnel.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tunnel.go b/tunnel.go index d933eedfc8..4fe68ac78a 100644 --- a/tunnel.go +++ b/tunnel.go @@ -5,7 +5,9 @@ import ( "encoding/json" "errors" "fmt" + "github.com/google/go-querystring/query" "net/http" + "strconv" "time" ) @@ -176,14 +178,28 @@ type TunnelListParams struct { // Tunnels lists all tunnels. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-list-cloudflare-tunnels -func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams) ([]Tunnel, error) { +func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams, opts ...ReqOption) ([]Tunnel, error) { if rc.Identifier == "" { return []Tunnel{}, ErrMissingAccountID } - uri := buildURI(fmt.Sprintf("/accounts/%s/cfd_tunnel", rc.Identifier), params) + v, _ := query.Values(params) + opt := reqOption{ + params: v, + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + for _, of := range opts { + of(&opt) + } + + if opt.params.Get("page") != "" || opt.params.Get("per_page") != "" { + return []Tunnel{}, errors.New(errManualPagination) + } + + opt.params.Add("per_page", strconv.Itoa(listZonesPerPage)) + + res, err := api.makeRequestContext(ctx, http.MethodGet, + fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, opt.params.Encode()), nil) if err != nil { return []Tunnel{}, err } From 47bccdb6e18d2cecefcb2cc5236d1dc26279bb5c Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 11:11:24 -0800 Subject: [PATCH 166/370] Add log Signed-off-by: Haytham Abuelfutuh --- tunnel.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tunnel.go b/tunnel.go index 4fe68ac78a..a955e40f30 100644 --- a/tunnel.go +++ b/tunnel.go @@ -198,8 +198,11 @@ func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params Tunne opt.params.Add("per_page", strconv.Itoa(listZonesPerPage)) + paramsStr := opt.params.Encode() + fmt.Printf("Issuing a cfd_tunnel query with params [%v]", paramsStr) + res, err := api.makeRequestContext(ctx, http.MethodGet, - fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, opt.params.Encode()), nil) + fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, paramsStr), nil) if err != nil { return []Tunnel{}, err } From 5c6a65b1a4ce05b44ae7f1877187ba8ade8c702a Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 11:24:41 -0800 Subject: [PATCH 167/370] Allow Tunnels() api to specify pagination options Signed-off-by: Haytham Abuelfutuh --- tunnel.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tunnel.go b/tunnel.go index a955e40f30..324749b552 100644 --- a/tunnel.go +++ b/tunnel.go @@ -7,7 +7,6 @@ import ( "fmt" "github.com/google/go-querystring/query" "net/http" - "strconv" "time" ) @@ -192,17 +191,8 @@ func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params Tunne of(&opt) } - if opt.params.Get("page") != "" || opt.params.Get("per_page") != "" { - return []Tunnel{}, errors.New(errManualPagination) - } - - opt.params.Add("per_page", strconv.Itoa(listZonesPerPage)) - - paramsStr := opt.params.Encode() - fmt.Printf("Issuing a cfd_tunnel query with params [%v]", paramsStr) - res, err := api.makeRequestContext(ctx, http.MethodGet, - fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, paramsStr), nil) + fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, opt.params.Encode()), nil) if err != nil { return []Tunnel{}, err } From 21e905bc3f0b9ffad51e92b647c3f78449edc04d Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 14:18:56 -0800 Subject: [PATCH 168/370] add a unit test Signed-off-by: Haytham Abuelfutuh --- tunnel_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tunnel_test.go b/tunnel_test.go index 48f8f386c6..612fee0305 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" "testing" "time" @@ -47,6 +48,52 @@ func TestTunnels(t *testing.T) { } } +func TestTunnelsPagination(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") + qry, _ := url.Parse(r.RequestURI) + assert.Equal(t, "blog", qry.Query().Get("name")) + assert.Equal(t, "2", qry.Query().Get("page")) + assert.Equal(t, "1", qry.Query().Get("per_page")) + fmt.Fprint(w, loadFixture("tunnel", "multiple_full")) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") + want := []Tunnel{ + { + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + Name: "blog", + CreatedAt: &createdAt, + DeletedAt: &deletedAt, + Connections: []TunnelConnection{{ + ColoName: "DFW", + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + IsPendingReconnect: false, + ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + ClientVersion: "2022.2.0", + OpenedAt: "2021-01-25T18:22:34.317854Z", + OriginIP: "198.51.100.1", + }}, + }, + } + + actual, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), + TunnelListParams{ + Name: "blog", + }, WithPagination(PaginationOptions{PerPage: 1, Page: 2})) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestTunnel(t *testing.T) { setup() defer teardown() From 31b23d3fce29e34eb7a18baa810e146300579971 Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 14:28:14 -0800 Subject: [PATCH 169/370] Add changelog file Signed-off-by: Haytham Abuelfutuh --- .changelog/1206.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1206.txt diff --git a/.changelog/1206.txt b/.changelog/1206.txt new file mode 100644 index 0000000000..fac539f068 --- /dev/null +++ b/.changelog/1206.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +tunnels: Added Pagination (through `WithPagination`) support to `Tunnels` API. +``` From 3d94d85220af478138b1c91f01c1ac018905663b Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Fri, 10 Feb 2023 14:29:56 -0800 Subject: [PATCH 170/370] goimports Signed-off-by: Haytham Abuelfutuh --- tunnel.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tunnel.go b/tunnel.go index 324749b552..0820a11a60 100644 --- a/tunnel.go +++ b/tunnel.go @@ -5,9 +5,10 @@ import ( "encoding/json" "errors" "fmt" - "github.com/google/go-querystring/query" "net/http" "time" + + "github.com/google/go-querystring/query" ) // ErrMissingTunnelID is for when a required tunnel ID is missing from the From b16e7afe80538b6ec165b07dc3eeb9f178a65de8 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Sat, 11 Feb 2023 12:06:40 +1100 Subject: [PATCH 171/370] cloudflare: make it clearer when we hit a server error and to retry later Occasionally, folks will hit an API endpoint that returns a 5xx for whatever reason. Instead of sending a vague and incorrect `could not read response body: %!w()` response, note that we hit the exception with the HTTP status code and to retry later in case it is a transient issue. --- .changelog/1207.txt | 3 +++ cloudflare.go | 13 ++----------- 2 files changed, 5 insertions(+), 11 deletions(-) create mode 100644 .changelog/1207.txt diff --git a/.changelog/1207.txt b/.changelog/1207.txt new file mode 100644 index 0000000000..7dd4bc7046 --- /dev/null +++ b/.changelog/1207.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cloudflare: make it clearer when we hit a server error and to retry later +``` diff --git a/cloudflare.go b/cloudflare.go index 5d69043257..e8d09ff697 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -266,18 +266,8 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m respErr = errors.New("exceeded available rate limit retries") } - // if we got a valid http response, try to read body so we can reuse the connection - // see https://golang.org/pkg/net/http/#Client.Do if respErr == nil { - respBody, err = io.ReadAll(resp.Body) - resp.Body.Close() - - respErr = fmt.Errorf("could not read response body: %w", err) - - api.logger.Printf("Request: %s %s got an error response %d: %s\n", method, uri, resp.StatusCode, - strings.Replace(strings.Replace(string(respBody), "\n", "", -1), "\t", "", -1)) - } else { - api.logger.Printf("Error performing request: %s %s : %s \n", method, uri, respErr.Error()) + respErr = fmt.Errorf("received %s response (HTTP %d), please try again later", strings.ToLower(http.StatusText(resp.StatusCode)), resp.StatusCode) } continue } else { @@ -286,6 +276,7 @@ func (api *API) makeRequestWithAuthTypeAndHeadersComplete(ctx context.Context, m if err != nil { return nil, fmt.Errorf("could not read response body: %w", err) } + break } } From 2f11f723e86db628c938e50fe260bc135340054b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sat, 11 Feb 2023 01:21:05 +0000 Subject: [PATCH 172/370] Update CHANGELOG.md for #1207 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e2a58c999..10d1d6b82e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* cloudflare: make it clearer when we hit a server error and to retry later ([#1207](https://github.com/cloudflare/cloudflare-go/issues/1207)) * dlp_profile: Use int rather than uint for allowed_match_count field ([#1200](https://github.com/cloudflare/cloudflare-go/issues/1200)) BUG FIXES: From 1385fe5defac70249e6c370f200215dc48940ca6 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sun, 12 Feb 2023 22:02:49 +0000 Subject: [PATCH 173/370] Update CHANGELOG.md for #1205 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10d1d6b82e..8286a86bb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * cloudflare: make it clearer when we hit a server error and to retry later ([#1207](https://github.com/cloudflare/cloudflare-go/issues/1207)) +* devices_policy: Add new exclude_office_ips field to policy ([#1205](https://github.com/cloudflare/cloudflare-go/issues/1205)) * dlp_profile: Use int rather than uint for allowed_match_count field ([#1200](https://github.com/cloudflare/cloudflare-go/issues/1200)) BUG FIXES: From b4affeda9bb066846660b3e5bcc1c27ad236f779 Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Mon, 13 Feb 2023 07:17:44 -0800 Subject: [PATCH 174/370] Comply with next-gen-client doc style Signed-off-by: Haytham Abuelfutuh --- tunnel.go | 55 +++++++++++++++++++++++++++++++++----------------- tunnel_test.go | 10 ++++++--- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/tunnel.go b/tunnel.go index 0820a11a60..4085958ead 100644 --- a/tunnel.go +++ b/tunnel.go @@ -7,8 +7,6 @@ import ( "fmt" "net/http" "time" - - "github.com/google/go-querystring/query" ) // ErrMissingTunnelID is for when a required tunnel ID is missing from the @@ -53,8 +51,12 @@ type TunnelConnection struct { type TunnelsDetailResponse struct { Result []Tunnel `json:"result"` Response + ResultInfo } +// listTunnelsDefaultPageSize represents the default per_page size of the API. +var listTunnelsDefaultPageSize int = 100 + // TunnelDetailResponse is used for representing the API response payload for // a single tunnel. type TunnelDetailResponse struct { @@ -173,37 +175,54 @@ type TunnelListParams struct { UUID string `url:"uuid,omitempty"` // the tunnel ID IsDeleted *bool `url:"is_deleted,omitempty"` ExistedAt *time.Time `url:"existed_at,omitempty"` + + ResultInfo } // Tunnels lists all tunnels. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-list-cloudflare-tunnels -func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams, opts ...ReqOption) ([]Tunnel, error) { +func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams) ([]Tunnel, *ResultInfo, error) { if rc.Identifier == "" { - return []Tunnel{}, ErrMissingAccountID + return []Tunnel{}, &ResultInfo{}, ErrMissingAccountID } - v, _ := query.Values(params) - opt := reqOption{ - params: v, + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false } - for _, of := range opts { - of(&opt) + if params.PerPage < 1 { + params.PerPage = listTunnelsDefaultPageSize } - res, err := api.makeRequestContext(ctx, http.MethodGet, - fmt.Sprintf("/accounts/%s/cfd_tunnel?%s", rc.Identifier, opt.params.Encode()), nil) - if err != nil { - return []Tunnel{}, err + if params.Page < 1 { + params.Page = 1 } - var argoDetailsResponse TunnelsDetailResponse - err = json.Unmarshal(res, &argoDetailsResponse) - if err != nil { - return []Tunnel{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + var records []Tunnel + var listResponse TunnelsDetailResponse + + for { + uri := buildURI(fmt.Sprintf("/accounts/%s/cfd_tunnel", rc.Identifier), params) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []Tunnel{}, &ResultInfo{}, err + } + + err = json.Unmarshal(res, &listResponse) + if err != nil { + return []Tunnel{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + records = append(records, listResponse.Result...) + params.ResultInfo = listResponse.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } } - return argoDetailsResponse.Result, nil + + return records, &listResponse.ResultInfo, nil } // Tunnel returns a single Argo tunnel. diff --git a/tunnel_test.go b/tunnel_test.go index 612fee0305..5e62910471 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -41,7 +41,7 @@ func TestTunnels(t *testing.T) { }}, }} - actual, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + actual, _, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -84,10 +84,14 @@ func TestTunnelsPagination(t *testing.T) { }, } - actual, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), + actual, _, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{ Name: "blog", - }, WithPagination(PaginationOptions{PerPage: 1, Page: 2})) + ResultInfo: ResultInfo{ + Page: 2, + PerPage: 1, + }, + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) From 0a96951570843c9104cf842213e600b8e7770f68 Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Mon, 13 Feb 2023 12:19:50 -0500 Subject: [PATCH 175/370] Support root_certificate_installation_enabled flag --- .changelog/1208.txt | 3 +++ teams_accounts.go | 5 +++-- teams_accounts_test.go | 19 +++++++++++-------- 3 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 .changelog/1208.txt diff --git a/.changelog/1208.txt b/.changelog/1208.txt new file mode 100644 index 0000000000..8075ecc793 --- /dev/null +++ b/.changelog/1208.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +teams_accounts: Add new root_certificate_installation_enabled field +``` diff --git a/teams_accounts.go b/teams_accounts.go index f90707147c..7667a155be 100644 --- a/teams_accounts.go +++ b/teams_accounts.go @@ -97,8 +97,9 @@ type TeamsLoggingSettings struct { } type TeamsDeviceSettings struct { - GatewayProxyEnabled bool `json:"gateway_proxy_enabled"` - GatewayProxyUDPEnabled bool `json:"gateway_udp_proxy_enabled"` + GatewayProxyEnabled bool `json:"gateway_proxy_enabled"` + GatewayProxyUDPEnabled bool `json:"gateway_udp_proxy_enabled"` + RootCertificateInstallationEnabled bool `json:"root_certificate_installation_enabled"` } type TeamsDeviceSettingsResponse struct { diff --git a/teams_accounts_test.go b/teams_accounts_test.go index a9535528bf..1741217355 100644 --- a/teams_accounts_test.go +++ b/teams_accounts_test.go @@ -239,7 +239,7 @@ func TestTeamsAccountGetDeviceConfiguration(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": {"gateway_proxy_enabled": true,"gateway_udp_proxy_enabled":false} + "result": {"gateway_proxy_enabled": true,"gateway_udp_proxy_enabled":false, "root_certificate_installation_enabled":true} }`) } @@ -249,8 +249,9 @@ func TestTeamsAccountGetDeviceConfiguration(t *testing.T) { if assert.NoError(t, err) { assert.Equal(t, actual, TeamsDeviceSettings{ - GatewayProxyEnabled: true, - GatewayProxyUDPEnabled: false, + GatewayProxyEnabled: true, + GatewayProxyUDPEnabled: false, + RootCertificateInstallationEnabled: true, }) } } @@ -266,21 +267,23 @@ func TestTeamsAccountUpdateDeviceConfiguration(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": {"gateway_proxy_enabled": true,"gateway_udp_proxy_enabled":true} + "result": {"gateway_proxy_enabled": true,"gateway_udp_proxy_enabled":true, "root_certificate_installation_enabled":true} }`) } mux.HandleFunc("/accounts/"+testAccountID+"/devices/settings", handler) actual, err := client.TeamsAccountDeviceUpdateConfiguration(context.Background(), testAccountID, TeamsDeviceSettings{ - GatewayProxyUDPEnabled: true, - GatewayProxyEnabled: true, + GatewayProxyUDPEnabled: true, + GatewayProxyEnabled: true, + RootCertificateInstallationEnabled: true, }) if assert.NoError(t, err) { assert.Equal(t, actual, TeamsDeviceSettings{ - GatewayProxyEnabled: true, - GatewayProxyUDPEnabled: true, + GatewayProxyEnabled: true, + GatewayProxyUDPEnabled: true, + RootCertificateInstallationEnabled: true, }) } } From 9b2e28902df2e0c1e987f278a65dba27c0a21ac7 Mon Sep 17 00:00:00 2001 From: Dawson Hensel Date: Tue, 14 Feb 2023 14:56:17 -0800 Subject: [PATCH 176/370] Support for DEX Tests --- .changelog/1208.txt | 3 + devices_dex.go | 174 +++++++++++++++++++++++++++++++++++ devices_dex_test.go | 220 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 397 insertions(+) create mode 100644 .changelog/1208.txt create mode 100644 devices_dex.go create mode 100644 devices_dex_test.go diff --git a/.changelog/1208.txt b/.changelog/1208.txt new file mode 100644 index 0000000000..bc83d55374 --- /dev/null +++ b/.changelog/1208.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dex_test: add CRUD functionality for DEX test configurations +``` \ No newline at end of file diff --git a/devices_dex.go b/devices_dex.go new file mode 100644 index 0000000000..0bdae1107a --- /dev/null +++ b/devices_dex.go @@ -0,0 +1,174 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +type Data map[string]interface{} + +type DeviceDexTest struct { + TestID string `json:"test_id"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Interval string `json:"interval"` + Enabled bool `json:"enabled"` + Updated time.Time `json:"updated"` + Created time.Time `json:"created"` + Data *Data `json:"data"` +} + +type DeviceDexTests struct { + DexTests []DeviceDexTest `json:"dex_tests"` +} + +type DeviceDexTestResponse struct { + Response + Result DeviceDexTest `json:"result"` +} + +type DeviceDexTestListResponse struct { + Response + Result DeviceDexTests `json:"result"` +} + +type ListDeviceDexTestParams struct{} + +type CreateDeviceDexTestParams struct { + TestID string `json:"network_id,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Interval string `json:"interval"` + Enabled bool `json:"enabled"` + Data *Data `json:"data"` +} + +type UpdateDeviceDexTestParams struct { + TestID string `json:"network_id,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Interval string `json:"interval"` + Enabled bool `json:"enabled"` + Data *Data `json:"data"` +} + +// ListDexTests returns all Device Managed Networks for a given +// account. +// +// API reference : https://developers.cloudflare.com/api/operations/device-dex-test-details +func (api *API) ListDexTests(ctx context.Context, rc *ResourceContainer, params ListDeviceDexTestParams) (DeviceDexTests, error) { + if rc.Level != AccountRouteLevel { + return DeviceDexTests{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/dex_tests", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return DeviceDexTests{}, err + } + + var response DeviceDexTestListResponse + err = json.Unmarshal(res, &response) + if err != nil { + return DeviceDexTests{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// CreateDeviceDexTest creates a new Device Managed Network. +// +// API reference: https://developers.cloudflare.com/api/operations/device-dex-test-create-device-dex-test +func (api *API) CreateDeviceDexTest(ctx context.Context, rc *ResourceContainer, params CreateDeviceDexTestParams) (DeviceDexTest, error) { + if rc.Level != AccountRouteLevel { + return DeviceDexTest{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/dex_tests", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return DeviceDexTest{}, err + } + + var deviceDexTestResponse DeviceDexTestResponse + if err := json.Unmarshal(res, &deviceDexTestResponse); err != nil { + return DeviceDexTest{}, fmt.Errorf("%s: %w\n\nres: %s", errUnmarshalError, err, string(res)) + } + + return deviceDexTestResponse.Result, err +} + +// UpdateDeviceDexTest Update a Device Managed Network. +// +// API reference: https://developers.cloudflare.com/api/operations/device-dex-test-update-device-dex-test +func (api *API) UpdateDeviceDexTest(ctx context.Context, rc *ResourceContainer, params UpdateDeviceDexTestParams) (DeviceManagedNetwork, error) { + if rc.Level != AccountRouteLevel { + return DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/dex_tests/%s", rc.Level, rc.Identifier, params.TestID) + + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) + if err != nil { + return DeviceManagedNetwork{}, err + } + + var deviceManagedNetworksResponse DeviceManagedNetworkResponse + + if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { + return DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return deviceManagedNetworksResponse.Result, err +} + +// GetDeviceDexTest gets a single Device Managed Network. +// +// API reference: https://developers.cloudflare.com/api/operations/device-dex-test-get-device-dex-test +func (api *API) GetDeviceDexTest(ctx context.Context, rc *ResourceContainer, testID string) (DeviceDexTest, error) { + if rc.Level != AccountRouteLevel { + return DeviceDexTest{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/dex_tests/%s", rc.Level, rc.Identifier, testID) + + deviceDexTestResponse := DeviceDexTestResponse{} + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return DeviceDexTest{}, err + } + + if err := json.Unmarshal(res, &deviceDexTestResponse); err != nil { + return DeviceDexTest{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return deviceDexTestResponse.Result, err +} + +// DeleteDexTest deletes a Device Managed Network. +// +// API reference: https://developers.cloudflare.com/api/operations/device-dex-test-delete-device-dex-test +func (api *API) DeleteDexTest(ctx context.Context, rc *ResourceContainer, testID string) (DeviceDexTests, error) { + if rc.Level != AccountRouteLevel { + return DeviceDexTests{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/devices/dex_tests/%s", rc.Level, rc.Identifier, testID) + + res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return DeviceDexTests{}, err + } + + var response DeviceDexTestListResponse + if err := json.Unmarshal(res, &response); err != nil { + return DeviceDexTests{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, err +} diff --git a/devices_dex_test.go b/devices_dex_test.go new file mode 100644 index 0000000000..2a61ff743c --- /dev/null +++ b/devices_dex_test.go @@ -0,0 +1,220 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +const testID = "f174e90a-fafe-4643-bbbc-4a0ed4fc8415" + +var dexTimestamp, _ = time.Parse(time.RFC3339, "2023-01-30T19:59:44.401278Z") + +func TestGetDeviceDexTests(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": { + "dex_tests": [ + { + "test_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "name": "http test dash", + "description": "dex test description", + "interval": "0h30m0s", + "enabled": true, + "data": { + "host": "https://dash.cloudflare.com", + "kind": "http", + "method": "GET" + }, + "updated": "2023-01-30T19:59:44.401278Z", + "created": "2023-01-30T19:59:44.401278Z" + } + ] + } + }`) + } + + dexTest := []DeviceDexTest{{ + TestID: testID, + Name: "http test dash", + Description: "dex test description", + Interval: "0h30m0s", + Enabled: true, + Data: &Data{ + "kind": "http", + "method": "GET", + "host": "https://dash.cloudflare.com", + }, + Updated: dexTimestamp, + Created: dexTimestamp, + }} + + want := DeviceDexTests{ + DexTests: dexTest, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/dex_tests", handler) + + actual, err := client.ListDexTests(context.Background(), AccountIdentifier(testAccountID), ListDeviceDexTestParams{}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeviceDexTest(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": { + "test_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "name": "http test dash", + "description": "dex test description", + "interval": "0h30m0s", + "enabled": true, + "data": { + "host": "https://dash.cloudflare.com", + "kind": "http", + "method": "GET" + }, + "updated": "2023-01-30T19:59:44.401278Z", + "created": "2023-01-30T19:59:44.401278Z" + } + }`) + } + + want := DeviceDexTest{ + TestID: testID, + Name: "http test dash", + Description: "dex test description", + Interval: "0h30m0s", + Enabled: true, + Data: &Data{ + "kind": "http", + "method": "GET", + "host": "https://dash.cloudflare.com", + }, + Updated: dexTimestamp, + Created: dexTimestamp, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/dex_tests/"+testID, handler) + + actual, err := client.GetDeviceDexTest(context.Background(), AccountIdentifier(testAccountID), testID) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestCreateDeviceDexTest(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "test_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "name": "http test dash", + "description": "dex test description", + "interval": "0h30m0s", + "enabled": true, + "data": { + "host": "https://dash.cloudflare.com", + "kind": "http", + "method": "GET" + }, + "updated": "2023-01-30T19:59:44.401278Z", + "created": "2023-01-30T19:59:44.401278Z" + } + }`) + } + + want := DeviceDexTest{ + TestID: testID, + Name: "http test dash", + Description: "dex test description", + Interval: "0h30m0s", + Enabled: true, + Data: &Data{ + "kind": "http", + "method": "GET", + "host": "https://dash.cloudflare.com", + }, + Updated: dexTimestamp, + Created: dexTimestamp, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/dex_tests", handler) + + actual, err := client.CreateDeviceDexTest(context.Background(), AccountIdentifier(testAccountID), CreateDeviceDexTestParams{ + TestID: testID, + Name: "http test dash", + Description: "dex test description", + Interval: "0h30m0s", + Enabled: true, + Data: &Data{ + "kind": "http", + "method": "GET", + "host": "https://dash.cloudflare.com", + }, + }) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteDeviceDexTest(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "dex_tests": [] + } + }`) + } + + want := DeviceDexTests{ + DexTests: []DeviceDexTest{}, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/dex_tests/"+testID, handler) + + actual, err := client.DeleteDexTest(context.Background(), AccountIdentifier(testAccountID), testID) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From b50c21a003bee8cbc3a1501c97979144698d30cb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 15 Feb 2023 15:37:53 +1100 Subject: [PATCH 177/370] update changelog --- .changelog/1202.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1202.txt b/.changelog/1202.txt index 5ca3187ae7..58c21d62c2 100644 --- a/.changelog/1202.txt +++ b/.changelog/1202.txt @@ -1,3 +1,3 @@ ```release-note:bug -stream: fixed the RequiredSignedURLs field name errors +stream: renamed `RequiredSignedURLs` to `RequireSignedURLs` ``` From a83da12e605a33a7f7d8e219e0b0ca16dd74e123 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 15 Feb 2023 04:42:42 +0000 Subject: [PATCH 178/370] Update CHANGELOG.md for #1202 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8286a86bb4..531d69a481 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: BUG FIXES: * dns: always send `tags` to allow clearing ([#1196](https://github.com/cloudflare/cloudflare-go/issues/1196)) +* stream: renamed `RequiredSignedURLs` to `RequireSignedURLs` ([#1202](https://github.com/cloudflare/cloudflare-go/issues/1202)) DEPENDENCIES: From 635d95a8ac1dd5b6c5ef8db53148c18b2264dfeb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 15 Feb 2023 15:43:37 +1100 Subject: [PATCH 179/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531d69a481..284b44c97f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.61.0 (Unreleased) +## 0.62.0 (Unreleased) + +## 0.61.0 (15th February, 2023) ENHANCEMENTS: From 0f2cd6570672e5b618bad2abe06ae4534f626205 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 16 Feb 2023 02:22:27 +0000 Subject: [PATCH 180/370] Update CHANGELOG.md for #1208 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 284b44c97f..b580146cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.62.0 (Unreleased) +ENHANCEMENTS: + +* teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) + ## 0.61.0 (15th February, 2023) ENHANCEMENTS: From 5bc3303eb1757538925e1a109ede0f5575c006e0 Mon Sep 17 00:00:00 2001 From: Haytham Abuelfutuh Date: Thu, 16 Feb 2023 07:27:50 -0800 Subject: [PATCH 181/370] Fix response object and testData response to have correct sample Signed-off-by: Haytham Abuelfutuh --- testdata/fixtures/tunnel/multiple_full.json | 8 +++++++- tunnel.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/testdata/fixtures/tunnel/multiple_full.json b/testdata/fixtures/tunnel/multiple_full.json index 409911a8f2..586dd9003a 100644 --- a/testdata/fixtures/tunnel/multiple_full.json +++ b/testdata/fixtures/tunnel/multiple_full.json @@ -20,5 +20,11 @@ } ] } - ] + ], + "result_info": { + "count": 1, + "page": 1, + "per_page": 20, + "total_count": 1 + } } diff --git a/tunnel.go b/tunnel.go index 4085958ead..8ae91d391d 100644 --- a/tunnel.go +++ b/tunnel.go @@ -51,7 +51,7 @@ type TunnelConnection struct { type TunnelsDetailResponse struct { Result []Tunnel `json:"result"` Response - ResultInfo + ResultInfo `json:"result_info"` } // listTunnelsDefaultPageSize represents the default per_page size of the API. From bdc379e766dc94ffe8460e1dac6e2c223e2844a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:56:59 +0000 Subject: [PATCH 182/370] build(deps): bump github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.3 to 2.24.4. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.3...v2.24.4) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 44c3b974d6..4731b3bea1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.2 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.24.3 + github.com/urfave/cli/v2 v2.24.4 golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index 5cc537c34f..dd22cce7c2 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/urfave/cli/v2 v2.24.3 h1:7Q1w8VN8yE0MJEHP06bv89PjYsN4IHWED2s1v/Zlfm0= -github.com/urfave/cli/v2 v2.24.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.24.4 h1:0gyJJEBYtCV87zI/x2nZCPyDxD51K6xM8SkwjHFCNEU= +github.com/urfave/cli/v2 v2.24.4/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.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= From 119b749bd47ba7803feaf3075b20a924166c5d56 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Feb 2023 16:57:17 +0000 Subject: [PATCH 183/370] add CHANGELOG for #1210 --- .changelog/1210.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1210.txt diff --git a/.changelog/1210.txt b/.changelog/1210.txt new file mode 100644 index 0000000000..a05f5531d1 --- /dev/null +++ b/.changelog/1210.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 +``` From 57d9aea2885c4cd3ba2507f2dbeb97e654388833 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 16 Feb 2023 21:01:20 +0000 Subject: [PATCH 184/370] Update CHANGELOG.md for #1210 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b580146cc1..504996e2c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ENHANCEMENTS: * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) +DEPENDENCIES: + +* deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) + ## 0.61.0 (15th February, 2023) ENHANCEMENTS: From 1856cd47677090e29dbe9cf816cc9420e0b0bc46 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 16 Feb 2023 23:51:19 +0000 Subject: [PATCH 185/370] Update CHANGELOG.md for #1209 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 504996e2c9..ef907c98c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* dex_test: add CRUD functionality for DEX test configurations ([#1209](https://github.com/cloudflare/cloudflare-go/issues/1209)) * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) DEPENDENCIES: From 6b5ab567dc35cb66b1dd60915e92aa79b6c02f0b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 17 Feb 2023 10:51:51 +1100 Subject: [PATCH 186/370] update changelog --- .changelog/1206.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1206.txt b/.changelog/1206.txt index fac539f068..fb12a08ebe 100644 --- a/.changelog/1206.txt +++ b/.changelog/1206.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -tunnels: Added Pagination (through `WithPagination`) support to `Tunnels` API. +tunnels: automatically paginate `ListTunnels` ``` From 44062f11f38476ed3432cf2fdaceeb0cef5d5c9c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 16 Feb 2023 23:56:05 +0000 Subject: [PATCH 187/370] Update CHANGELOG.md for #1206 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef907c98c5..792686e249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ENHANCEMENTS: * dex_test: add CRUD functionality for DEX test configurations ([#1209](https://github.com/cloudflare/cloudflare-go/issues/1209)) * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) +* tunnels: automatically paginate `ListTunnels` ([#1206](https://github.com/cloudflare/cloudflare-go/issues/1206)) DEPENDENCIES: From e51150855b8af9d5d72a78cd5492734d3e87624a Mon Sep 17 00:00:00 2001 From: Dawson Hensel Date: Tue, 21 Feb 2023 14:55:28 -0800 Subject: [PATCH 188/370] Fix update function to use dex types rather than managed networks. --- devices_dex.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/devices_dex.go b/devices_dex.go index d04a840289..f95cb9b5cf 100644 --- a/devices_dex.go +++ b/devices_dex.go @@ -38,7 +38,7 @@ type DeviceDexTestListResponse struct { type ListDeviceDexTestParams struct{} type CreateDeviceDexTestParams struct { - TestID string `json:"network_id,omitempty"` + TestID string `json:"test_id,omitempty"` Name string `json:"name"` Description string `json:"description,omitempty"` Interval string `json:"interval"` @@ -47,7 +47,7 @@ type CreateDeviceDexTestParams struct { } type UpdateDeviceDexTestParams struct { - TestID string `json:"network_id,omitempty"` + TestID string `json:"test_id,omitempty"` Name string `json:"name"` Description string `json:"description,omitempty"` Interval string `json:"interval"` @@ -105,25 +105,25 @@ func (api *API) CreateDeviceDexTest(ctx context.Context, rc *ResourceContainer, // UpdateDeviceDexTest Updates a Device Dex Test. // // API reference: https://developers.cloudflare.com/api/operations/device-dex-test-update-device-dex-test -func (api *API) UpdateDeviceDexTest(ctx context.Context, rc *ResourceContainer, params UpdateDeviceDexTestParams) (DeviceManagedNetwork, error) { +func (api *API) UpdateDeviceDexTest(ctx context.Context, rc *ResourceContainer, params UpdateDeviceDexTestParams) (DeviceDexTest, error) { if rc.Level != AccountRouteLevel { - return DeviceManagedNetwork{}, ErrRequiredAccountLevelResourceContainer + return DeviceDexTest{}, ErrRequiredAccountLevelResourceContainer } uri := fmt.Sprintf("/%s/%s/devices/dex_tests/%s", rc.Level, rc.Identifier, params.TestID) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { - return DeviceManagedNetwork{}, err + return DeviceDexTest{}, err } - var deviceManagedNetworksResponse DeviceManagedNetworkResponse + var deviceDexTestsResponse DeviceDexTestResponse - if err := json.Unmarshal(res, &deviceManagedNetworksResponse); err != nil { - return DeviceManagedNetwork{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + if err := json.Unmarshal(res, &deviceDexTestsResponse); err != nil { + return DeviceDexTest{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return deviceManagedNetworksResponse.Result, err + return deviceDexTestsResponse.Result, err } // GetDeviceDexTest gets a single Device Dex Test. From b69977c93608ed6b75321c4eaf9ce7ac4f6afb30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 08:59:50 +0000 Subject: [PATCH 189/370] build(deps): bump golang.org/x/text from 0.3.7 to 0.3.8 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 3 +-- go.sum | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4731b3bea1..26fb6abb57 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/text v0.3.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index dd22cce7c2..06aab3d1b6 100644 --- a/go.sum +++ b/go.sum @@ -64,24 +64,41 @@ github.com/urfave/cli/v2 v2.24.4 h1:0gyJJEBYtCV87zI/x2nZCPyDxD51K6xM8SkwjHFCNEU= github.com/urfave/cli/v2 v2.24.4/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= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 50665f81cd832848a2fbcfff3effe25e1596fc8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Feb 2023 09:00:11 +0000 Subject: [PATCH 190/370] add CHANGELOG for #1215 --- .changelog/1215.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1215.txt diff --git a/.changelog/1215.txt b/.changelog/1215.txt new file mode 100644 index 0000000000..44307cf98b --- /dev/null +++ b/.changelog/1215.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 +``` From bffd984d0d07bd9f519ff867c36903ff7f5cdc4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 10:33:03 +0000 Subject: [PATCH 191/370] build(deps): bump golang.org/x/text in /internal/tools Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: indirect ... Signed-off-by: dependabot[bot] --- internal/tools/go.mod | 2 +- internal/tools/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 1dfd729e85..75fe7ad3e4 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -225,7 +225,7 @@ require ( golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/text v0.3.8 // indirect golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect golang.org/x/tools v0.1.13-0.20220812184215-3f9b119300de // indirect golang.org/x/vuln v0.0.0-20220725105440-4151a5aca1df // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index f5841ad108..c9d927c13a 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -1115,8 +1115,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From d514d19e8213e290b1873680033a35768e43c8a7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 23 Feb 2023 10:33:22 +0000 Subject: [PATCH 192/370] add CHANGELOG for #1216 --- .changelog/1216.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1216.txt diff --git a/.changelog/1216.txt b/.changelog/1216.txt new file mode 100644 index 0000000000..44307cf98b --- /dev/null +++ b/.changelog/1216.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 +``` From f5d05436638df6dbc17b3c2f2548352b457ee810 Mon Sep 17 00:00:00 2001 From: Alyssa Wang Date: Tue, 21 Feb 2023 15:11:52 -0800 Subject: [PATCH 193/370] Add teams rule setting untrusted cert action --- .changelog/1214.txt | 3 +++ teams_rules.go | 22 ++++++++++++++++++++++ teams_rules_test.go | 24 +++++++++++++++++++++--- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 .changelog/1214.txt diff --git a/.changelog/1214.txt b/.changelog/1214.txt new file mode 100644 index 0000000000..e41d1a146d --- /dev/null +++ b/.changelog/1214.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +teams_rules: Add `untrusted_cert` rule setting +``` \ No newline at end of file diff --git a/teams_rules.go b/teams_rules.go index 16c5134e2a..ecf20569b0 100644 --- a/teams_rules.go +++ b/teams_rules.go @@ -37,6 +37,20 @@ type TeamsRuleSettings struct { InsecureDisableDNSSECValidation bool `json:"insecure_disable_dnssec_validation"` EgressSettings *EgressSettings `json:"egress"` + + UntrustedCertSettings *UntrustedCertSettings `json:"untrusted_cert"` +} + +type TeamsGatewayUntrustedCertAction string + +const ( + UntrustedCertPassthrough TeamsGatewayUntrustedCertAction = "pass_through" + UntrustedCertBlock TeamsGatewayUntrustedCertAction = "block" + UntrustedCertError TeamsGatewayUntrustedCertAction = "error" +) + +type UntrustedCertSettings struct { + Action TeamsGatewayUntrustedCertAction `json:"action"` } type EgressSettings struct { @@ -109,6 +123,14 @@ func TeamsRulesActionValues() []string { } } +func TeamsRulesUntrustedCertActionValues() []string { + return []string{ + string(UntrustedCertPassthrough), + string(UntrustedCertBlock), + string(UntrustedCertError), + } +} + // TeamsRule represents an Teams wirefilter rule. type TeamsRule struct { ID string `json:"id,omitempty"` diff --git a/teams_rules_test.go b/teams_rules_test.go index e86642b2e0..167f16b067 100644 --- a/teams_rules_test.go +++ b/teams_rules_test.go @@ -50,7 +50,10 @@ func TestTeamsRules(t *testing.T) { "enforce": true, "duration": "15m0s" }, - "insecure_disable_dnssec_validation": false + "insecure_disable_dnssec_validation": false, + "untrusted_cert": { + "action": "error" + } } }, { @@ -78,7 +81,10 @@ func TestTeamsRules(t *testing.T) { "biso_admin_controls": null, "add_headers": null, "check_session": null, - "insecure_disable_dnssec_validation": true + "insecure_disable_dnssec_validation": true, + "untrusted_cert": { + "action": "pass_through" + } } } ] @@ -114,6 +120,9 @@ func TestTeamsRules(t *testing.T) { Duration: Duration{900 * time.Second}, }, InsecureDisableDNSSECValidation: false, + UntrustedCertSettings: &UntrustedCertSettings{ + Action: UntrustedCertError, + }, }, CreatedAt: &createdAt, UpdatedAt: &updatedAt, @@ -142,6 +151,9 @@ func TestTeamsRules(t *testing.T) { CheckSession: nil, // setting is invalid for block rules, just testing serialization here InsecureDisableDNSSECValidation: true, + UntrustedCertSettings: &UntrustedCertSettings{ + Action: UntrustedCertPassthrough, + }, }, CreatedAt: &createdAt, UpdatedAt: &updatedAt, @@ -196,7 +208,10 @@ func TestTeamsRule(t *testing.T) { "enforce": true, "duration": "15m0s" }, - "insecure_disable_dnssec_validation": false + "insecure_disable_dnssec_validation": false, + "untrusted_cert": { + "action": "block" + } } } } @@ -231,6 +246,9 @@ func TestTeamsRule(t *testing.T) { Duration: Duration{900 * time.Second}, }, InsecureDisableDNSSECValidation: false, + UntrustedCertSettings: &UntrustedCertSettings{ + Action: UntrustedCertBlock, + }, }, CreatedAt: &createdAt, UpdatedAt: &updatedAt, From 933c018961deb709dd9cba82dbe37bc5fcf085bc Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Feb 2023 08:46:55 +0000 Subject: [PATCH 194/370] Update CHANGELOG.md for #1216 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 792686e249..5111b054db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ENHANCEMENTS: DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) +* deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1215](https://github.com/cloudflare/cloudflare-go/issues/1215)) +* deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1216](https://github.com/cloudflare/cloudflare-go/issues/1216)) ## 0.61.0 (15th February, 2023) From 4bcf145ad2f3e23c674d1c40134b734adc689756 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 08:50:36 +0000 Subject: [PATCH 195/370] build(deps): bump golang.org/x/net in /internal/tools Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/commits/v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] --- internal/tools/go.mod | 6 +++--- internal/tools/go.sum | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 75fe7ad3e4..eb343b7063 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -222,10 +222,10 @@ require ( golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect - golang.org/x/text v0.3.8 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect golang.org/x/tools v0.1.13-0.20220812184215-3f9b119300de // indirect golang.org/x/vuln v0.0.0-20220725105440-4151a5aca1df // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index c9d927c13a..aeb2689f01 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -1005,8 +1005,8 @@ golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5o golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1103,10 +1103,10 @@ golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc= -golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1116,8 +1116,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 6d9ebe2fdb203a8ebfdfb22c379291654068f0b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Feb 2023 08:50:54 +0000 Subject: [PATCH 196/370] add CHANGELOG for #1219 --- .changelog/1219.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1219.txt diff --git a/.changelog/1219.txt b/.changelog/1219.txt new file mode 100644 index 0000000000..148e60cca6 --- /dev/null +++ b/.changelog/1219.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 +``` From d56cfe788c271134de234939bdab570d0c1c0bea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 08:51:50 +0000 Subject: [PATCH 197/370] build(deps): bump golang.org/x/time Bumps [golang.org/x/time](https://github.com/golang/time) from 0.0.0-20220224211638-0e9765cccd65 to 0.3.0. - [Release notes](https://github.com/golang/time/releases) - [Commits](https://github.com/golang/time/commits/v0.3.0) --- updated-dependencies: - dependency-name: golang.org/x/time dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 26fb6abb57..a7c1b7da4a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/urfave/cli/v2 v2.24.4 golang.org/x/net v0.0.0-20220722155237-a158d28d115b - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 + golang.org/x/time v0.3.0 ) require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 06aab3d1b6..c8e72ffd5e 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From f0b47908234e1edb7635855ac92066a95d66e0e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Feb 2023 08:52:08 +0000 Subject: [PATCH 198/370] add CHANGELOG for #1217 --- .changelog/1217.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1217.txt diff --git a/.changelog/1217.txt b/.changelog/1217.txt new file mode 100644 index 0000000000..0fc959900b --- /dev/null +++ b/.changelog/1217.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/time from 0.0.0-20220224211638-0e9765cccd65 to 0.3.0 +``` From aacd36a98b9d852d3a002ff5884b896c02524f79 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Feb 2023 08:52:38 +0000 Subject: [PATCH 199/370] Update CHANGELOG.md for #1219 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5111b054db..6472dd3b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) +* deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1219](https://github.com/cloudflare/cloudflare-go/issues/1219)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1215](https://github.com/cloudflare/cloudflare-go/issues/1215)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1216](https://github.com/cloudflare/cloudflare-go/issues/1216)) From 7005ef3db601e83958063d55860fc0302267f07a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Feb 2023 08:55:22 +0000 Subject: [PATCH 200/370] Update CHANGELOG.md for #1217 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6472dd3b5f..c402a3d2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ DEPENDENCIES: * deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1219](https://github.com/cloudflare/cloudflare-go/issues/1219)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1215](https://github.com/cloudflare/cloudflare-go/issues/1215)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1216](https://github.com/cloudflare/cloudflare-go/issues/1216)) +* deps: bumps golang.org/x/time from 0.0.0-20220224211638-0e9765cccd65 to 0.3.0 ([#1217](https://github.com/cloudflare/cloudflare-go/issues/1217)) ## 0.61.0 (15th February, 2023) From 7f096ea78bf9886754d831e6a2cf94ee54831a60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 09:05:09 +0000 Subject: [PATCH 201/370] build(deps): bump golang.org/x/net Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/commits/v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a7c1b7da4a..cb534c4cbb 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.1 github.com/urfave/cli/v2 v2.24.4 - golang.org/x/net v0.0.0-20220722155237-a158d28d115b + golang.org/x/net v0.7.0 golang.org/x/time v0.3.0 ) @@ -30,6 +30,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/text v0.3.8 // indirect + golang.org/x/text v0.7.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c8e72ffd5e..2cf3d40949 100644 --- a/go.sum +++ b/go.sum @@ -70,8 +70,9 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -84,15 +85,17 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc 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.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From cb7dac7c5a81522a3731018fcae74053dd534ecc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Feb 2023 09:05:23 +0000 Subject: [PATCH 202/370] add CHANGELOG for #1218 --- .changelog/1218.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1218.txt diff --git a/.changelog/1218.txt b/.changelog/1218.txt new file mode 100644 index 0000000000..148e60cca6 --- /dev/null +++ b/.changelog/1218.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 +``` From 7bf8adcc5f41a511b6d08c802f1ad01231ca649e Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Feb 2023 09:05:47 +0000 Subject: [PATCH 203/370] Update CHANGELOG.md for #1213 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c402a3d2e5..1640ed5b26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ ENHANCEMENTS: * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) * tunnels: automatically paginate `ListTunnels` ([#1206](https://github.com/cloudflare/cloudflare-go/issues/1206)) +BUG FIXES: + +* dex_test: use dex test types and json struct mappings instead of managed networks ([#1213](https://github.com/cloudflare/cloudflare-go/issues/1213)) + DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) From 7b7e6ab78e51c88408d9c39a305f1cbc1a038a5a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Feb 2023 09:22:20 +0000 Subject: [PATCH 204/370] Update CHANGELOG.md for #1218 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1640ed5b26..b178229963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ BUG FIXES: DEPENDENCIES: * deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) +* deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1218](https://github.com/cloudflare/cloudflare-go/issues/1218)) * deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1219](https://github.com/cloudflare/cloudflare-go/issues/1219)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1215](https://github.com/cloudflare/cloudflare-go/issues/1215)) * deps: bumps golang.org/x/text from 0.3.7 to 0.3.8 ([#1216](https://github.com/cloudflare/cloudflare-go/issues/1216)) From 72b3b6a27e35cb04676e26d19e8b9671eee57d87 Mon Sep 17 00:00:00 2001 From: Olivia Trewin Date: Tue, 3 Jan 2023 15:12:20 -0600 Subject: [PATCH 205/370] DLP-809: Add support for DLP payload logging rule/account settings --- .changelog/1212.txt | 3 ++ dlp_payload_log.go | 71 ++++++++++++++++++++++++++++++++++ dlp_payload_log_test.go | 84 +++++++++++++++++++++++++++++++++++++++++ teams_rules.go | 7 ++++ 4 files changed, 165 insertions(+) create mode 100644 .changelog/1212.txt create mode 100644 dlp_payload_log.go create mode 100644 dlp_payload_log_test.go diff --git a/.changelog/1212.txt b/.changelog/1212.txt new file mode 100644 index 0000000000..8656a47b4a --- /dev/null +++ b/.changelog/1212.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dlp: Adds support for partial payload logging +``` diff --git a/dlp_payload_log.go b/dlp_payload_log.go new file mode 100644 index 0000000000..34f37ca8cc --- /dev/null +++ b/dlp_payload_log.go @@ -0,0 +1,71 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +type DLPPayloadLogSettings struct { + PublicKey string `json:"public_key,omitempty"` + + // Only present in responses + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type GetDLPPayloadLogSettingsParams struct{} + +type DLPPayloadLogSettingsResponse struct { + Response + Result DLPPayloadLogSettings `json:"result"` +} + +// GetDLPPayloadLogSettings gets the current DLP payload logging settings. +// +// API reference: https://api.cloudflare.com/#dlp-payload-log-settings-get-settings +func (api *API) GetDLPPayloadLogSettings(ctx context.Context, rc *ResourceContainer, params GetDLPPayloadLogSettingsParams) (DLPPayloadLogSettings, error) { + if rc.Identifier == "" { + return DLPPayloadLogSettings{}, ErrMissingResourceIdentifier + } + + uri := buildURI(fmt.Sprintf("/%s/%s/dlp/payload_log", rc.Level, rc.Identifier), nil) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return DLPPayloadLogSettings{}, err + } + + var dlpPayloadLogSettingsResponse DLPPayloadLogSettingsResponse + err = json.Unmarshal(res, &dlpPayloadLogSettingsResponse) + if err != nil { + return DLPPayloadLogSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return dlpPayloadLogSettingsResponse.Result, nil +} + +// UpdateDLPPayloadLogSettings sets the current DLP payload logging settings to new values. +// +// API reference: https://api.cloudflare.com/#dlp-payload-log-settings-update-settings +func (api *API) UpdateDLPPayloadLogSettings(ctx context.Context, rc *ResourceContainer, settings DLPPayloadLogSettings) (DLPPayloadLogSettings, error) { + if rc.Identifier == "" { + return DLPPayloadLogSettings{}, ErrMissingResourceIdentifier + } + + uri := buildURI(fmt.Sprintf("/%s/%s/dlp/payload_log", rc.Level, rc.Identifier), nil) + + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, settings) + if err != nil { + return DLPPayloadLogSettings{}, err + } + + var dlpPayloadLogSettingsResponse DLPPayloadLogSettingsResponse + err = json.Unmarshal(res, &dlpPayloadLogSettingsResponse) + if err != nil { + return DLPPayloadLogSettings{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return dlpPayloadLogSettingsResponse.Result, nil +} diff --git a/dlp_payload_log_test.go b/dlp_payload_log_test.go new file mode 100644 index 0000000000..4ef505da49 --- /dev/null +++ b/dlp_payload_log_test.go @@ -0,0 +1,84 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetDLPPayloadLogSettings(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": { + "public_key": "3NP5MGKjzBLLceVxNZrF+LyithbWX+AVFBMRAA0Xl2A=", + "updated_at": "2022-12-22T21:02:39Z" + } + }`) + } + + updatedAt, _ := time.Parse(time.RFC3339, "2022-12-22T21:02:39Z") + + want := DLPPayloadLogSettings{ + PublicKey: "3NP5MGKjzBLLceVxNZrF+LyithbWX+AVFBMRAA0Xl2A=", + UpdatedAt: &updatedAt, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/dlp/payload_log", handler) + + actual, err := client.GetDLPPayloadLogSettings(context.Background(), AccountIdentifier(testAccountID), GetDLPPayloadLogSettingsParams{}) + require.NoError(t, err) + require.Equal(t, want, actual) +} + +func TestPutDLPPayloadLogSettings(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") + + var requestSettings DLPPayloadLogSettings + err := json.NewDecoder(r.Body).Decode(&requestSettings) + require.Nil(t, err) + + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "public_key": "`+requestSettings.PublicKey+`", + "updated_at": "2022-12-22T21:02:39Z" + } + }`) + } + + updatedAt, _ := time.Parse(time.RFC3339, "2022-12-22T21:02:39Z") + + want := DLPPayloadLogSettings{ + PublicKey: "3NP5MGKjzBLLceVxNZrF+LyithbWX+AVFBMRAA0Xl2A=", + UpdatedAt: &updatedAt, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/dlp/payload_log", handler) + + actual, err := client.UpdateDLPPayloadLogSettings(context.Background(), AccountIdentifier(testAccountID), DLPPayloadLogSettings{ + PublicKey: "3NP5MGKjzBLLceVxNZrF+LyithbWX+AVFBMRAA0Xl2A=", + }) + require.NoError(t, err) + require.Equal(t, want, actual) +} diff --git a/teams_rules.go b/teams_rules.go index 16c5134e2a..6fdf7cbcd9 100644 --- a/teams_rules.go +++ b/teams_rules.go @@ -37,6 +37,9 @@ type TeamsRuleSettings struct { InsecureDisableDNSSECValidation bool `json:"insecure_disable_dnssec_validation"` EgressSettings *EgressSettings `json:"egress"` + + // DLP payload logging configuration + PayloadLog *TeamsDlpPayloadLogSettings `json:"payload_log"` } type EgressSettings struct { @@ -64,6 +67,10 @@ type TeamsCheckSessionSettings struct { Duration Duration `json:"duration"` } +type TeamsDlpPayloadLogSettings struct { + Enabled bool `json:"enabled"` +} + type TeamsFilterType string type TeamsGatewayAction string From a12fc6e10255a274dbb85df10c3614e90b98d720 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sat, 25 Feb 2023 19:57:58 +0000 Subject: [PATCH 206/370] Update CHANGELOG.md for #1212 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b178229963..e1c90a1ff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * dex_test: add CRUD functionality for DEX test configurations ([#1209](https://github.com/cloudflare/cloudflare-go/issues/1209)) +* dlp: Adds support for partial payload logging ([#1212](https://github.com/cloudflare/cloudflare-go/issues/1212)) * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) * tunnels: automatically paginate `ListTunnels` ([#1206](https://github.com/cloudflare/cloudflare-go/issues/1206)) From a69882f4d21640f0986560bb83801d0a052eb364 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:57:16 +0000 Subject: [PATCH 207/370] build(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cb534c4cbb..2a470664d1 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ 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.1 + github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.24.4 golang.org/x/net v0.7.0 golang.org/x/time v0.3.0 diff --git a/go.sum b/go.sum index 2cf3d40949..97fa1297e5 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE 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.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +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.24.4 h1:0gyJJEBYtCV87zI/x2nZCPyDxD51K6xM8SkwjHFCNEU= github.com/urfave/cli/v2 v2.24.4/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= From 21d21cd146a57b77a4be24fee41c85b1bb2e94ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 27 Feb 2023 16:57:33 +0000 Subject: [PATCH 208/370] add CHANGELOG for #1220 --- .changelog/1220.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1220.txt diff --git a/.changelog/1220.txt b/.changelog/1220.txt new file mode 100644 index 0000000000..6f31f37add --- /dev/null +++ b/.changelog/1220.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/stretchr/testify from 1.8.1 to 1.8.2 +``` From 5c7e0d4ab6a1cb46185d8f1d0c2e97c48a732cf5 Mon Sep 17 00:00:00 2001 From: Adam Eastbury <91943050+MrMortbury@users.noreply.github.com> Date: Mon, 27 Feb 2023 19:12:03 +0000 Subject: [PATCH 209/370] Fix List DNS pagination proxy ptr issue --- dns.go | 6 ++- dns_test.go | 42 ++++++++++++++++++++- testdata/fixtures/dns/list_page_1.json | 52 ++++++++++++++++++++++++-- testdata/fixtures/dns/list_page_2.json | 35 ++++++++++++++--- 4 files changed, 122 insertions(+), 13 deletions(-) diff --git a/dns.go b/dns.go index aa8cc22840..d7bd308d7c 100644 --- a/dns.go +++ b/dns.go @@ -172,7 +172,7 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, param } var records []DNSRecord - var listResponse DNSListResponse + var lastResultInfo ResultInfo for { uri := buildURI(fmt.Sprintf("/zones/%s/dns_records", rc.Identifier), params) @@ -180,17 +180,19 @@ func (api *API) ListDNSRecords(ctx context.Context, rc *ResourceContainer, param if err != nil { return []DNSRecord{}, &ResultInfo{}, err } + var listResponse DNSListResponse err = json.Unmarshal(res, &listResponse) if err != nil { return []DNSRecord{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } records = append(records, listResponse.Result...) + lastResultInfo = listResponse.ResultInfo params.ResultInfo = listResponse.ResultInfo.Next() if params.ResultInfo.Done() || !autoPaginate { break } } - return records, &listResponse.ResultInfo, nil + return records, &lastResultInfo, nil } // ErrMissingDNSRecordID is for when DNS record ID is needed but not given. diff --git a/dns_test.go b/dns_test.go index 41b7c33350..46871f1626 100644 --- a/dns_test.go +++ b/dns_test.go @@ -347,7 +347,7 @@ func TestListDNSRecordsSearch(t *testing.T) { func TestListDNSRecordsPagination(t *testing.T) { // change listDNSRecordsDefaultPageSize value to 1 to force pagination - listDNSRecordsDefaultPageSize = 1 + listDNSRecordsDefaultPageSize = 3 setup() defer teardown() @@ -378,7 +378,45 @@ func TestListDNSRecordsPagination(t *testing.T) { require.NoError(t, err) assert.True(t, page1Called) assert.True(t, page2Called) - assert.Len(t, actual, 2) + assert.Len(t, actual, 5) + + type ls struct { + Results []map[string]interface{} `json:"result"` + } + + expectedRecords := make(map[string]map[string]interface{}) + + response1 := loadFixture("dns", "list_page_1") + var fixtureDataPage1 ls + err = json.Unmarshal([]byte(response1), &fixtureDataPage1) + assert.NoError(t, err) + for _, record := range fixtureDataPage1.Results { + expectedRecords[record["id"].(string)] = record + } + + response2 := loadFixture("dns", "list_page_2") + var fixtureDataPage2 ls + err = json.Unmarshal([]byte(response2), &fixtureDataPage2) + assert.NoError(t, err) + for _, record := range fixtureDataPage2.Results { + expectedRecords[record["id"].(string)] = record + } + + for _, actualRecord := range actual { + expected, exist := expectedRecords[actualRecord.ID] + assert.True(t, exist, "DNS record doesn't exist in fixtures") + assert.Equal(t, expected["type"].(string), actualRecord.Type) + assert.Equal(t, expected["name"].(string), actualRecord.Name) + assert.Equal(t, expected["content"].(string), actualRecord.Content) + assert.Equal(t, expected["proxiable"].(bool), actualRecord.Proxiable) + assert.Equal(t, expected["proxied"].(bool), *actualRecord.Proxied) + assert.Equal(t, int(expected["ttl"].(float64)), actualRecord.TTL) + assert.Equal(t, expected["locked"].(bool), actualRecord.Locked) + assert.Equal(t, expected["zone_id"].(string), actualRecord.ZoneID) + assert.Equal(t, expected["zone_name"].(string), actualRecord.ZoneName) + assert.Equal(t, expected["data"], actualRecord.Data) + assert.Equal(t, expected["meta"], actualRecord.Meta) + } } func TestGetDNSRecord(t *testing.T) { diff --git a/testdata/fixtures/dns/list_page_1.json b/testdata/fixtures/dns/list_page_1.json index 15acc55332..505577398b 100644 --- a/testdata/fixtures/dns/list_page_1.json +++ b/testdata/fixtures/dns/list_page_1.json @@ -25,13 +25,59 @@ "tag1", "tag2extended" ] + }, + { + "id": "7eb0a9821aec4b1395bd8cc03d88c17d", + "type": "A", + "name": "sub1.example.com", + "content": "198.51.100.5", + "proxiable": true, + "proxied": false, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": [ + "tag1", + "tag2extended" + ] + }, + { + "id": "4c2c40857e334a2d903dd28f65a99682", + "type": "A", + "name": "sub2.example.com", + "content": "198.51.100.6", + "proxiable": true, + "proxied": true, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": [ + "tag1", + "tag2extended" + ] } ], "result_info": { - "count": 1, + "count": 3, "page": 1, - "per_page": 1, - "total_count": 2, + "per_page": 3, + "total_count": 5, "total_pages": 2 } } diff --git a/testdata/fixtures/dns/list_page_2.json b/testdata/fixtures/dns/list_page_2.json index b7836c01c3..b866c825de 100644 --- a/testdata/fixtures/dns/list_page_2.json +++ b/testdata/fixtures/dns/list_page_2.json @@ -4,12 +4,35 @@ "messages": [], "result": [ { - "id": "372e67954025e0ba6aaa6d586b9e0b59", + "id": "97e1dc2d19204b448b6ee04724f005ba", "type": "A", - "name": "www.example.com", - "content": "198.51.100.4", + "name": "sub3.example.com", + "content": "198.51.100.7", "proxiable": true, - "proxied": true, + "proxied": false, + "ttl": 120, + "locked": false, + "zone_id": "d56084adb405e0b7e32c52321bf07be6", + "zone_name": "example.com", + "created_on": "2014-01-01T05:20:00Z", + "modified_on": "2014-01-01T05:20:00Z", + "data": {}, + "meta": { + "auto_added": true, + "source": "primary" + }, + "tags": [ + "tag1", + "tag2extended" + ] + }, + { + "id": "5bafaa7059d3480da9f6e2ecd8468c33", + "type": "A", + "name": "sub4.example.com", + "content": "198.51.100.8", + "proxiable": true, + "proxied": false, "ttl": 120, "locked": false, "zone_id": "d56084adb405e0b7e32c52321bf07be6", @@ -28,9 +51,9 @@ } ], "result_info": { - "count": 1, + "count": 2, "page": 2, - "per_page": 1, + "per_page": 3, "total_count": 2, "total_pages": 2 } From be2eab498b8bc7273fef7337313da41b340c737c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 27 Feb 2023 19:35:36 +0000 Subject: [PATCH 210/370] Update CHANGELOG.md for #1220 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c90a1ff3..a0f4809ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ BUG FIXES: DEPENDENCIES: +* deps: bumps github.com/stretchr/testify from 1.8.1 to 1.8.2 ([#1220](https://github.com/cloudflare/cloudflare-go/issues/1220)) * deps: bumps github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 ([#1210](https://github.com/cloudflare/cloudflare-go/issues/1210)) * deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1218](https://github.com/cloudflare/cloudflare-go/issues/1218)) * deps: bumps golang.org/x/net from 0.0.0-20220722155237-a158d28d115b to 0.7.0 ([#1219](https://github.com/cloudflare/cloudflare-go/issues/1219)) From f1357618a5e7b3479524e2e9d49ac82b346035dc Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 27 Feb 2023 20:47:22 +0000 Subject: [PATCH 211/370] Update CHANGELOG.md for #1214 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0f4809ded..12df81dd2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ENHANCEMENTS: * dex_test: add CRUD functionality for DEX test configurations ([#1209](https://github.com/cloudflare/cloudflare-go/issues/1209)) * dlp: Adds support for partial payload logging ([#1212](https://github.com/cloudflare/cloudflare-go/issues/1212)) * teams_accounts: Add new root_certificate_installation_enabled field ([#1208](https://github.com/cloudflare/cloudflare-go/issues/1208)) +* teams_rules: Add `untrusted_cert` rule setting ([#1214](https://github.com/cloudflare/cloudflare-go/issues/1214)) * tunnels: automatically paginate `ListTunnels` ([#1206](https://github.com/cloudflare/cloudflare-go/issues/1206)) BUG FIXES: From 2e3e59991f761eeabc5500cfa844fd0df31e80d8 Mon Sep 17 00:00:00 2001 From: Adam Eastbury <91943050+MrMortbury@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:49:43 +0000 Subject: [PATCH 212/370] Adding changelog entry --- .changelog/1221.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1221.txt diff --git a/.changelog/1221.txt b/.changelog/1221.txt new file mode 100644 index 0000000000..b07e654620 --- /dev/null +++ b/.changelog/1221.txt @@ -0,0 +1,3 @@ +```release-note:bug +DNS: dont reuse DNSListResponse when using pagination to avoid Proxied pointer overwrite +``` \ No newline at end of file From 1639b3b7009c56cda37fb814bb4900e6b2d79eec Mon Sep 17 00:00:00 2001 From: Adam Eastbury <91943050+MrMortbury@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:57:07 +0000 Subject: [PATCH 213/370] Correct typo in dns/list_page_2.json fixture --- testdata/fixtures/dns/list_page_2.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/fixtures/dns/list_page_2.json b/testdata/fixtures/dns/list_page_2.json index b866c825de..bb3d8f7277 100644 --- a/testdata/fixtures/dns/list_page_2.json +++ b/testdata/fixtures/dns/list_page_2.json @@ -54,7 +54,7 @@ "count": 2, "page": 2, "per_page": 3, - "total_count": 2, + "total_count": 5, "total_pages": 2 } } From 4e3f02a9aa174bc65af9b9bdcc8cd6cba2820be6 Mon Sep 17 00:00:00 2001 From: Adam Eastbury <91943050+MrMortbury@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:03:39 +0000 Subject: [PATCH 214/370] Rename changelog txt 1221 to 1222 to match PR --- .changelog/{1221.txt => 1222.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1221.txt => 1222.txt} (100%) diff --git a/.changelog/1221.txt b/.changelog/1222.txt similarity index 100% rename from .changelog/1221.txt rename to .changelog/1222.txt From cdc015f61a55d32d48d514ce68f78a26db71f49f Mon Sep 17 00:00:00 2001 From: Akemi Davisson Date: Tue, 28 Feb 2023 09:03:13 -0600 Subject: [PATCH 215/370] Adds new attr to Access App model --- access_application.go | 1 + access_application_test.go | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/access_application.go b/access_application.go index 9b5a6aac9f..e627fca27c 100644 --- a/access_application.go +++ b/access_application.go @@ -48,6 +48,7 @@ type AccessApplication struct { EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` } type AccessApplicationGatewayRule struct { diff --git a/access_application_test.go b/access_application_test.go index 608bd77e4d..ce488347d2 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -41,7 +41,8 @@ func TestAccessApplications(t *testing.T) { "logo_url": "https://www.example.com/example.png", "skip_interstitial": true, "app_launcher_visible": true, - "service_auth_401_redirect": true + "service_auth_401_redirect": true, + "path_cookie_attribute": true } ], "result_info": { @@ -77,6 +78,7 @@ func TestAccessApplications(t *testing.T) { HttpOnlyCookieAttribute: BoolPtr(true), LogoURL: "https://www.example.com/example.png", SkipInterstitial: BoolPtr(true), + PathCookieAttribute: BoolPtr(true), }} mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) @@ -125,7 +127,8 @@ func TestAccessApplication(t *testing.T) { "skip_interstitial": true, "app_launcher_visible": true, "service_auth_401_redirect": true, - "http_only_cookie_attribute": false + "http_only_cookie_attribute": false, + "path_cookie_attribute": false } } `) @@ -153,6 +156,7 @@ func TestAccessApplication(t *testing.T) { LogoURL: "https://www.example.com/example.png", SkipInterstitial: BoolPtr(true), HttpOnlyCookieAttribute: BoolPtr(false), + PathCookieAttribute: BoolPtr(false), } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) From 2f7e8d76e6a4d79466f509a5acdba75fa696eb64 Mon Sep 17 00:00:00 2001 From: Akemi Davisson Date: Tue, 28 Feb 2023 10:12:16 -0600 Subject: [PATCH 216/370] changelog --- .changelog/1223.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1223.txt diff --git a/.changelog/1223.txt b/.changelog/1223.txt new file mode 100644 index 0000000000..e046c338bc --- /dev/null +++ b/.changelog/1223.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access_application: Add `path_cookie_attribute` app setting +``` \ No newline at end of file From b75870fb6fc0a9afee6d259cb792be417269c66c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Mar 2023 08:58:07 +1100 Subject: [PATCH 217/370] update CHANGELOG --- .changelog/1222.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1222.txt b/.changelog/1222.txt index b07e654620..5d9a668a01 100644 --- a/.changelog/1222.txt +++ b/.changelog/1222.txt @@ -1,3 +1,3 @@ ```release-note:bug -DNS: dont reuse DNSListResponse when using pagination to avoid Proxied pointer overwrite +dns: dont reuse DNSListResponse when using pagination to avoid Proxied pointer overwrite ``` \ No newline at end of file From b6bd057117643656de84c1f5aab0b4a04d443ff8 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 28 Feb 2023 22:05:19 +0000 Subject: [PATCH 218/370] Update CHANGELOG.md for #1222 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12df81dd2a..30d064844b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ENHANCEMENTS: BUG FIXES: * dex_test: use dex test types and json struct mappings instead of managed networks ([#1213](https://github.com/cloudflare/cloudflare-go/issues/1213)) +* dns: dont reuse DNSListResponse when using pagination to avoid Proxied pointer overwrite ([#1222](https://github.com/cloudflare/cloudflare-go/issues/1222)) DEPENDENCIES: From bab690ab33e23e502cec932d7d33459ce8867b56 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 1 Mar 2023 15:37:41 +1100 Subject: [PATCH 219/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30d064844b..5cff87d146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.62.0 (Unreleased) +## 0.63.0 (Unreleased) + +## 0.62.0 (1st March, 2023) ENHANCEMENTS: From cd4454dc7e1154765bf4840cf4ae000991bd2bc9 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 1 Mar 2023 18:53:56 +0000 Subject: [PATCH 220/370] Update CHANGELOG.md for #1181 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cff87d146..db3543301e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.63.0 (Unreleased) +ENHANCEMENTS: + +* access_organization: add ui_read_only_toggle_reason field ([#1181](https://github.com/cloudflare/cloudflare-go/issues/1181)) + ## 0.62.0 (1st March, 2023) ENHANCEMENTS: From 3421d5d27b2dcd687fe4dbdf72e966bac2517f25 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 3 Mar 2023 16:15:49 -0500 Subject: [PATCH 221/370] Update tests --- challenge_widgets_test.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/challenge_widgets_test.go b/challenge_widgets_test.go index bdc19a8c05..30150995e3 100644 --- a/challenge_widgets_test.go +++ b/challenge_widgets_test.go @@ -38,24 +38,24 @@ func TestChallengeWidgets_Create(t *testing.T) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` -{ - "success": true, - "errors": [], - "messages": [], - "result": { - "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", - "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", - "created_on": "2014-01-01T05:20:00.123123Z", - "modified_on": "2014-01-01T05:20:00.123123Z", - "name": "blog.cloudflare.com login form", - "domains": [ - "203.0.113.1", - "cloudflare.com", - "blog.example.com" - ], - "type": "invisible" - } -}`) + { + "success": true, + "errors": [], + "messages": [], + "result": { + "sitekey": "0x4AAF00AAAABn0R22HWm-YUc", + "secret": "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", + "created_on": "2014-01-01T05:20:00.123123Z", + "modified_on": "2014-01-01T05:20:00.123123Z", + "name": "blog.cloudflare.com login form", + "domains": [ + "203.0.113.1", + "cloudflare.com", + "blog.example.com" + ], + "type": "invisible" + } + }`) }) // Make sure missing account ID is thrown From 59a1e0f690a18039993d1f7988757cd6b5ebd580 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 3 Mar 2023 16:39:20 -0500 Subject: [PATCH 222/370] Update tunnels --- .changelog/1227.txt | 6 +++ testdata/fixtures/tunnel/single_full.json | 47 ++++++++++++----------- tunnel.go | 37 ++++++++++-------- tunnel_test.go | 24 +++++++----- 4 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 .changelog/1227.txt diff --git a/.changelog/1227.txt b/.changelog/1227.txt new file mode 100644 index 0000000000..37f4eefc4e --- /dev/null +++ b/.changelog/1227.txt @@ -0,0 +1,6 @@ +```release-note:breaking-change +tunnel: changed to use List and Get +``` +```release-note:enhancement +tunnel: updated parameters to latest API docs +``` \ No newline at end of file diff --git a/testdata/fixtures/tunnel/single_full.json b/testdata/fixtures/tunnel/single_full.json index 5408bdb56e..e5178e650f 100644 --- a/testdata/fixtures/tunnel/single_full.json +++ b/testdata/fixtures/tunnel/single_full.json @@ -1,22 +1,25 @@ -{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "name": "blog", - "created_at": "2009-11-10T23:00:00Z", - "deleted_at": "2009-11-10T23:00:00Z", - "connections": [ - { - "colo_name": "DFW", - "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", - "is_pending_reconnect": false, - "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", - "client_version": "2022.2.0", - "opened_at": "2021-01-25T18:22:34.317854Z", - "origin_ip": "198.51.100.1" - } - ] - } -} +{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "name": "blog", + "created_at": "2009-11-10T23:00:00Z", + "deleted_at": "2009-11-10T23:00:00Z", + "connections": [ + { + "colo_name": "DFW", + "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + "is_pending_reconnect": false, + "client_id": "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", + "client_version": "2022.2.0", + "opened_at": "2021-01-25T18:22:34.317854Z", + "origin_ip": "198.51.100.1" + } + ], + "status": "healthy", + "tun_type": "cfd_tunnel", + "remote_config": true + } +} diff --git a/tunnel.go b/tunnel.go index 8ae91d391d..a43a81e35e 100644 --- a/tunnel.go +++ b/tunnel.go @@ -23,16 +23,20 @@ type Tunnel struct { Connections []TunnelConnection `json:"connections,omitempty"` ConnsActiveAt *time.Time `json:"conns_active_at,omitempty"` ConnInactiveAt *time.Time `json:"conns_inactive_at,omitempty"` + TunnelType string `json:"tun_type,omitempty"` + Status string `json:"status,omitempty"` + RemoteConfig bool `json:"remote_config,omitempty"` } // Connection is the struct definition of a connection. type Connection struct { - ID string `json:"id,omitempty"` - Features []string `json:"features,omitempty"` - Version string `json:"version,omitempty"` - Arch string `json:"arch,omitempty"` - Connections []TunnelConnection `json:"conns,omitempty"` - RunAt *time.Time `json:"run_at,omitempty"` + ID string `json:"id,omitempty"` + Features []string `json:"features,omitempty"` + Version string `json:"version,omitempty"` + Arch string `json:"arch,omitempty"` + Connections []TunnelConnection `json:"conns,omitempty"` + RunAt *time.Time `json:"run_at,omitempty"` + ConfigVersion int `json:"config_version,omitempty"` } // TunnelConnection represents the connections associated with a tunnel. @@ -91,8 +95,9 @@ type TunnelTokenResponse struct { } type TunnelCreateParams struct { - Name string `json:"name,omitempty"` - Secret string `json:"tunnel_secret,omitempty"` + Name string `json:"name,omitempty"` + Secret string `json:"tunnel_secret,omitempty"` + ConfigSrc string `json:"config_src,omitempty"` } type TunnelUpdateParams struct { @@ -179,10 +184,10 @@ type TunnelListParams struct { ResultInfo } -// Tunnels lists all tunnels. +// ListTunnels lists all tunnels. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-list-cloudflare-tunnels -func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams) ([]Tunnel, *ResultInfo, error) { +func (api *API) ListTunnels(ctx context.Context, rc *ResourceContainer, params TunnelListParams) ([]Tunnel, *ResultInfo, error) { if rc.Identifier == "" { return []Tunnel{}, &ResultInfo{}, ErrMissingAccountID } @@ -225,10 +230,10 @@ func (api *API) Tunnels(ctx context.Context, rc *ResourceContainer, params Tunne return records, &listResponse.ResultInfo, nil } -// Tunnel returns a single Argo tunnel. +// GetTunnel returns a single Argo tunnel. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel -func (api *API) Tunnel(ctx context.Context, rc *ResourceContainer, tunnelID string) (Tunnel, error) { +func (api *API) GetTunnel(ctx context.Context, rc *ResourceContainer, tunnelID string) (Tunnel, error) { if rc.Identifier == "" { return Tunnel{}, ErrMissingAccountID } @@ -386,10 +391,10 @@ func (api *API) GetTunnelConfiguration(ctx context.Context, rc *ResourceContaine return tunnelDetails, nil } -// TunnelConnections gets all connections on a tunnel. +// ListTunnelConnections gets all connections on a tunnel. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-list-cloudflare-tunnel-connections -func (api *API) TunnelConnections(ctx context.Context, rc *ResourceContainer, tunnelID string) ([]Connection, error) { +func (api *API) ListTunnelConnections(ctx context.Context, rc *ResourceContainer, tunnelID string) ([]Connection, error) { if rc.Identifier == "" { return []Connection{}, ErrMissingAccountID } @@ -461,10 +466,10 @@ func (api *API) CleanupTunnelConnections(ctx context.Context, rc *ResourceContai return nil } -// TunnelToken that allows to run a tunnel. +// GetTunnelToken that allows to run a tunnel. // // API reference: https://api.cloudflare.com/#cloudflare-tunnel-get-cloudflare-tunnel-token -func (api *API) TunnelToken(ctx context.Context, rc *ResourceContainer, tunnelID string) (string, error) { +func (api *API) GetTunnelToken(ctx context.Context, rc *ResourceContainer, tunnelID string) (string, error) { if rc.Identifier == "" { return "", ErrMissingAccountID } diff --git a/tunnel_test.go b/tunnel_test.go index 5e62910471..7488e5a891 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestTunnels(t *testing.T) { +func TestListTunnels(t *testing.T) { setup() defer teardown() @@ -41,14 +41,14 @@ func TestTunnels(t *testing.T) { }}, }} - actual, _, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + actual, _, err := client.ListTunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestTunnelsPagination(t *testing.T) { +func TestListTunnelsPagination(t *testing.T) { setup() defer teardown() @@ -84,7 +84,7 @@ func TestTunnelsPagination(t *testing.T) { }, } - actual, _, err := client.Tunnels(context.Background(), AccountIdentifier(testAccountID), + actual, _, err := client.ListTunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{ Name: "blog", ResultInfo: ResultInfo{ @@ -98,7 +98,7 @@ func TestTunnelsPagination(t *testing.T) { } } -func TestTunnel(t *testing.T) { +func TestGetTunnel(t *testing.T) { setup() defer teardown() @@ -126,9 +126,12 @@ func TestTunnel(t *testing.T) { OpenedAt: "2021-01-25T18:22:34.317854Z", OriginIP: "198.51.100.1", }}, + TunnelType: "cfd_tunnel", + Status: "healthy", + RemoteConfig: true, } - actual, err := client.Tunnel(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.GetTunnel(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -163,9 +166,12 @@ func TestCreateTunnel(t *testing.T) { OpenedAt: "2021-01-25T18:22:34.317854Z", OriginIP: "198.51.100.1", }}, + TunnelType: "cfd_tunnel", + Status: "healthy", + RemoteConfig: true, } - actual, err := client.CreateTunnel(context.Background(), AccountIdentifier(testAccountID), TunnelCreateParams{Name: "blog", Secret: "notarealsecret"}) + actual, err := client.CreateTunnel(context.Background(), AccountIdentifier(testAccountID), TunnelCreateParams{Name: "blog", Secret: "notarealsecret", ConfigSrc: "cloudflare"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -334,7 +340,7 @@ func TestTunnelConnections(t *testing.T) { }, } - actual, err := client.TunnelConnections(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.ListTunnelConnections(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -385,7 +391,7 @@ func TestTunnelToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/token", handler) - token, err := client.TunnelToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + token, err := client.GetTunnelToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) assert.Equal(t, "ZHNraGdhc2RraGFza2hqZGFza2poZGFza2poYXNrZGpoYWtzamRoa2FzZGpoa2FzamRoa2Rhc2po\na2FzamRoa2FqCg==", token) } From d92df1fe5ab3f2352923fb4dd4ea914a812287c1 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 3 Mar 2023 17:19:17 -0500 Subject: [PATCH 223/370] Update tunnel test fixtures --- tunnel_test.go | 54 ++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/tunnel_test.go b/tunnel_test.go index 7488e5a891..ced320c74c 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -26,13 +26,13 @@ func TestListTunnels(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") want := []Tunnel{{ - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, Name: "blog", CreatedAt: &createdAt, DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, IsPendingReconnect: false, ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", ClientVersion: "2022.2.0", @@ -41,7 +41,7 @@ func TestListTunnels(t *testing.T) { }}, }} - actual, _, err := client.ListTunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) + actual, _, err := client.ListTunnels(context.Background(), AccountIdentifier(testAccountID), TunnelListParams{UUID: testTunnelID}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -68,13 +68,13 @@ func TestListTunnelsPagination(t *testing.T) { deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") want := []Tunnel{ { - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, Name: "blog", CreatedAt: &createdAt, DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, IsPendingReconnect: false, ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", ClientVersion: "2022.2.0", @@ -108,18 +108,18 @@ func TestGetTunnel(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "single_full")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/"+testTunnelID, handler) createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") want := Tunnel{ - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, Name: "blog", CreatedAt: &createdAt, DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, IsPendingReconnect: false, ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", ClientVersion: "2022.2.0", @@ -131,7 +131,7 @@ func TestGetTunnel(t *testing.T) { RemoteConfig: true, } - actual, err := client.GetTunnel(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.GetTunnel(context.Background(), AccountIdentifier(testAccountID), testTunnelID) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -153,13 +153,13 @@ func TestCreateTunnel(t *testing.T) { createdAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") deletedAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") want := Tunnel{ - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, Name: "blog", CreatedAt: &createdAt, DeletedAt: &deletedAt, Connections: []TunnelConnection{{ ColoName: "DFW", - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, IsPendingReconnect: false, ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", ClientVersion: "2022.2.0", @@ -189,9 +189,9 @@ func TestUpdateTunnelConfiguration(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "configuration")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/configurations", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/configurations", testAccountID, testTunnelID), handler) want := TunnelConfigurationResult{ - TunnelID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + TunnelID: testTunnelID, Version: 5, Config: TunnelConfiguration{ Ingress: []UnvalidatedIngressRule{ @@ -212,7 +212,7 @@ func TestUpdateTunnelConfiguration(t *testing.T) { }} actual, err := client.UpdateTunnelConfiguration(context.Background(), AccountIdentifier(testAccountID), TunnelConfigurationParams{ - TunnelID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + TunnelID: testTunnelID, Config: TunnelConfiguration{ Ingress: []UnvalidatedIngressRule{ { @@ -248,9 +248,9 @@ func TestGetTunnelConfiguration(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "configuration")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/configurations", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/configurations", testAccountID, testTunnelID), handler) want := TunnelConfigurationResult{ - TunnelID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + TunnelID: testTunnelID, Version: 5, Config: TunnelConfiguration{ Ingress: []UnvalidatedIngressRule{ @@ -270,7 +270,7 @@ func TestGetTunnelConfiguration(t *testing.T) { }, }} - actual, err := client.GetTunnelConfiguration(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.GetTunnelConfiguration(context.Background(), AccountIdentifier(testAccountID), testTunnelID) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -297,6 +297,7 @@ func TestTunnelConnections(t *testing.T) { ], "version": "2022.2.0", "arch": "linux_amd64", + "config_version": 15, "run_at":"2009-11-10T23:00:00Z", "conns": [ { @@ -314,7 +315,7 @@ func TestTunnelConnections(t *testing.T) { `) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", testAccountID, testTunnelID), handler) runAt, _ := time.Parse(time.RFC3339, "2009-11-10T23:00:00Z") want := []Connection{ @@ -330,17 +331,18 @@ func TestTunnelConnections(t *testing.T) { RunAt: &runAt, Connections: []TunnelConnection{{ ColoName: "DFW", - ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", + ID: testTunnelID, IsPendingReconnect: false, ClientID: "dc6472cc-f1ae-44a0-b795-6b8a0ce29f90", ClientVersion: "2022.2.0", OpenedAt: "2021-01-25T18:22:34.317854Z", OriginIP: "198.51.100.1", }}, + ConfigVersion: 15, }, } - actual, err := client.ListTunnelConnections(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.ListTunnelConnections(context.Background(), AccountIdentifier(testAccountID), testTunnelID) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -357,9 +359,9 @@ func TestDeleteTunnel(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "single_full")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s", testAccountID, testTunnelID), handler) - err := client.DeleteTunnel(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err := client.DeleteTunnel(context.Background(), AccountIdentifier(testAccountID), testTunnelID) assert.NoError(t, err) } @@ -373,9 +375,9 @@ func TestCleanupTunnelConnections(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "empty")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/connections", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/connections", testAccountID, testTunnelID), handler) - err := client.CleanupTunnelConnections(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err := client.CleanupTunnelConnections(context.Background(), AccountIdentifier(testAccountID), testTunnelID) assert.NoError(t, err) } @@ -389,9 +391,9 @@ func TestTunnelToken(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "token")) } - mux.HandleFunc("/accounts/"+testAccountID+"/cfd_tunnel/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/token", handler) + mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/token", testAccountID, testTunnelID), handler) - token, err := client.GetTunnelToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + token, err := client.GetTunnelToken(context.Background(), AccountIdentifier(testAccountID), testTunnelID) assert.NoError(t, err) assert.Equal(t, "ZHNraGdhc2RraGFza2hqZGFza2poZGFza2poYXNrZGpoYWtzamRoa2FzZGpoa2FzamRoa2Rhc2po\na2FzamRoa2FqCg==", token) } From eb89b782512849f94021dd4598ed08d88d820256 Mon Sep 17 00:00:00 2001 From: Rex Scaria Date: Sat, 4 Mar 2023 04:42:04 -0500 Subject: [PATCH 224/370] =?UTF-8?q?feat:=20added=20audit=5Fssh=20to=20gate?= =?UTF-8?q?way=20actions,=20updated=20gateway=20rul=E2=80=A6=20(#1226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rex Scaria Co-authored-by: Jacob Bednarz --- .changelog/1226.txt | 3 + teams_rules.go | 57 ++++++++++----- teams_rules_test.go | 166 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 195 insertions(+), 31 deletions(-) create mode 100644 .changelog/1226.txt diff --git a/.changelog/1226.txt b/.changelog/1226.txt new file mode 100644 index 0000000000..167b1e6f78 --- /dev/null +++ b/.changelog/1226.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +added audit_ssh to gateway actions, updated gateway rule settings +``` diff --git a/teams_rules.go b/teams_rules.go index 7950d10825..51075012e8 100644 --- a/teams_rules.go +++ b/teams_rules.go @@ -36,11 +36,25 @@ type TeamsRuleSettings struct { // whether to disable dnssec validation for allow action InsecureDisableDNSSECValidation bool `json:"insecure_disable_dnssec_validation"` + // settings for rules with egress action EgressSettings *EgressSettings `json:"egress"` // DLP payload logging configuration PayloadLog *TeamsDlpPayloadLogSettings `json:"payload_log"` + //AuditSsh Settings + AuditSSH *AuditSSHRuleSettings `json:"audit_ssh"` + + // Turns on ip category based filter on dns if the rule contains dns category checks + IPCategories bool `json:"ip_categories"` + + // Allow parent MSP accounts to enable bypass their children's rules. + AllowChildBypass bool `json:"allow_child_bypass"` + + // Allow child MSP accounts to bypass their parent's rules + BypassParentRule bool `json:"bypass_parent_rule"` + + // Action taken when an untrusted origin certificate error occurs in a http allow rule UntrustedCertSettings *UntrustedCertSettings `json:"untrusted_cert"` } @@ -56,6 +70,10 @@ type UntrustedCertSettings struct { Action TeamsGatewayUntrustedCertAction `json:"action"` } +type AuditSSHRuleSettings struct { + CommandLogging bool `json:"command_logging"` +} + type EgressSettings struct { Ipv6Range string `json:"ipv6"` Ipv4 string `json:"ipv4"` @@ -69,11 +87,12 @@ type TeamsL4OverrideSettings struct { } type TeamsBISOAdminControlSettings struct { - DisablePrinting bool `json:"dp"` - DisableCopyPaste bool `json:"dcp"` - DisableDownload bool `json:"dd"` - DisableUpload bool `json:"du"` - DisableKeyboard bool `json:"dk"` + DisablePrinting bool `json:"dp"` + DisableCopyPaste bool `json:"dcp"` + DisableDownload bool `json:"dd"` + DisableUpload bool `json:"du"` + DisableKeyboard bool `json:"dk"` + DisableClipboardRedirection bool `json:"dcr"` } type TeamsCheckSessionSettings struct { @@ -97,19 +116,20 @@ const ( ) const ( - Allow TeamsGatewayAction = "allow" - Block TeamsGatewayAction = "block" - SafeSearch TeamsGatewayAction = "safesearch" - YTRestricted TeamsGatewayAction = "ytrestricted" - On TeamsGatewayAction = "on" - Off TeamsGatewayAction = "off" - Scan TeamsGatewayAction = "scan" - NoScan TeamsGatewayAction = "noscan" - Isolate TeamsGatewayAction = "isolate" - NoIsolate TeamsGatewayAction = "noisolate" - Override TeamsGatewayAction = "override" - L4Override TeamsGatewayAction = "l4_override" - Egress TeamsGatewayAction = "egress" + Allow TeamsGatewayAction = "allow" // dns|http|l4 + Block TeamsGatewayAction = "block" // dns|http|l4 + SafeSearch TeamsGatewayAction = "safesearch" // dns + YTRestricted TeamsGatewayAction = "ytrestricted" // dns + On TeamsGatewayAction = "on" // http + Off TeamsGatewayAction = "off" // http + Scan TeamsGatewayAction = "scan" // http + NoScan TeamsGatewayAction = "noscan" // http + Isolate TeamsGatewayAction = "isolate" // http + NoIsolate TeamsGatewayAction = "noisolate" // http + Override TeamsGatewayAction = "override" // http + L4Override TeamsGatewayAction = "l4_override" // l4 + Egress TeamsGatewayAction = "egress" // egress + AuditSSH TeamsGatewayAction = "audit_ssh" // l4 ) func TeamsRulesActionValues() []string { @@ -127,6 +147,7 @@ func TeamsRulesActionValues() []string { string(Override), string(L4Override), string(Egress), + string(AuditSSH), } } diff --git a/teams_rules_test.go b/teams_rules_test.go index 167f16b067..0378d5bcf1 100644 --- a/teams_rules_test.go +++ b/teams_rules_test.go @@ -264,7 +264,7 @@ func TestTeamsRule(t *testing.T) { } } -func TestTeamsCreateRule(t *testing.T) { +func TestTeamsCreateHTTPRule(t *testing.T) { setup() defer teardown() @@ -288,11 +288,7 @@ func TestTeamsCreateRule(t *testing.T) { "identity": "", "rule_settings": { "block_page_enabled": false, - "block_reason": "", - "override_ips": null, - "override_host": "", - "l4override": null, - "biso_admin_controls": null, + "biso_admin_controls": {"dp": true, "du": true, "dk": true}, "add_headers": { "X-Test": ["abcd"] }, @@ -318,18 +314,162 @@ func TestTeamsCreateRule(t *testing.T) { Identity: "", DevicePosture: "", RuleSettings: TeamsRuleSettings{ - BlockPageEnabled: false, - BlockReason: "", - OverrideIPs: nil, - OverrideHost: "", - L4Override: nil, - AddHeaders: http.Header{"X-Test": []string{"abcd"}}, - BISOAdminControls: nil, + BlockPageEnabled: false, + BlockReason: "", + OverrideIPs: nil, + OverrideHost: "", + L4Override: nil, + AddHeaders: http.Header{"X-Test": []string{"abcd"}}, + BISOAdminControls: &TeamsBISOAdminControlSettings{ + DisablePrinting: true, + DisableKeyboard: true, + DisableUpload: true, + }, CheckSession: &TeamsCheckSessionSettings{ Enforce: true, Duration: Duration{300 * time.Second}, }, InsecureDisableDNSSECValidation: false, + EgressSettings: nil, + }, + DeletedAt: nil, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/gateway/rules", handler) + + actual, err := client.TeamsCreateRule(context.Background(), testAccountID, want) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestTeamsCreateEgressRule(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "name": "egress via chicago", + "description": "rule description", + "precedence": 1000, + "enabled": false, + "action": "egress", + "filters": [ + "egress" + ], + "traffic": "net.src.geo.country == \"US\"", + "identity": "", + "rule_settings": { + "egress": { + "ipv6": "2a06:98c1:54::c61/64", + "ipv4": "2.2.2.2", + "ipv4_fallback": "1.1.1.1" + } + } + } + } + `) + } + + want := TeamsRule{ + Name: "egress via chicago", + Description: "rule description", + Precedence: 1000, + Enabled: false, + Action: Egress, + Filters: []TeamsFilterType{EgressFilter}, + Traffic: `net.src.geo.country == "US"`, + Identity: "", + DevicePosture: "", + RuleSettings: TeamsRuleSettings{ + BlockPageEnabled: false, + BlockReason: "", + OverrideIPs: nil, + OverrideHost: "", + L4Override: nil, + AddHeaders: nil, + BISOAdminControls: nil, + CheckSession: nil, + InsecureDisableDNSSECValidation: false, + EgressSettings: &EgressSettings{ + Ipv6Range: "2a06:98c1:54::c61/64", + Ipv4: "2.2.2.2", + Ipv4Fallback: "1.1.1.1", + }, + }, + DeletedAt: nil, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/gateway/rules", handler) + + actual, err := client.TeamsCreateRule(context.Background(), testAccountID, want) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestTeamsCreateL4Rule(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "name": "block 4.4.4.4", + "description": "rule description", + "precedence": 1000, + "enabled": true, + "action": "audit_ssh", + "filters": [ + "l4" + ], + "traffic": "net.src.geo.country == \"US\"", + "identity": "", + "rule_settings": { + "audit_ssh": { "command_logging": true } + } + } + } + `) + } + + want := TeamsRule{ + Name: "block 4.4.4.4", + Description: "rule description", + Precedence: 1000, + Enabled: true, + Action: AuditSSH, + Filters: []TeamsFilterType{L4Filter}, + Traffic: `net.src.geo.country == "US"`, + Identity: "", + DevicePosture: "", + RuleSettings: TeamsRuleSettings{ + BlockPageEnabled: false, + BlockReason: "", + OverrideIPs: nil, + OverrideHost: "", + L4Override: nil, + AddHeaders: nil, + BISOAdminControls: nil, + CheckSession: nil, + InsecureDisableDNSSECValidation: false, + EgressSettings: nil, + AuditSSH: &AuditSSHRuleSettings{ + CommandLogging: true, + }, }, DeletedAt: nil, } From bea2d32458460b394f62bee459e992de3a813d55 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sat, 4 Mar 2023 09:43:53 +0000 Subject: [PATCH 225/370] Update CHANGELOG.md for #1226 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db3543301e..77d93d9883 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * access_organization: add ui_read_only_toggle_reason field ([#1181](https://github.com/cloudflare/cloudflare-go/issues/1181)) +* added audit_ssh to gateway actions, updated gateway rule settings ([#1226](https://github.com/cloudflare/cloudflare-go/issues/1226)) ## 0.62.0 (1st March, 2023) From b762d69d40e32da03e7d0bd25b2bcefafc433bf9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 6 Mar 2023 09:59:46 +1100 Subject: [PATCH 226/370] update CHANGELOG --- .changelog/1227.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.changelog/1227.txt b/.changelog/1227.txt index 37f4eefc4e..96c1ce0524 100644 --- a/.changelog/1227.txt +++ b/.changelog/1227.txt @@ -1,5 +1,9 @@ ```release-note:breaking-change -tunnel: changed to use List and Get +tunnel: renamed `Tunnels` to `ListTunnels` +``` + +```release-note:breaking-change +tunnel: renamed `Tunnel` to `GetTunnel` ``` ```release-note:enhancement tunnel: updated parameters to latest API docs From ba1d72684e8a07170e9e4f946a77973bc7b6b20f Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sun, 5 Mar 2023 23:03:41 +0000 Subject: [PATCH 227/370] Update CHANGELOG.md for #1227 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d93d9883..0c4b29fe46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ ## 0.63.0 (Unreleased) +BREAKING CHANGES: + +* tunnel: renamed `Tunnel` to `GetTunnel` ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) +* tunnel: renamed `Tunnels` to `ListTunnels` ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) + ENHANCEMENTS: * access_organization: add ui_read_only_toggle_reason field ([#1181](https://github.com/cloudflare/cloudflare-go/issues/1181)) * added audit_ssh to gateway actions, updated gateway rule settings ([#1226](https://github.com/cloudflare/cloudflare-go/issues/1226)) +* tunnel: updated parameters to latest API docs ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) ## 0.62.0 (1st March, 2023) From ec29ede395eaa7ef3bf5fe863e7f1649b2c9168b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:56:55 +0000 Subject: [PATCH 228/370] build(deps): bump golang.org/x/net from 0.7.0 to 0.8.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2a470664d1..d286853c17 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.24.4 - golang.org/x/net v0.7.0 + golang.org/x/net v0.8.0 golang.org/x/time v0.3.0 ) @@ -30,6 +30,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/text v0.8.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 97fa1297e5..7fd91bed05 100644 --- a/go.sum +++ b/go.sum @@ -68,13 +68,16 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -86,21 +89,25 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 14dcb66a8dbcfe7094aeb34cfb7c3b4e62853c7b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 6 Mar 2023 16:57:15 +0000 Subject: [PATCH 229/370] add CHANGELOG for #1228 --- .changelog/1228.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1228.txt diff --git a/.changelog/1228.txt b/.changelog/1228.txt new file mode 100644 index 0000000000..72816b5f3d --- /dev/null +++ b/.changelog/1228.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.7.0 to 0.8.0 +``` From 3f45fed29d4dcc0baa1d2f47e405fa00743185b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 19:34:50 +0000 Subject: [PATCH 230/370] build(deps): bump github.com/urfave/cli/v2 from 2.24.4 to 2.25.0 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.4 to 2.25.0. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.4...v2.25.0) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d286853c17..4765d844bc 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( 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.24.4 + github.com/urfave/cli/v2 v2.25.0 golang.org/x/net v0.8.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index 7fd91bed05..5edae26d2a 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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.24.4 h1:0gyJJEBYtCV87zI/x2nZCPyDxD51K6xM8SkwjHFCNEU= -github.com/urfave/cli/v2 v2.24.4/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8= +github.com/urfave/cli/v2 v2.25.0/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= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= From b91ff8b776e31186f52c07ef942b3a177192c858 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 6 Mar 2023 19:35:09 +0000 Subject: [PATCH 231/370] add CHANGELOG for #1229 --- .changelog/1229.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1229.txt diff --git a/.changelog/1229.txt b/.changelog/1229.txt new file mode 100644 index 0000000000..a4b655ccb5 --- /dev/null +++ b/.changelog/1229.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.24.4 to 2.25.0 +``` From 3d7eda61e7df8828781e373b4b520744f2f27561 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 6 Mar 2023 19:35:50 +0000 Subject: [PATCH 232/370] Update CHANGELOG.md for #1228 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c4b29fe46..3a0219fc82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ ENHANCEMENTS: * added audit_ssh to gateway actions, updated gateway rule settings ([#1226](https://github.com/cloudflare/cloudflare-go/issues/1226)) * tunnel: updated parameters to latest API docs ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) +DEPENDENCIES: + +* deps: bumps golang.org/x/net from 0.7.0 to 0.8.0 ([#1228](https://github.com/cloudflare/cloudflare-go/issues/1228)) + ## 0.62.0 (1st March, 2023) ENHANCEMENTS: From ce804ed5eafab6a5ac6653c5cd46add4cb5d727d Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 6 Mar 2023 19:52:29 +0000 Subject: [PATCH 233/370] Update CHANGELOG.md for #1229 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0219fc82..4f3bb425e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ ENHANCEMENTS: DEPENDENCIES: +* deps: bumps github.com/urfave/cli/v2 from 2.24.4 to 2.25.0 ([#1229](https://github.com/cloudflare/cloudflare-go/issues/1229)) * deps: bumps golang.org/x/net from 0.7.0 to 0.8.0 ([#1228](https://github.com/cloudflare/cloudflare-go/issues/1228)) ## 0.62.0 (1st March, 2023) From 372741f4e71f62d8d42101aaa310ebe7e507edb7 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 8 Mar 2023 05:12:09 +0000 Subject: [PATCH 234/370] Update CHANGELOG.md for #1197 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3bb425e2..8a7a76c5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: * access_organization: add ui_read_only_toggle_reason field ([#1181](https://github.com/cloudflare/cloudflare-go/issues/1181)) * added audit_ssh to gateway actions, updated gateway rule settings ([#1226](https://github.com/cloudflare/cloudflare-go/issues/1226)) +* teams_account: add support for `check_disks` ([#1197](https://github.com/cloudflare/cloudflare-go/issues/1197)) * tunnel: updated parameters to latest API docs ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) DEPENDENCIES: From 2b0a3fcb9c351d91e4a845d806cf170f90b3c026 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Wed, 8 Mar 2023 14:22:33 +0100 Subject: [PATCH 235/370] refactor: simplify time formatting --- access_audit_log.go | 4 ++-- dns_firewall.go | 4 ++-- zone.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/access_audit_log.go b/access_audit_log.go index 1627914d83..bb488f6348 100644 --- a/access_audit_log.go +++ b/access_audit_log.go @@ -74,11 +74,11 @@ func (a AccessAuditLogFilterOptions) Encode() string { } if a.Since != nil { - v.Set("since", (*a.Since).Format(time.RFC3339)) + v.Set("since", a.Since.Format(time.RFC3339)) } if a.Until != nil { - v.Set("until", (*a.Until).Format(time.RFC3339)) + v.Set("until", a.Until.Format(time.RFC3339)) } return v.Encode() diff --git a/dns_firewall.go b/dns_firewall.go index f2cfa42ae8..d426e8989e 100644 --- a/dns_firewall.go +++ b/dns_firewall.go @@ -166,10 +166,10 @@ func (api *API) DeleteDNSFirewallCluster(ctx context.Context, clusterID string) func (o DNSFirewallUserAnalyticsOptions) encode() string { v := url.Values{} if o.Since != nil { - v.Set("since", (*o.Since).UTC().Format(time.RFC3339)) + v.Set("since", o.Since.UTC().Format(time.RFC3339)) } if o.Until != nil { - v.Set("until", (*o.Until).UTC().Format(time.RFC3339)) + v.Set("until", o.Until.UTC().Format(time.RFC3339)) } if o.Metrics != nil { v.Set("metrics", strings.Join(o.Metrics, ",")) diff --git a/zone.go b/zone.go index 3929356000..ba544c7896 100644 --- a/zone.go +++ b/zone.go @@ -722,10 +722,10 @@ func (api *API) AvailableZonePlans(ctx context.Context, zoneID string) ([]ZonePl func (o ZoneAnalyticsOptions) encode() string { v := url.Values{} if o.Since != nil { - v.Set("since", (*o.Since).Format(time.RFC3339)) + v.Set("since", o.Since.Format(time.RFC3339)) } if o.Until != nil { - v.Set("until", (*o.Until).Format(time.RFC3339)) + v.Set("until", o.Until.Format(time.RFC3339)) } if o.Continuous != nil { v.Set("continuous", fmt.Sprintf("%t", *o.Continuous)) From 05b27fd53eaa80374b67aa026acf655b339ff7d7 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 3 Mar 2023 15:51:58 +1100 Subject: [PATCH 236/370] rulesets: update to support migration to plugin framework --- rulesets.go | 18 ++++++++++-------- rulesets_test.go | 46 +++++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/rulesets.go b/rulesets.go index 27521b024c..d460eb8fec 100644 --- a/rulesets.go +++ b/rulesets.go @@ -40,6 +40,7 @@ const ( RulesetPhaseSuperBotFightMode RulesetPhase = "http_request_sbfm" RulesetPhaseHTTPConfigSettings RulesetPhase = "http_config_settings" + RulesetRuleActionAllow RulesetRuleAction = "allow" RulesetRuleActionBlock RulesetRuleAction = "block" RulesetRuleActionChallenge RulesetRuleAction = "challenge" RulesetRuleActionDDoSDynamic RulesetRuleAction = "ddos_dynamic" @@ -115,6 +116,7 @@ func RulesetPhaseValues() []string { // as a slice of strings. func RulesetRuleActionValues() []string { return []string{ + string(RulesetRuleActionAllow), string(RulesetRuleActionBlock), string(RulesetRuleActionChallenge), string(RulesetRuleActionDDoSDynamic), @@ -185,7 +187,7 @@ type Ruleset struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` Kind string `json:"kind,omitempty"` - Version string `json:"version,omitempty"` + Version *string `json:"version,omitempty"` LastUpdated *time.Time `json:"last_updated,omitempty"` Phase string `json:"phase,omitempty"` Rules []RulesetRule `json:"rules"` @@ -212,7 +214,7 @@ type RulesetRuleActionParameters struct { Phases []string `json:"phases,omitempty"` Overrides *RulesetRuleActionParametersOverrides `json:"overrides,omitempty"` MatchedData *RulesetRuleActionParametersMatchedData `json:"matched_data,omitempty"` - Version string `json:"version,omitempty"` + Version *string `json:"version,omitempty"` Response *RulesetRuleActionParametersBlockResponse `json:"response,omitempty"` HostHeader string `json:"host_header,omitempty"` Origin *RulesetRuleActionParametersOrigin `json:"origin,omitempty"` @@ -381,7 +383,7 @@ type RulesetRuleActionParametersBlockResponse struct { type RulesetRuleActionParametersURI struct { Path *RulesetRuleActionParametersURIPath `json:"path,omitempty"` Query *RulesetRuleActionParametersURIQuery `json:"query,omitempty"` - Origin bool `json:"origin,omitempty"` + Origin *bool `json:"origin,omitempty"` } // RulesetRuleActionParametersURIPath holds the path specific portion of a URI @@ -394,8 +396,8 @@ type RulesetRuleActionParametersURIPath struct { // RulesetRuleActionParametersURIQuery holds the query specific portion of a URI // action parameter. type RulesetRuleActionParametersURIQuery struct { - Value string `json:"value,omitempty"` - Expression string `json:"expression,omitempty"` + Value *string `json:"value,omitempty"` + Expression string `json:"expression,omitempty"` } // RulesetRuleActionParametersHTTPHeader is the definition for define action @@ -627,14 +629,14 @@ func (p SSL) IntoRef() *SSL { // RulesetRule contains information about a single Ruleset Rule. type RulesetRule struct { ID string `json:"id,omitempty"` - Version string `json:"version,omitempty"` + Version *string `json:"version,omitempty"` Action string `json:"action"` ActionParameters *RulesetRuleActionParameters `json:"action_parameters,omitempty"` Expression string `json:"expression"` - Description string `json:"description"` + Description string `json:"description,omitempty"` LastUpdated *time.Time `json:"last_updated,omitempty"` Ref string `json:"ref,omitempty"` - Enabled bool `json:"enabled"` + Enabled *bool `json:"enabled,omitempty"` ScoreThreshold int `json:"score_threshold,omitempty"` RateLimit *RulesetRuleRateLimit `json:"ratelimit,omitempty"` ExposedCredentialCheck *RulesetRuleExposedCredentialCheck `json:"exposed_credential_check,omitempty"` diff --git a/rulesets_test.go b/rulesets_test.go index a2b33ad079..32a0774c72 100644 --- a/rulesets_test.go +++ b/rulesets_test.go @@ -46,7 +46,7 @@ func TestListRulesets(t *testing.T) { Name: "my example ruleset", Description: "Test magic transit ruleset", Kind: "root", - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseMagicTransit), }, @@ -96,7 +96,7 @@ func TestGetRuleset_MagicTransit(t *testing.T) { Name: "my example ruleset", Description: "Test magic transit ruleset", Kind: "root", - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseMagicTransit), } @@ -161,20 +161,20 @@ func TestGetRuleset_WAF(t *testing.T) { rules := []RulesetRule{{ ID: "78723a9e0c7c4c6dbec5684cb766231d", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionRewrite), ActionParameters: &RulesetRuleActionParameters{ URI: &RulesetRuleActionParametersURI{ Path: &RulesetRuleActionParametersURIPath{ Expression: "normalize_url_path(raw.http.request.uri.path)", }, - Origin: false, + Origin: BoolPtr(false), }, }, Description: "Normalization on the URL path, without propagating it to the origin", LastUpdated: &lastUpdated, Ref: "272936dc447b41fe976255ff6b768ec0", - Enabled: true, + Enabled: BoolPtr(true), }} want := Ruleset{ @@ -182,7 +182,7 @@ func TestGetRuleset_WAF(t *testing.T) { Name: "Cloudflare Normalization Ruleset", Description: "Created by the Cloudflare security team, this ruleset provides normalization on the URL path", Kind: string(RulesetKindManaged), - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseHTTPRequestSanitize), Rules: rules, @@ -265,7 +265,7 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { rules := []RulesetRule{{ ID: "78723a9e0c7c4c6dbec5684cb766231d", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionSetCacheSettings), ActionParameters: &RulesetRuleActionParameters{ Cache: BoolPtr(true), @@ -329,7 +329,7 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { Description: "Set all available cache settings in one rule", LastUpdated: &lastUpdated, Ref: "272936dc447b41fe976255ff6b768ec0", - Enabled: true, + Enabled: BoolPtr(true), }} want := Ruleset{ @@ -337,7 +337,7 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { Name: "Cloudflare Cache Rules Ruleset", Description: "This ruleset provides cache settings modifications", Kind: string(RulesetKindZone), - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseHTTPRequestCacheSettings), Rules: rules, @@ -413,7 +413,7 @@ func TestGetRuleset_SetConfig(t *testing.T) { rules := []RulesetRule{{ ID: "78723a9e0c7c4c6dbec5684cb766231d", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionSetConfig), ActionParameters: &RulesetRuleActionParameters{ AutomaticHTTPSRewrites: BoolPtr(true), @@ -440,7 +440,7 @@ func TestGetRuleset_SetConfig(t *testing.T) { Description: "Set all available config rules in one rule", LastUpdated: &lastUpdated, Ref: "272936dc447b41fe976255ff6b768ec0", - Enabled: true, + Enabled: BoolPtr(true), }} want := Ruleset{ @@ -448,7 +448,7 @@ func TestGetRuleset_SetConfig(t *testing.T) { Name: "Cloudflare Config Rules Ruleset", Description: "This ruleset provides config rules modifications", Kind: string(RulesetKindZone), - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseHTTPConfigSettings), Rules: rules, @@ -515,7 +515,7 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { rules := []RulesetRule{{ ID: "78723a9e0c7c4c6dbec5684cb766231d", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionRedirect), ActionParameters: &RulesetRuleActionParameters{ FromValue: &RulesetRuleActionParametersFromValue{ @@ -529,7 +529,7 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { Description: "Set dynamic redirect from value", LastUpdated: &lastUpdated, Ref: "272936dc447b41fe976255ff6b768ec0", - Enabled: true, + Enabled: BoolPtr(true), }} want := Ruleset{ @@ -537,7 +537,7 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { Name: "Cloudflare Redirect Rules Ruleset", Description: "This ruleset provides redirect from value", Kind: string(RulesetKindZone), - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseHTTPRequestDynamicRedirect), Rules: rules, @@ -599,7 +599,7 @@ func TestCreateRuleset(t *testing.T) { rules := []RulesetRule{{ ID: "62449e2e0de149619edb35e59c10d801", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionSkip), ActionParameters: &RulesetRuleActionParameters{ Ruleset: "current", @@ -608,7 +608,7 @@ func TestCreateRuleset(t *testing.T) { Description: "Allow TCP Ephemeral Ports", LastUpdated: &lastUpdated, Ref: "72449e2e0de149619edb35e59c10d801", - Enabled: true, + Enabled: BoolPtr(true), }} newRuleset := Ruleset{ @@ -624,7 +624,7 @@ func TestCreateRuleset(t *testing.T) { Name: "my example ruleset", Description: "Test magic transit ruleset", Kind: "root", - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseMagicTransit), Rules: rules, @@ -719,7 +719,7 @@ func TestUpdateRuleset(t *testing.T) { rules := []RulesetRule{{ ID: "62449e2e0de149619edb35e59c10d801", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionSkip), ActionParameters: &RulesetRuleActionParameters{ Ruleset: "current", @@ -728,10 +728,10 @@ func TestUpdateRuleset(t *testing.T) { Description: "Allow TCP Ephemeral Ports", LastUpdated: &lastUpdated, Ref: "72449e2e0de149619edb35e59c10d801", - Enabled: true, + Enabled: BoolPtr(true), }, { ID: "62449e2e0de149619edb35e59c10d802", - Version: "1", + Version: StringPtr("1"), Action: string(RulesetRuleActionSkip), ActionParameters: &RulesetRuleActionParameters{ Ruleset: "current", @@ -740,7 +740,7 @@ func TestUpdateRuleset(t *testing.T) { Description: "Allow UDP Ephemeral Ports", LastUpdated: &lastUpdated, Ref: "72449e2e0de149619edb35e59c10d801", - Enabled: true, + Enabled: BoolPtr(true), }} want := Ruleset{ @@ -748,7 +748,7 @@ func TestUpdateRuleset(t *testing.T) { Name: "ruleset1", Description: "Test Firewall Ruleset Update", Kind: "root", - Version: "1", + Version: StringPtr("1"), LastUpdated: &lastUpdated, Phase: string(RulesetPhaseMagicTransit), Rules: rules, From dbddd1eaeb52eb971506e015bb4ee0106da85e48 Mon Sep 17 00:00:00 2001 From: Minghang Chen Date: Thu, 9 Mar 2023 22:21:34 +0000 Subject: [PATCH 237/370] addressing: add support for Address Map About Address Map: https://developers.cloudflare.com/byoip/proxy-ips/ --- addressing_address_map.go | 271 +++++++++++++ addressing_address_map_test.go | 369 ++++++++++++++++++ ...s_management.go => addressing_ip_prefix.go | 0 ...nt_test.go => addressing_ip_prefix_test.go | 0 convert_types.go | 36 +- resource.go | 13 + 6 files changed, 671 insertions(+), 18 deletions(-) create mode 100644 addressing_address_map.go create mode 100644 addressing_address_map_test.go rename ip_address_management.go => addressing_ip_prefix.go (100%) rename ip_address_management_test.go => addressing_ip_prefix_test.go (100%) diff --git a/addressing_address_map.go b/addressing_address_map.go new file mode 100644 index 0000000000..f55201d177 --- /dev/null +++ b/addressing_address_map.go @@ -0,0 +1,271 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +// AddressMap contains information about an address map. +type AddressMap struct { + ID string `json:"id"` + Description *string `json:"description,omitempty"` + DefaultSNI *string `json:"default_sni"` + Enabled bool `json:"enabled"` + Deletable bool `json:"can_delete"` + CanModifyIPs bool `json:"can_modify_ips"` + Memberships []AddressMapMembership `json:"memberships"` + IPs []AddressMapIP `json:"ips"` + CreatedAt time.Time `json:"created_at"` + ModifiedAt time.Time `json:"modified_at"` +} + +type AddressMapIP struct { + IP string `json:"ip"` + CreatedAt time.Time `json:"created_at"` +} + +type AddressMapMembershipContainer struct { + Identifier string `json:"identifier"` + Kind AddressMapMembershipKind `json:"kind"` +} + +type AddressMapMembership struct { + AddressMapMembershipContainer + Deletable bool `json:"can_delete"` + CreatedAt time.Time `json:"created_at"` +} + +func (ammb *AddressMapMembershipContainer) URLFragment() string { + switch ammb.Kind { + case AddressMapMembershipAccount: + return fmt.Sprintf("accounts/%s", ammb.Identifier) + case AddressMapMembershipZone: + return fmt.Sprintf("zones/%s", ammb.Identifier) + default: + return fmt.Sprintf("%s/%s", ammb.Kind, ammb.Identifier) + } +} + +type AddressMapMembershipKind string + +const ( + AddressMapMembershipZone AddressMapMembershipKind = "zone" + AddressMapMembershipAccount AddressMapMembershipKind = "account" +) + +// ListAddressMapResponse contains a slice of address maps. +type ListAddressMapResponse struct { + Response + Result []AddressMap `json:"result"` +} + +// GetAddressMapResponse contains a specific address map's API Response. +type GetAddressMapResponse struct { + Response + Result AddressMap `json:"result"` +} + +// AddressMapCreateParams contains information about an address map to be created. +type AddressMapCreateParams struct { + Description *string `json:"description"` + Enabled *bool `json:"enabled"` + IPs []string `json:"ips"` + Memberships []AddressMapMembershipContainer `json:"memberships"` +} + +// AddressMapUpdateParams contains information about an address map to be updated. +type AddressMapUpdateParams struct { + ID string `json:"id"` + Description *string `json:"description,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + DefaultSNI *string `json:"default_sni,omitempty"` +} + +// AddressMapFilter contains filter parameters for finding a list of address maps. +type AddressMapFilterParams struct { + IP *string `url:"ip,omitempty"` + CIDR *string `url:"cidr,omitempty"` +} + +// AddressMapIPParams contains request parameters to add/remove IP address to/from an address map. +type AddressMapIPParams struct { + // ID represents the target address map for adding/removing the IP address. + ID string + // The IP address. + IP string +} + +// AddressMapMembershipParams contains request parameters to add/remove membership from an address map. +type AddressMapMembershipParams struct { + // ID represents the target address map for adding/removing the membershp. + ID string + Membership AddressMapMembershipContainer +} + +// ListAddressMaps lists all address maps owned by the account. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-list-address-maps +func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, params AddressMapFilterParams) ([]AddressMap, error) { + if rc.Level != AccountRouteLevel { + return []AddressMap{}, ErrRequiredAccountLevelResourceContainer + } + + uri := buildURI(fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment()), params) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AddressMap{}, err + } + + result := ListAddressMapResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return []AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return result.Result, nil +} + +// CreateAddressMap creates a new address map under the account. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-create-address-map +func (api *API) CreateAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapCreateParams) (AddressMap, error) { + if rc.Level != AccountRouteLevel { + return AddressMap{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment()) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return AddressMap{}, err + } + + result := GetAddressMapResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return result.Result, nil +} + +// GetAddressMap returns a specific address map. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-address-map-details +func (api *API) GetAddressMap(ctx context.Context, rc *ResourceContainer, id string) (AddressMap, error) { + if rc.Level != AccountRouteLevel { + return AddressMap{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), id) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return AddressMap{}, err + } + + result := GetAddressMapResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return result.Result, nil +} + +// UpdateAddressMap modifies properties of an address map owned by the account. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-update-address-map +func (api *API) UpdateAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapUpdateParams) (AddressMap, error) { + if rc.Level != AccountRouteLevel { + return AddressMap{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), params.ID) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return AddressMap{}, err + } + + result := GetAddressMapResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return AddressMap{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return result.Result, nil +} + +// DeleteAddressMap deletes a particular address map owned by the account. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-delete-address-map +func (api *API) DeleteAddressMap(ctx context.Context, rc *ResourceContainer, id string) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s", rc.URLFragment(), id) + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + return err +} + +// CreateIPAddressToAddressMap adds an IP address from a prefix owned by the account to a particular address map. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-ip-to-an-address-map +func (api *API) CreateIPAddressToAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapIPParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/ips/%s", rc.URLFragment(), params.ID, params.IP) + _, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil) + return err +} + +// DeleteIPAddressFromAddressMap removes an IP address from a particular address map. +// +// API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-ip-from-an-address-map +func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapIPParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/ips/%s", rc.URLFragment(), params.ID, params.IP) + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + return err +} + +// AddMembershipToAddressMap adds a zone/account as a member of a particular address map. +// +// API reference: +// - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-account-membership-to-an-address-map +// - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-a-zone-membership-to-an-address-map +func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapMembershipParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + if params.Membership.Kind != AddressMapMembershipZone && params.Membership.Kind != AddressMapMembershipAccount { + return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) + _, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil) + return err +} + +// DeleteMembershipFromAddressMap removes a zone/account as a member of a particular address map. +// +// API reference: +// - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-account-membership-from-an-address-map +// - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-a-zone-membership-from-an-address-map +func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapMembershipParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + if params.Membership.Kind != AddressMapMembershipZone && params.Membership.Kind != AddressMapMembershipAccount { + return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) + } + + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + return err +} diff --git a/addressing_address_map_test.go b/addressing_address_map_test.go new file mode 100644 index 0000000000..b5f081f620 --- /dev/null +++ b/addressing_address_map_test.go @@ -0,0 +1,369 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var ( + addressMapDesc = "My Ecommerce zones" + addressMapDefaultSNI = "*.example.com" +) + +func TestListAddressMap(t *testing.T) { + setup() + defer teardown() + + expectedIP := "127.0.0.1" + expectedCIDR := "127.0.0.1/24" + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + + actualIP := r.URL.Query().Get("ip") + assert.Equal(t, expectedIP, actualIP, "Expected ip %q, got %q", expectedIP, actualIP) + + actualCIDR := r.URL.Query().Get("cidr") + assert.Equal(t, expectedCIDR, actualCIDR, "Expected cidr %q, got %q", expectedCIDR, actualCIDR) + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [{ + "id": "9a7806061c88ada191ed06f989cc3dac", + "description": "My Ecommerce zones", + "can_delete": true, + "can_modify_ips": true, + "default_sni": "*.example.com", + "created_at": "2023-01-01T05:20:00.12345Z", + "modified_at": "2023-01-05T05:20:00.12345Z", + "enabled": true, + "ips": [ + { + "ip": "192.0.2.1", + "created_at": "2023-01-02T05:20:00.12345Z" + } + ], + "memberships": [ + { + "kind": "zone", + "identifier": "01a7362d577a6c3019a474fd6f485823", + "can_delete": true, + "created_at": "2023-01-03T05:20:00.12345Z" + } + ] + }] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2023-01-01T05:20:00.12345Z") + modifiedAt, _ := time.Parse(time.RFC3339, "2023-01-05T05:20:00.12345Z") + ipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-02T05:20:00.12345Z") + membershipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-03T05:20:00.12345Z") + + want := []AddressMap{ + { + ID: "9a7806061c88ada191ed06f989cc3dac", + CreatedAt: createdAt, + ModifiedAt: modifiedAt, + Description: &addressMapDesc, + Deletable: true, + CanModifyIPs: true, + DefaultSNI: &addressMapDefaultSNI, + Enabled: true, + IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, + Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + }, + } + + actual, err := client.ListAddressMaps(context.Background(), AccountIdentifier(testAccountID), AddressMapFilterParams{&expectedIP, &expectedCIDR}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestGetAddressMap(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.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "9a7806061c88ada191ed06f989cc3dac", + "description": "My Ecommerce zones", + "can_delete": true, + "can_modify_ips": true, + "default_sni": "*.example.com", + "created_at": "2023-01-01T05:20:00.12345Z", + "modified_at": "2023-01-05T05:20:00.12345Z", + "enabled": true, + "ips": [ + { + "ip": "192.0.2.1", + "created_at": "2023-01-02T05:20:00.12345Z" + } + ], + "memberships": [ + { + "kind": "zone", + "identifier": "01a7362d577a6c3019a474fd6f485823", + "can_delete": true, + "created_at": "2023-01-03T05:20:00.12345Z" + } + ] + } + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2023-01-01T05:20:00.12345Z") + modifiedAt, _ := time.Parse(time.RFC3339, "2023-01-05T05:20:00.12345Z") + ipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-02T05:20:00.12345Z") + membershipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-03T05:20:00.12345Z") + + want := AddressMap{ + ID: "9a7806061c88ada191ed06f989cc3dac", + CreatedAt: createdAt, + ModifiedAt: modifiedAt, + Description: &addressMapDesc, + Deletable: true, + CanModifyIPs: true, + DefaultSNI: &addressMapDefaultSNI, + Enabled: true, + IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, + Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + } + + actual, err := client.GetAddressMap(context.Background(), AccountIdentifier(testAccountID), "9a7806061c88ada191ed06f989cc3dac") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateAddressMap(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.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "9a7806061c88ada191ed06f989cc3dac", + "description": "My Ecommerce zones", + "can_delete": true, + "can_modify_ips": true, + "default_sni": "*.example.com", + "created_at": "2023-01-01T05:20:00.12345Z", + "modified_at": "2023-01-05T05:20:00.12345Z", + "enabled": true, + "ips": [ + { + "ip": "192.0.2.1", + "created_at": "2023-01-02T05:20:00.12345Z" + } + ], + "memberships": [ + { + "kind": "zone", + "identifier": "01a7362d577a6c3019a474fd6f485823", + "can_delete": true, + "created_at": "2023-01-03T05:20:00.12345Z" + } + ] + } + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac", handler) + + createdAt, _ := time.Parse(time.RFC3339, "2023-01-01T05:20:00.12345Z") + modifiedAt, _ := time.Parse(time.RFC3339, "2023-01-05T05:20:00.12345Z") + ipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-02T05:20:00.12345Z") + membershipCreatedAt, _ := time.Parse(time.RFC3339, "2023-01-03T05:20:00.12345Z") + + want := AddressMap{ + ID: "9a7806061c88ada191ed06f989cc3dac", + CreatedAt: createdAt, + ModifiedAt: modifiedAt, + Description: &addressMapDesc, + Deletable: true, + CanModifyIPs: true, + DefaultSNI: &addressMapDefaultSNI, + Enabled: true, + IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, + Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + } + + actual, err := client.UpdateAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapUpdateParams{ID: "9a7806061c88ada191ed06f989cc3dac"}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteAddressMap(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "9a7806061c88ada191ed06f989cc3dac" + } + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac", handler) + + err := client.DeleteAddressMap(context.Background(), AccountIdentifier(testAccountID), "9a7806061c88ada191ed06f989cc3dac") + assert.NoError(t, err) +} + +func TestAddIPAddressToAddressMap(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.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/ips/192.0.2.1", handler) + + err := client.CreateIPAddressToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapIPParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) + assert.NoError(t, err) +} + +func TestRemoveIPAddressFromAddressMap(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/ips/192.0.2.1", handler) + + err := client.DeleteIPAddressFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapIPParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) + assert.NoError(t, err) +} + +func TestAddZoneToAddressMap(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.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/zones/01a7362d577a6c3019a474fd6f485823", handler) + + err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) + assert.NoError(t, err) +} + +func TestRemoveZoneFromAddressMap(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/zones/01a7362d577a6c3019a474fd6f485823", handler) + + err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) + assert.NoError(t, err) +} + +func TestAddAccountToAddressMap(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.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/accounts/01a7362d577a6c3019a474fd6f485823", handler) + + err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) + assert.NoError(t, err) +} + +func TestRemoveAccountFromAddressMap(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/accounts/01a7362d577a6c3019a474fd6f485823", handler) + + err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) + assert.NoError(t, err) +} diff --git a/ip_address_management.go b/addressing_ip_prefix.go similarity index 100% rename from ip_address_management.go rename to addressing_ip_prefix.go diff --git a/ip_address_management_test.go b/addressing_ip_prefix_test.go similarity index 100% rename from ip_address_management_test.go rename to addressing_ip_prefix_test.go diff --git a/convert_types.go b/convert_types.go index 1d45d34557..f3ebc83d0d 100644 --- a/convert_types.go +++ b/convert_types.go @@ -24,24 +24,24 @@ import ( // // Usage: var _ *Type = AnyPtr(Type(value) | value).(*Type) // -// var _ *bool = AnyPtr(true).(*bool) -// var _ *byte = AnyPtr(byte(1)).(*byte) -// var _ *complex64 = AnyPtr(complex64(1.1)).(*complex64) -// var _ *complex128 = AnyPtr(complex128(1.1)).(*complex128) -// var _ *float32 = AnyPtr(float32(1.1)).(*float32) -// var _ *float64 = AnyPtr(float64(1.1)).(*float64) -// var _ *int = AnyPtr(int(1)).(*int) -// var _ *int8 = AnyPtr(int8(8)).(*int8) -// var _ *int16 = AnyPtr(int16(16)).(*int16) -// var _ *int32 = AnyPtr(int32(32)).(*int32) -// var _ *int64 = AnyPtr(int64(64)).(*int64) -// var _ *rune = AnyPtr(rune(1)).(*rune) -// var _ *string = AnyPtr("ptr").(*string) -// var _ *uint = AnyPtr(uint(1)).(*uint) -// var _ *uint8 = AnyPtr(uint8(8)).(*uint8) -// var _ *uint16 = AnyPtr(uint16(16)).(*uint16) -// var _ *uint32 = AnyPtr(uint32(32)).(*uint32) -// var _ *uint64 = AnyPtr(uint64(64)).(*uint64) +// var _ *bool = AnyPtr(true).(*bool) +// var _ *byte = AnyPtr(byte(1)).(*byte) +// var _ *complex64 = AnyPtr(complex64(1.1)).(*complex64) +// var _ *complex128 = AnyPtr(complex128(1.1)).(*complex128) +// var _ *float32 = AnyPtr(float32(1.1)).(*float32) +// var _ *float64 = AnyPtr(float64(1.1)).(*float64) +// var _ *int = AnyPtr(int(1)).(*int) +// var _ *int8 = AnyPtr(int8(8)).(*int8) +// var _ *int16 = AnyPtr(int16(16)).(*int16) +// var _ *int32 = AnyPtr(int32(32)).(*int32) +// var _ *int64 = AnyPtr(int64(64)).(*int64) +// var _ *rune = AnyPtr(rune(1)).(*rune) +// var _ *string = AnyPtr("ptr").(*string) +// var _ *uint = AnyPtr(uint(1)).(*uint) +// var _ *uint8 = AnyPtr(uint8(8)).(*uint8) +// var _ *uint16 = AnyPtr(uint16(16)).(*uint16) +// var _ *uint32 = AnyPtr(uint32(32)).(*uint32) +// var _ *uint64 = AnyPtr(uint64(64)).(*uint64) func AnyPtr(v interface{}) interface{} { r := reflect.New(reflect.TypeOf(v)) reflect.ValueOf(r.Interface()).Elem().Set(reflect.ValueOf(v)) diff --git a/resource.go b/resource.go index cf0a9cfb6b..2113e5eba7 100644 --- a/resource.go +++ b/resource.go @@ -1,5 +1,7 @@ package cloudflare +import "fmt" + // RouteLevel holds the "level" where the resource resides. type RouteLevel string @@ -17,6 +19,17 @@ type ResourceContainer struct { Identifier string } +// Returns a URL fragment of the endpoint scoped by the container. +// +// For example, a zone identifier would have a fragment like "zones/foobar" while +// an account identifier would generate "accounts/foobar". +func (rc *ResourceContainer) URLFragment() string { + if rc.Level == "" { + return rc.Identifier + } + return fmt.Sprintf("%s/%s", rc.Level, rc.Identifier) +} + // ResourceIdentifier returns a generic *ResourceContainer. func ResourceIdentifier(id string) *ResourceContainer { return &ResourceContainer{ From 65107c129f8525d1ac4e566be640c37a2a33a5a6 Mon Sep 17 00:00:00 2001 From: Minghang Chen Date: Thu, 9 Mar 2023 22:37:14 +0000 Subject: [PATCH 238/370] Fix markdown headings in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 988d1a3cac..2a2635ca13 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,6 @@ This library is starting to ship with experimental improvements that are not yet ready for production but will be introduced before the next major version. See [experimental README](/docs/experimental.md) for full details. -# License +## License BSD licensed. See the [LICENSE](LICENSE) file for details. From 1b2507e42f60ebecac50e79d8f7708b472c66562 Mon Sep 17 00:00:00 2001 From: Minghang Chen Date: Thu, 9 Mar 2023 22:45:09 +0000 Subject: [PATCH 239/370] changelog --- .changelog/1232.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1232.txt diff --git a/.changelog/1232.txt b/.changelog/1232.txt new file mode 100644 index 0000000000..c8e3ce2bdd --- /dev/null +++ b/.changelog/1232.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +addressing: Add `Address Map` support +``` From 76ee0445325bee98a884dad1f6d88183b7ab2b6e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 13 Mar 2023 11:10:15 +1100 Subject: [PATCH 240/370] swap booleans to pointers --- addressing_address_map.go | 13 +++++++------ addressing_address_map_test.go | 21 ++++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/addressing_address_map.go b/addressing_address_map.go index f55201d177..72577d4816 100644 --- a/addressing_address_map.go +++ b/addressing_address_map.go @@ -13,9 +13,9 @@ type AddressMap struct { ID string `json:"id"` Description *string `json:"description,omitempty"` DefaultSNI *string `json:"default_sni"` - Enabled bool `json:"enabled"` - Deletable bool `json:"can_delete"` - CanModifyIPs bool `json:"can_modify_ips"` + Enabled *bool `json:"enabled"` + Deletable *bool `json:"can_delete"` + CanModifyIPs *bool `json:"can_modify_ips"` Memberships []AddressMapMembership `json:"memberships"` IPs []AddressMapIP `json:"ips"` CreatedAt time.Time `json:"created_at"` @@ -33,9 +33,10 @@ type AddressMapMembershipContainer struct { } type AddressMapMembership struct { - AddressMapMembershipContainer - Deletable bool `json:"can_delete"` - CreatedAt time.Time `json:"created_at"` + Identifier string `json:"identifier"` + Kind AddressMapMembershipKind `json:"kind"` + Deletable *bool `json:"can_delete"` + CreatedAt time.Time `json:"created_at"` } func (ammb *AddressMapMembershipContainer) URLFragment() string { diff --git a/addressing_address_map_test.go b/addressing_address_map_test.go index b5f081f620..df545b860a 100644 --- a/addressing_address_map_test.go +++ b/addressing_address_map_test.go @@ -76,12 +76,13 @@ func TestListAddressMap(t *testing.T) { CreatedAt: createdAt, ModifiedAt: modifiedAt, Description: &addressMapDesc, - Deletable: true, - CanModifyIPs: true, + Deletable: BoolPtr(true), + CanModifyIPs: BoolPtr(true), DefaultSNI: &addressMapDefaultSNI, - Enabled: true, + Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Deletable: BoolPtr(true), }, } @@ -141,12 +142,13 @@ func TestGetAddressMap(t *testing.T) { CreatedAt: createdAt, ModifiedAt: modifiedAt, Description: &addressMapDesc, - Deletable: true, - CanModifyIPs: true, + Deletable: BoolPtr(true), + CanModifyIPs: BoolPtr(true), DefaultSNI: &addressMapDefaultSNI, - Enabled: true, + Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Deletable: BoolPtr(true), } actual, err := client.GetAddressMap(context.Background(), AccountIdentifier(testAccountID), "9a7806061c88ada191ed06f989cc3dac") @@ -205,12 +207,13 @@ func TestUpdateAddressMap(t *testing.T) { CreatedAt: createdAt, ModifiedAt: modifiedAt, Description: &addressMapDesc, - Deletable: true, - CanModifyIPs: true, + Deletable: BoolPtr(true), + CanModifyIPs: BoolPtr(true), DefaultSNI: &addressMapDefaultSNI, - Enabled: true, + Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Deletable: BoolPtr(true), } actual, err := client.UpdateAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapUpdateParams{ID: "9a7806061c88ada191ed06f989cc3dac"}) From a7570fa99f5c9c0e061b6f96cec2d852ead8c74f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 13 Mar 2023 11:10:44 +1100 Subject: [PATCH 241/370] update method parameter naming conventions --- addressing_address_map.go | 54 +++++++++++++++++++++------------- addressing_address_map_test.go | 34 ++++++++++++++------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/addressing_address_map.go b/addressing_address_map.go index 72577d4816..e4f5c60466 100644 --- a/addressing_address_map.go +++ b/addressing_address_map.go @@ -69,16 +69,16 @@ type GetAddressMapResponse struct { Result AddressMap `json:"result"` } -// AddressMapCreateParams contains information about an address map to be created. -type AddressMapCreateParams struct { +// CreateAddressMapParams contains information about an address map to be created. +type CreateAddressMapParams struct { Description *string `json:"description"` Enabled *bool `json:"enabled"` IPs []string `json:"ips"` Memberships []AddressMapMembershipContainer `json:"memberships"` } -// AddressMapUpdateParams contains information about an address map to be updated. -type AddressMapUpdateParams struct { +// UpdateAddressMapParams contains information about an address map to be updated. +type UpdateAddressMapParams struct { ID string `json:"id"` Description *string `json:"description,omitempty"` Enabled *bool `json:"enabled,omitempty"` @@ -86,35 +86,47 @@ type AddressMapUpdateParams struct { } // AddressMapFilter contains filter parameters for finding a list of address maps. -type AddressMapFilterParams struct { +type ListAddressMapsParams struct { IP *string `url:"ip,omitempty"` CIDR *string `url:"cidr,omitempty"` } -// AddressMapIPParams contains request parameters to add/remove IP address to/from an address map. -type AddressMapIPParams struct { - // ID represents the target address map for adding/removing the IP address. +// CreateIPAddressToAddressMapParams contains request parameters to add/remove IP address to/from an address map. +type CreateIPAddressToAddressMapParams struct { + // ID represents the target address map for adding the IP address. ID string // The IP address. IP string } -// AddressMapMembershipParams contains request parameters to add/remove membership from an address map. -type AddressMapMembershipParams struct { - // ID represents the target address map for adding/removing the membershp. +// CreateMembershipToAddressMapParams contains request parameters to add/remove membership from an address map. +type CreateMembershipToAddressMapParams struct { + // ID represents the target address map for adding the membershp. ID string Membership AddressMapMembershipContainer } +type DeleteMembershipFromAddressMapParams struct { + // ID represents the target address map for removing the IP address. + ID string + Membership AddressMapMembershipContainer +} + +type DeleteIPAddressFromAddressMapParams struct { + // ID represents the target address map for adding the membershp. + ID string + IP string +} + // ListAddressMaps lists all address maps owned by the account. // // API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-list-address-maps -func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, params AddressMapFilterParams) ([]AddressMap, error) { +func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, params ListAddressMapsParams) ([]AddressMap, error) { if rc.Level != AccountRouteLevel { return []AddressMap{}, ErrRequiredAccountLevelResourceContainer } - uri := buildURI(fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment()), params) + uri := buildURI(fmt.Sprintf("/%s/%s/addressing/address_maps", rc.Level, rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AddressMap{}, err @@ -131,7 +143,7 @@ func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, para // CreateAddressMap creates a new address map under the account. // // API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-create-address-map -func (api *API) CreateAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapCreateParams) (AddressMap, error) { +func (api *API) CreateAddressMap(ctx context.Context, rc *ResourceContainer, params CreateAddressMapParams) (AddressMap, error) { if rc.Level != AccountRouteLevel { return AddressMap{}, ErrRequiredAccountLevelResourceContainer } @@ -175,7 +187,7 @@ func (api *API) GetAddressMap(ctx context.Context, rc *ResourceContainer, id str // UpdateAddressMap modifies properties of an address map owned by the account. // // API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-update-address-map -func (api *API) UpdateAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapUpdateParams) (AddressMap, error) { +func (api *API) UpdateAddressMap(ctx context.Context, rc *ResourceContainer, params UpdateAddressMapParams) (AddressMap, error) { if rc.Level != AccountRouteLevel { return AddressMap{}, ErrRequiredAccountLevelResourceContainer } @@ -210,7 +222,7 @@ func (api *API) DeleteAddressMap(ctx context.Context, rc *ResourceContainer, id // CreateIPAddressToAddressMap adds an IP address from a prefix owned by the account to a particular address map. // // API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-ip-to-an-address-map -func (api *API) CreateIPAddressToAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapIPParams) error { +func (api *API) CreateIPAddressToAddressMap(ctx context.Context, rc *ResourceContainer, params CreateIPAddressToAddressMapParams) error { if rc.Level != AccountRouteLevel { return ErrRequiredAccountLevelResourceContainer } @@ -223,7 +235,7 @@ func (api *API) CreateIPAddressToAddressMap(ctx context.Context, rc *ResourceCon // DeleteIPAddressFromAddressMap removes an IP address from a particular address map. // // API reference: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-ip-from-an-address-map -func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapIPParams) error { +func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceContainer, params DeleteIPAddressFromAddressMapParams) error { if rc.Level != AccountRouteLevel { return ErrRequiredAccountLevelResourceContainer } @@ -238,7 +250,7 @@ func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceC // API reference: // - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-account-membership-to-an-address-map // - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-a-zone-membership-to-an-address-map -func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapMembershipParams) error { +func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceContainer, params CreateMembershipToAddressMapParams) error { if rc.Level != AccountRouteLevel { return ErrRequiredAccountLevelResourceContainer } @@ -247,7 +259,7 @@ func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceCo return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) } - uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) + uri := fmt.Sprintf("/%s/%s/addressing/address_maps/%s/%s", rc.Level, rc.Identifier, params.ID, params.Membership.URLFragment()) _, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil) return err } @@ -257,7 +269,7 @@ func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceCo // API reference: // - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-an-account-membership-from-an-address-map // - zone: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-remove-a-zone-membership-from-an-address-map -func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *ResourceContainer, params AddressMapMembershipParams) error { +func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *ResourceContainer, params DeleteMembershipFromAddressMapParams) error { if rc.Level != AccountRouteLevel { return ErrRequiredAccountLevelResourceContainer } @@ -266,7 +278,7 @@ func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *Resource return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) } - uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) + uri := fmt.Sprintf("/%s/%s/addressing/address_maps/%s/%s", rc.Level, rc.Identifier, params.ID, params.Membership.URLFragment()) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) return err } diff --git a/addressing_address_map_test.go b/addressing_address_map_test.go index df545b860a..0bbb3dd606 100644 --- a/addressing_address_map_test.go +++ b/addressing_address_map_test.go @@ -81,12 +81,16 @@ func TestListAddressMap(t *testing.T) { DefaultSNI: &addressMapDefaultSNI, Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, - Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Memberships: []AddressMapMembership{{ + Identifier: "01a7362d577a6c3019a474fd6f485823", + Kind: AddressMapMembershipZone, Deletable: BoolPtr(true), + CreatedAt: membershipCreatedAt, + }}, }, } - actual, err := client.ListAddressMaps(context.Background(), AccountIdentifier(testAccountID), AddressMapFilterParams{&expectedIP, &expectedCIDR}) + actual, err := client.ListAddressMaps(context.Background(), AccountIdentifier(testAccountID), ListAddressMapsParams{&expectedIP, &expectedCIDR}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -147,8 +151,12 @@ func TestGetAddressMap(t *testing.T) { DefaultSNI: &addressMapDefaultSNI, Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, - Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Memberships: []AddressMapMembership{{ + Identifier: "01a7362d577a6c3019a474fd6f485823", + Kind: AddressMapMembershipZone, Deletable: BoolPtr(true), + CreatedAt: membershipCreatedAt, + }}, } actual, err := client.GetAddressMap(context.Background(), AccountIdentifier(testAccountID), "9a7806061c88ada191ed06f989cc3dac") @@ -212,11 +220,15 @@ func TestUpdateAddressMap(t *testing.T) { DefaultSNI: &addressMapDefaultSNI, Enabled: BoolPtr(true), IPs: []AddressMapIP{{"192.0.2.1", ipCreatedAt}}, - Memberships: []AddressMapMembership{{AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}, true, membershipCreatedAt}}, + Memberships: []AddressMapMembership{{ + Identifier: "01a7362d577a6c3019a474fd6f485823", + Kind: AddressMapMembershipZone, Deletable: BoolPtr(true), + CreatedAt: membershipCreatedAt, + }}, } - actual, err := client.UpdateAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapUpdateParams{ID: "9a7806061c88ada191ed06f989cc3dac"}) + actual, err := client.UpdateAddressMap(context.Background(), AccountIdentifier(testAccountID), UpdateAddressMapParams{ID: "9a7806061c88ada191ed06f989cc3dac"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -262,7 +274,7 @@ func TestAddIPAddressToAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/ips/192.0.2.1", handler) - err := client.CreateIPAddressToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapIPParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) + err := client.CreateIPAddressToAddressMap(context.Background(), AccountIdentifier(testAccountID), CreateIPAddressToAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) assert.NoError(t, err) } @@ -283,7 +295,7 @@ func TestRemoveIPAddressFromAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/ips/192.0.2.1", handler) - err := client.DeleteIPAddressFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapIPParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) + err := client.DeleteIPAddressFromAddressMap(context.Background(), AccountIdentifier(testAccountID), DeleteIPAddressFromAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", "192.0.2.1"}) assert.NoError(t, err) } @@ -304,7 +316,7 @@ func TestAddZoneToAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/zones/01a7362d577a6c3019a474fd6f485823", handler) - err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) + err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), CreateMembershipToAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) assert.NoError(t, err) } @@ -325,7 +337,7 @@ func TestRemoveZoneFromAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/zones/01a7362d577a6c3019a474fd6f485823", handler) - err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) + err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), DeleteMembershipFromAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipZone}}) assert.NoError(t, err) } @@ -346,7 +358,7 @@ func TestAddAccountToAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/accounts/01a7362d577a6c3019a474fd6f485823", handler) - err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) + err := client.CreateMembershipToAddressMap(context.Background(), AccountIdentifier(testAccountID), CreateMembershipToAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) assert.NoError(t, err) } @@ -367,6 +379,6 @@ func TestRemoveAccountFromAddressMap(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/addressing/address_maps/9a7806061c88ada191ed06f989cc3dac/accounts/01a7362d577a6c3019a474fd6f485823", handler) - err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), AddressMapMembershipParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) + err := client.DeleteMembershipFromAddressMap(context.Background(), AccountIdentifier(testAccountID), DeleteMembershipFromAddressMapParams{"9a7806061c88ada191ed06f989cc3dac", AddressMapMembershipContainer{"01a7362d577a6c3019a474fd6f485823", AddressMapMembershipAccount}}) assert.NoError(t, err) } From 0a19349122fa545f19141b3889673124edef7d00 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 13 Mar 2023 11:11:03 +1100 Subject: [PATCH 242/370] add test coverage for resource URLFragment method --- resource_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 resource_test.go diff --git a/resource_test.go b/resource_test.go new file mode 100644 index 0000000000..ef0c96d312 --- /dev/null +++ b/resource_test.go @@ -0,0 +1,25 @@ +package cloudflare + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResourcURLFragment(t *testing.T) { + tests := map[string]struct { + container *ResourceContainer + want string + }{ + "account resource": {container: AccountIdentifier("foo"), want: "accounts/foo"}, + "zone resource": {container: ZoneIdentifier("foo"), want: "zones/foo"}, + "missing level resource": {container: &ResourceContainer{Level: "", Identifier: "foo"}, want: "foo"}, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := tc.container.URLFragment() + assert.Equal(t, tc.want, got) + }) + } +} From 9ac4a16ecf1b92f1a855d04665adb1c02949f949 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 13 Mar 2023 11:21:12 +1100 Subject: [PATCH 243/370] bump library to use 1.18 Follows our plan to support latest version minus 2 --- .github/workflows/coverage.yml | 2 +- go.mod | 2 +- go.sum | 33 --------------------------------- 3 files changed, 2 insertions(+), 35 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 57870aa4a8..2385edba1a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/cache@v3 with: path: ~/go/pkg/mod - key: ${{ runner.os }}-go1.18-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }} + key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }} - name: Run coverage run: go test ./... -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov diff --git a/go.mod b/go.mod index 4765d844bc..6de6702280 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cloudflare/cloudflare-go -go 1.17 +go 1.18 require ( github.com/google/go-querystring v1.1.0 diff --git a/go.sum b/go.sum index 5edae26d2a..d03f2e1d22 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 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= @@ -64,51 +63,19 @@ github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8= github.com/urfave/cli/v2 v2.25.0/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= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From dfb484858225f29417725cc3eea6e86038b4eef3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 13 Mar 2023 12:06:38 +1100 Subject: [PATCH 244/370] consistent use of `rc.URLFragment` --- addressing_address_map.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addressing_address_map.go b/addressing_address_map.go index e4f5c60466..9627c8a06c 100644 --- a/addressing_address_map.go +++ b/addressing_address_map.go @@ -126,7 +126,7 @@ func (api *API) ListAddressMaps(ctx context.Context, rc *ResourceContainer, para return []AddressMap{}, ErrRequiredAccountLevelResourceContainer } - uri := buildURI(fmt.Sprintf("/%s/%s/addressing/address_maps", rc.Level, rc.Identifier), params) + uri := buildURI(fmt.Sprintf("/%s/addressing/address_maps", rc.URLFragment()), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AddressMap{}, err @@ -259,7 +259,7 @@ func (api *API) CreateMembershipToAddressMap(ctx context.Context, rc *ResourceCo return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) } - uri := fmt.Sprintf("/%s/%s/addressing/address_maps/%s/%s", rc.Level, rc.Identifier, params.ID, params.Membership.URLFragment()) + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) _, err := api.makeRequestContext(ctx, http.MethodPut, uri, nil) return err } @@ -278,7 +278,7 @@ func (api *API) DeleteMembershipFromAddressMap(ctx context.Context, rc *Resource return fmt.Errorf("requested membershp kind (%q) is not supported", params.Membership.Kind) } - uri := fmt.Sprintf("/%s/%s/addressing/address_maps/%s/%s", rc.Level, rc.Identifier, params.ID, params.Membership.URLFragment()) + uri := fmt.Sprintf("/%s/addressing/address_maps/%s/%s", rc.URLFragment(), params.ID, params.Membership.URLFragment()) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) return err } From 4a2a27a4b3478feb6ecab210f00b9e37d34991a5 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 13 Mar 2023 01:13:10 +0000 Subject: [PATCH 245/370] Update CHANGELOG.md for #1232 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a7a76c5f9..42342c711c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: * access_organization: add ui_read_only_toggle_reason field ([#1181](https://github.com/cloudflare/cloudflare-go/issues/1181)) * added audit_ssh to gateway actions, updated gateway rule settings ([#1226](https://github.com/cloudflare/cloudflare-go/issues/1226)) +* addressing: Add `Address Map` support ([#1232](https://github.com/cloudflare/cloudflare-go/issues/1232)) * teams_account: add support for `check_disks` ([#1197](https://github.com/cloudflare/cloudflare-go/issues/1197)) * tunnel: updated parameters to latest API docs ([#1227](https://github.com/cloudflare/cloudflare-go/issues/1227)) From 548f91d4ccafed860ab8a9d67bd086c99af805d0 Mon Sep 17 00:00:00 2001 From: Minghang Chen Date: Mon, 13 Mar 2023 15:10:54 -0700 Subject: [PATCH 246/370] remove unexpected id field in PATCH payload --- addressing_address_map.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addressing_address_map.go b/addressing_address_map.go index 9627c8a06c..93f9f9687e 100644 --- a/addressing_address_map.go +++ b/addressing_address_map.go @@ -79,7 +79,7 @@ type CreateAddressMapParams struct { // UpdateAddressMapParams contains information about an address map to be updated. type UpdateAddressMapParams struct { - ID string `json:"id"` + ID string `json:"-"` Description *string `json:"description,omitempty"` Enabled *bool `json:"enabled,omitempty"` DefaultSNI *string `json:"default_sni,omitempty"` @@ -245,7 +245,7 @@ func (api *API) DeleteIPAddressFromAddressMap(ctx context.Context, rc *ResourceC return err } -// AddMembershipToAddressMap adds a zone/account as a member of a particular address map. +// CreateMembershipToAddressMap adds a zone/account as a member of a particular address map. // // API reference: // - account: https://developers.cloudflare.com/api/operations/ip-address-management-address-maps-add-an-account-membership-to-an-address-map From a1f9af616bd92fd37cdabb5ef13bc47e26e2364f Mon Sep 17 00:00:00 2001 From: Minghang Chen Date: Mon, 13 Mar 2023 16:39:53 -0700 Subject: [PATCH 247/370] allow for unset default_sni from addres map When PATCHING an address map, the api supports either unset the default SNI via `{"default_sni": null}`, or set it to same value via `{"default_sni": ""}`, or don't touch it a all via `{}`. This commit introuduced a helper type `JSONNullable` to support the use case. From 89598852ebd58f66ef33e7093d2ad74b9dcb964c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 15 Mar 2023 09:20:49 +1100 Subject: [PATCH 248/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42342c711c..223bfa5ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.63.0 (Unreleased) +## 0.64.0 (Unreleased) + +## 0.63.0 (15th March, 2023) BREAKING CHANGES: From 3d86d8c6d7074321fe003068ee11b4f420b29689 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 15 Mar 2023 10:26:06 +1100 Subject: [PATCH 249/370] automatically lock issues/PRs after a milestone release Updates the release process to automatically lock issues and PRs after a release to get folks to create new issues for problems instead of dogpiling. --- .github/workflows/milestone-closed.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/milestone-closed.yml b/.github/workflows/milestone-closed.yml index 5f1a045685..a919459c1b 100644 --- a/.github/workflows/milestone-closed.yml +++ b/.github/workflows/milestone-closed.yml @@ -18,3 +18,18 @@ 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: + - run: | + IFS=',' read -r -a issues <<< "$ISSUES" + for element in "${issues[@]}" + do + echo "Locking $element" + echo "no" | gh pr lock -r resolved $element + echo "no" | gh issue lock -r resolved $element + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUES: ${{ needs.comment-on-closed-milestone.outputs.ids }} From 8d97069f69112cfcd448e6cadc98dd46274f03b6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 15 Mar 2023 15:50:07 +1100 Subject: [PATCH 250/370] trim up README --- README.md | 51 +++++---------------------------------------------- 1 file changed, 5 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 2a2635ca13..dc93558467 100644 --- a/README.md +++ b/README.md @@ -21,38 +21,6 @@ A Go library for interacting with A command-line client, [flarectl](cmd/flarectl), is also available as part of this project. -## Features - -The current feature list includes: - -- [x] Cache purging -- [x] Cloudflare IPs -- [x] Custom hostnames -- [x] DNS Firewall -- [x] DNS Records -- [x] Firewall (partial) -- [x] Gateway Locations -- [x] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/) -- [x] [Load Balancing](https://blog.cloudflare.com/introducing-load-balancing-intelligent-failover-with-cloudflare/) -- [x] [Logpush Jobs](https://developers.cloudflare.com/logs/logpush/) -- [x] Magic Transit / Magic WAN -- [x] mTLS Certificate Store -- [x] Notifications -- [ ] Organization Administration -- [x] [Origin CA](https://blog.cloudflare.com/universal-ssl-encryption-all-the-way-to-the-origin-for-free/) -- [x] [Railgun](https://www.cloudflare.com/railgun/) administration -- [x] Rate Limiting -- [x] User Administration (partial) -- [x] Web Application Firewall (WAF) -- [x] Workers KV -- [x] Zone cache settings -- [x] Zone Lockdown and User-Agent Block rules -- [x] Zones -- [x] Managed Headers - -Pull Requests are welcome, but please open an issue (or comment in an existing -issue) to discuss any non-trivial changes before submitting code. - ## Installation You need a working Go environment. We officially support only currently supported Go versions according to [Go project's release policy](https://go.dev/doc/devel/release#policy). @@ -94,20 +62,6 @@ func main() { } // Print user details fmt.Println(u) - - // Fetch the zone ID - id, err := api.ZoneIDByName("example.com") // Assuming example.com exists in your Cloudflare account already - if err != nil { - log.Fatal(err) - } - - // Fetch zone details - zone, err := api.ZoneDetails(ctx, id) - if err != nil { - log.Fatal(err) - } - // Print zone details - fmt.Println(zone) } ``` @@ -121,6 +75,11 @@ This library is starting to ship with experimental improvements that are not yet ready for production but will be introduced before the next major version. See [experimental README](/docs/experimental.md) for full details. +## Contributing + +Pull Requests are welcome, but please open an issue (or comment in an existing +issue) to discuss any non-trivial changes before submitting code. + ## License BSD licensed. See the [LICENSE](LICENSE) file for details. From 43c44d74f27f13c504aefa7ded3fac2aa8cf7007 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 16:57:14 +0000 Subject: [PATCH 251/370] build(deps): bump actions/setup-go from 3 to 4 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/changelog-check.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/generate-changelog.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml index 45b8c408be..4b3616de73 100644 --- a/.github/workflows/changelog-check.yml +++ b/.github/workflows/changelog-check.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version-file: 'internal/tools/go.mod' - run: go generate -tags tools internal/tools/tools.go diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2385edba1a..749581b54f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -6,7 +6,7 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version-file: 'go.mod' - uses: actions/cache@v3 diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml index b8029ae782..691bdf3cf6 100644 --- a/.github/workflows/generate-changelog.yml +++ b/.github/workflows/generate-changelog.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version-file: 'internal/tools/go.mod' - run: go generate -tags tools internal/tools/tools.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a6351cfb1..d93438671a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version-file: 'go.mod' - name: Run GoReleaser diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5ab9bcafbc..142f386590 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: go-version: ["1.18", "1.19", "1.20"] runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} - name: Checkout code From 9d8f4b97240c59f1deb48e6134c87f17bbfc4014 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Mar 2023 16:57:34 +0000 Subject: [PATCH 252/370] add CHANGELOG for #1236 --- .changelog/1236.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1236.txt diff --git a/.changelog/1236.txt b/.changelog/1236.txt new file mode 100644 index 0000000000..bf5b7c4ace --- /dev/null +++ b/.changelog/1236.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps actions/setup-go from 3 to 4 +``` From fb8eb6914ebbdda4b8c7daab73e44b866ca38ce4 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 15 Mar 2023 21:23:31 +0000 Subject: [PATCH 253/370] Update CHANGELOG.md for #1236 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 223bfa5ef1..72b453351e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.64.0 (Unreleased) +DEPENDENCIES: + +* deps: bumps actions/setup-go from 3 to 4 ([#1236](https://github.com/cloudflare/cloudflare-go/issues/1236)) + ## 0.63.0 (15th March, 2023) BREAKING CHANGES: From bb88bafcba470c56cb049ef8cf2cbd22dd1d32b9 Mon Sep 17 00:00:00 2001 From: Jesse Li Date: Thu, 16 Mar 2023 15:24:18 -0400 Subject: [PATCH 254/370] AUTH-5081 Add claims and scopes fields to Access IDP config --- .changelog/1237.txt | 3 +++ access_identity_provider.go | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 .changelog/1237.txt diff --git a/.changelog/1237.txt b/.changelog/1237.txt new file mode 100644 index 0000000000..1c87f2721b --- /dev/null +++ b/.changelog/1237.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access_identity_provider: add `claims` and `scopes` fields +``` diff --git a/access_identity_provider.go b/access_identity_provider.go index fb986b4b23..4a793472e8 100644 --- a/access_identity_provider.go +++ b/access_identity_provider.go @@ -30,6 +30,8 @@ type AccessIdentityProviderConfiguration struct { CertsURL string `json:"certs_url,omitempty"` ClientID string `json:"client_id,omitempty"` ClientSecret string `json:"client_secret,omitempty"` + Claims []string `json:"claims,omitempty"` + Scopes []string `json:"scopes,omitempty"` DirectoryID string `json:"directory_id,omitempty"` EmailAttributeName string `json:"email_attribute_name,omitempty"` IdpPublicCert string `json:"idp_public_cert,omitempty"` From e41c0a2a615b8ee946b5ddf3698fb2181de0485d Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 17 Mar 2023 19:41:44 +0000 Subject: [PATCH 255/370] Update CHANGELOG.md for #1237 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72b453351e..d564cf6587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.64.0 (Unreleased) +ENHANCEMENTS: + +* access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) + DEPENDENCIES: * deps: bumps actions/setup-go from 3 to 4 ([#1236](https://github.com/cloudflare/cloudflare-go/issues/1236)) From 3dddb17f35eba6110ea1a1816d09a55daff378ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Puci=C5=82owski?= Date: Tue, 21 Mar 2023 18:41:00 +0100 Subject: [PATCH 256/370] Fix CreateTunnel CreateTunnel previously did not use config_src in the request --- tunnel.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tunnel.go b/tunnel.go index a43a81e35e..5d9498e13e 100644 --- a/tunnel.go +++ b/tunnel.go @@ -275,9 +275,7 @@ func (api *API) CreateTunnel(ctx context.Context, rc *ResourceContainer, params uri := fmt.Sprintf("/accounts/%s/cfd_tunnel", rc.Identifier) - tunnel := Tunnel{Name: params.Name, Secret: params.Secret} - - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, tunnel) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return Tunnel{}, err } From 74bec2416125cc3d980f7f0ef159f90d69c66b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Puci=C5=82owski?= Date: Tue, 21 Mar 2023 17:59:22 +0000 Subject: [PATCH 257/370] changelog --- .changelog/1238.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1238.txt diff --git a/.changelog/1238.txt b/.changelog/1238.txt new file mode 100644 index 0000000000..e01bf64532 --- /dev/null +++ b/.changelog/1238.txt @@ -0,0 +1,3 @@ +```release-note:bug +tunnel: Fix 'CreateTunnel' for tunnels using config_src +``` \ No newline at end of file From 0a69e78b62b4b7888757be671f41ba09f491d24c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 22 Mar 2023 01:20:54 +0000 Subject: [PATCH 258/370] Update CHANGELOG.md for #1238 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d564cf6587..6bdde3df9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) +BUG FIXES: + +* tunnel: Fix 'CreateTunnel' for tunnels using config_src ([#1238](https://github.com/cloudflare/cloudflare-go/issues/1238)) + DEPENDENCIES: * deps: bumps actions/setup-go from 3 to 4 ([#1236](https://github.com/cloudflare/cloudflare-go/issues/1236)) From 1a41f652d4c473abd2963685af9c86e55b02e061 Mon Sep 17 00:00:00 2001 From: Joao Pereira Date: Thu, 23 Mar 2023 18:01:59 +0000 Subject: [PATCH 259/370] Change UpdateDNSRecords method signature to return (DNSRecord, error) and fix resulting compilation errors --- dns.go | 13 +++++++------ dns_test.go | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/dns.go b/dns.go index d7bd308d7c..325b6f58d7 100644 --- a/dns.go +++ b/dns.go @@ -227,13 +227,13 @@ func (api *API) GetDNSRecord(ctx context.Context, rc *ResourceContainer, recordI // identifiers. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record -func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, params UpdateDNSRecordParams) error { +func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, params UpdateDNSRecordParams) (DNSRecord, error) { if rc.Identifier == "" { - return ErrMissingZoneID + return DNSRecord{}, ErrMissingZoneID } if params.ID == "" { - return ErrMissingDNSRecordID + return DNSRecord{}, ErrMissingDNSRecordID } params.Name = toUTS46ASCII(params.Name) @@ -241,14 +241,15 @@ func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, para uri := fmt.Sprintf("/zones/%s/dns_records/%s", rc.Identifier, params.ID) res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { - return err + return DNSRecord{}, err } var r DNSRecordResponse err = json.Unmarshal(res, &r) if err != nil { - return fmt.Errorf("%s: %w", errUnmarshalError, err) + return DNSRecord{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return nil + + return r.Result, nil } // DeleteDNSRecord deletes a single DNS record for the given zone & record diff --git a/dns_test.go b/dns_test.go index 46871f1626..037c856564 100644 --- a/dns_test.go +++ b/dns_test.go @@ -549,13 +549,13 @@ func TestUpdateDNSRecord(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{ID: dnsRecordID}) + _, err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(""), UpdateDNSRecordParams{ID: dnsRecordID}) assert.ErrorIs(t, err, ErrMissingZoneID) - err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{}) + _, err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{}) assert.ErrorIs(t, err, ErrMissingDNSRecordID) - err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + _, err = client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ ID: dnsRecordID, Type: "A", Name: "😺.example.com", @@ -617,7 +617,7 @@ func TestUpdateDNSRecord_ClearComment(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/dns_records/"+dnsRecordID, handler) - err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ + _, err := client.UpdateDNSRecord(context.Background(), ZoneIdentifier(testZoneID), UpdateDNSRecordParams{ ID: dnsRecordID, Comment: "", }) From 02e367b6531e017ef349763b137183c1dd5d611c Mon Sep 17 00:00:00 2001 From: Joao Pereira Date: Thu, 23 Mar 2023 18:06:50 +0000 Subject: [PATCH 260/370] Uniformize Create/UpdateDNSRecords methods' signatures and bodies rebase --- cmd/flarectl/dns.go | 24 +++++++----------------- dns.go | 17 +++++++++-------- dns_test.go | 35 ++++++++++++++++------------------- 3 files changed, 32 insertions(+), 44 deletions(-) diff --git a/cmd/flarectl/dns.go b/cmd/flarectl/dns.go index fd5a528163..5199e10271 100644 --- a/cmd/flarectl/dns.go +++ b/cmd/flarectl/dns.go @@ -50,14 +50,14 @@ func dnsCreate(c *cli.Context) error { Proxied: &proxy, Priority: &priority, } - resp, err := api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) + result, err := api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) if err != nil { fmt.Fprintln(os.Stderr, "Error creating DNS record: ", err) return err } output := [][]string{ - formatDNSRecord(resp.Result), + formatDNSRecord(result), } writeTable(c, output, "ID", "Name", "Type", "Content", "TTL", "Proxiable", "Proxy", "Locked") @@ -90,7 +90,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { return err } - var resp *cloudflare.DNSRecordResponse + var result cloudflare.DNSRecord if len(records) > 0 { // Record exists - find the ID and update it. // This is imprecise without knowing the original content; if a label @@ -105,21 +105,11 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr.Proxied = &proxy rr.Priority = &priority - err := api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) + result, err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) if err != nil { fmt.Println("Error updating DNS record:", err) return err } - resp = &cloudflare.DNSRecordResponse{ - Result: cloudflare.DNSRecord{ - ID: rr.ID, - Name: rr.Name, - Type: rr.Type, - Content: rr.Content, - TTL: rr.TTL, - Proxied: &proxy, - }, - } } } } else { @@ -131,7 +121,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { rr.Proxied = &proxy rr.Priority = &priority // TODO: Print the response. - resp, err = api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) + result, err = api.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), rr) if err != nil { fmt.Println("Error creating DNS record:", err) return err @@ -139,7 +129,7 @@ func dnsCreateOrUpdate(c *cli.Context) error { } output := [][]string{ - formatDNSRecord(resp.Result), + formatDNSRecord(result), } writeTable(c, output, "ID", "Name", "Type", "Content", "TTL", "Proxiable", "Proxy", "Locked") @@ -176,7 +166,7 @@ func dnsUpdate(c *cli.Context) error { Proxied: &proxy, Priority: &priority, } - err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) + _, err = api.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(zoneID), record) if err != nil { fmt.Fprintln(os.Stderr, "Error updating DNS record: ", err) return err diff --git a/dns.go b/dns.go index 325b6f58d7..afc47b66bd 100644 --- a/dns.go +++ b/dns.go @@ -127,25 +127,25 @@ type CreateDNSRecordParams struct { // CreateDNSRecord creates a DNS record for the zone identifier. // // API reference: https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record -func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, params CreateDNSRecordParams) (*DNSRecordResponse, error) { +func (api *API) CreateDNSRecord(ctx context.Context, rc *ResourceContainer, params CreateDNSRecordParams) (DNSRecord, error) { if rc.Identifier == "" { - return nil, ErrMissingZoneID + return DNSRecord{}, ErrMissingZoneID } params.Name = toUTS46ASCII(params.Name) uri := fmt.Sprintf("/zones/%s/dns_records", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { - return nil, err + return DNSRecord{}, err } var recordResp *DNSRecordResponse err = json.Unmarshal(res, &recordResp) if err != nil { - return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) + return DNSRecord{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return recordResp, nil + return recordResp.Result, nil } // ListDNSRecords returns a slice of DNS records for the given zone identifier. @@ -243,13 +243,14 @@ func (api *API) UpdateDNSRecord(ctx context.Context, rc *ResourceContainer, para if err != nil { return DNSRecord{}, err } - var r DNSRecordResponse - err = json.Unmarshal(res, &r) + + var recordResp *DNSRecordResponse + err = json.Unmarshal(res, &recordResp) if err != nil { return DNSRecord{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return r.Result, nil + return recordResp.Result, nil } // DeleteDNSRecord deletes a single DNS record for the given zone & record diff --git a/dns_test.go b/dns_test.go index 037c856564..3145a764c8 100644 --- a/dns_test.go +++ b/dns_test.go @@ -116,26 +116,23 @@ func TestCreateDNSRecord(t *testing.T) { createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := &DNSRecordResponse{ - Result: DNSRecord{ - ID: "372e67954025e0ba6aaa6d586b9e0b59", - Type: asciiInput.Type, - Name: asciiInput.Name, - Content: asciiInput.Content, - Proxiable: true, - Proxied: asciiInput.Proxied, - TTL: asciiInput.TTL, - ZoneID: testZoneID, - ZoneName: "example.com", - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - Data: map[string]interface{}{}, - Meta: map[string]interface{}{ - "auto_added": true, - "source": "primary", - }, + want := DNSRecord{ + ID: "372e67954025e0ba6aaa6d586b9e0b59", + Type: asciiInput.Type, + Name: asciiInput.Name, + Content: asciiInput.Content, + Proxiable: true, + Proxied: asciiInput.Proxied, + TTL: asciiInput.TTL, + ZoneID: testZoneID, + ZoneName: "example.com", + CreatedOn: createdOn, + ModifiedOn: modifiedOn, + Data: map[string]interface{}{}, + Meta: map[string]interface{}{ + "auto_added": true, + "source": "primary", }, - Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, } _, err := client.CreateDNSRecord(context.Background(), ZoneIdentifier(""), CreateDNSRecordParams{}) From c283e379449e39d424b8a7efce1e7fd2cd37843f Mon Sep 17 00:00:00 2001 From: Joao Pereira Date: Thu, 23 Mar 2023 18:41:13 +0000 Subject: [PATCH 261/370] changelog --- .changelog/1243.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1243.txt diff --git a/.changelog/1243.txt b/.changelog/1243.txt new file mode 100644 index 0000000000..f5c0728ec9 --- /dev/null +++ b/.changelog/1243.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +dns: Changed Create/UpdateDNSRecord method signatures to return (DNSRecord, error) +``` \ No newline at end of file From 7e5ae92ffa57bab4e80666add434fbd27dbbab0e Mon Sep 17 00:00:00 2001 From: Rex Scaria Date: Thu, 23 Mar 2023 15:37:42 -0400 Subject: [PATCH 262/370] feat: updated gateway teams rule settings --- .changelog/1242.txt | 3 +++ CHANGELOG.md | 4 ++++ teams_rules.go | 8 ++++---- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .changelog/1242.txt diff --git a/.changelog/1242.txt b/.changelog/1242.txt new file mode 100644 index 0000000000..461d757524 --- /dev/null +++ b/.changelog/1242.txt @@ -0,0 +1,3 @@ +```release-note:bug +teams_rules: changed a rule setting type +``` diff --git a/CHANGELOG.md b/CHANGELOG.md index d564cf6587..6bdde3df9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) +BUG FIXES: + +* tunnel: Fix 'CreateTunnel' for tunnels using config_src ([#1238](https://github.com/cloudflare/cloudflare-go/issues/1238)) + DEPENDENCIES: * deps: bumps actions/setup-go from 3 to 4 ([#1236](https://github.com/cloudflare/cloudflare-go/issues/1236)) diff --git a/teams_rules.go b/teams_rules.go index 51075012e8..d177e2c706 100644 --- a/teams_rules.go +++ b/teams_rules.go @@ -48,11 +48,11 @@ type TeamsRuleSettings struct { // Turns on ip category based filter on dns if the rule contains dns category checks IPCategories bool `json:"ip_categories"` - // Allow parent MSP accounts to enable bypass their children's rules. - AllowChildBypass bool `json:"allow_child_bypass"` + // Allow parent MSP accounts to enable bypass their children's rules. Do not set them for non MSP accounts. + AllowChildBypass *bool `json:"allow_child_bypass,omitempty"` - // Allow child MSP accounts to bypass their parent's rules - BypassParentRule bool `json:"bypass_parent_rule"` + // Allow child MSP accounts to bypass their parent's rules. Do not set them for non MSP accounts. + BypassParentRule *bool `json:"bypass_parent_rule,omitempty"` // Action taken when an untrusted origin certificate error occurs in a http allow rule UntrustedCertSettings *UntrustedCertSettings `json:"untrusted_cert"` From b3adae06f54b461d9ff6c79f856ff12bbf1555f3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 24 Mar 2023 07:48:03 +1100 Subject: [PATCH 263/370] make changelog more specific --- .changelog/1242.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.changelog/1242.txt b/.changelog/1242.txt index 461d757524..f847da86f8 100644 --- a/.changelog/1242.txt +++ b/.changelog/1242.txt @@ -1,3 +1,7 @@ ```release-note:bug -teams_rules: changed a rule setting type +teams_rules: `AllowChildBypass` changes from a `bool` to `*bool` +``` + +```release-note:bug +teams_rules: `BypassParentRule` changes from a `bool` to `*bool` ``` From 8bb87d355860f94429d2c3d351cb5daa6ca761c0 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 23 Mar 2023 22:54:44 +0000 Subject: [PATCH 264/370] Update CHANGELOG.md for #1242 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bdde3df9c..58eb6c86ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ENHANCEMENTS: BUG FIXES: +* teams_rules: `AllowChildBypass` changes from a `bool` to `*bool` ([#1242](https://github.com/cloudflare/cloudflare-go/issues/1242)) +* teams_rules: `BypassParentRule` changes from a `bool` to `*bool` ([#1242](https://github.com/cloudflare/cloudflare-go/issues/1242)) * tunnel: Fix 'CreateTunnel' for tunnels using config_src ([#1238](https://github.com/cloudflare/cloudflare-go/issues/1238)) DEPENDENCIES: From fc4b244204c6e679f5f6ab71a42226315993f558 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Mar 2023 03:04:19 +0000 Subject: [PATCH 265/370] Update CHANGELOG.md for #1178 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58eb6c86ad..26c470abf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) +* access_identity_provider: add scim_config field ([#1178](https://github.com/cloudflare/cloudflare-go/issues/1178)) BUG FIXES: From 0a2244303cb0851c57a2202262d16543c62e8aaf Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 24 Mar 2023 03:10:01 +0000 Subject: [PATCH 266/370] Update CHANGELOG.md for #1243 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26c470abf8..4623d3a888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.64.0 (Unreleased) +BREAKING CHANGES: + +* dns: Changed Create/UpdateDNSRecord method signatures to return (DNSRecord, error) ([#1243](https://github.com/cloudflare/cloudflare-go/issues/1243)) + ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) From 4cb37fbc33a6b310018912c37ce6646a2ca5df75 Mon Sep 17 00:00:00 2001 From: Janik Rabe Date: Fri, 24 Mar 2023 14:18:47 +0000 Subject: [PATCH 267/370] DNS-8918: DNS Firewall: rename origin_ips to upstream_ips This field has been renamed for consistency. --- .changelog/1246.txt | 3 +++ dns_firewall.go | 2 +- virtualdns.go | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 .changelog/1246.txt diff --git a/.changelog/1246.txt b/.changelog/1246.txt new file mode 100644 index 0000000000..678b27fd5e --- /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/dns_firewall.go b/dns_firewall.go index d426e8989e..a6282aea20 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/virtualdns.go b/virtualdns.go index ad4ed02575..d4bc91bd96 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, From deaa2f4cb7aa5f6c717a3bf8c0c36d2a172dfc55 Mon Sep 17 00:00:00 2001 From: Dawson Hensel Date: Mon, 27 Mar 2023 08:32:26 -0700 Subject: [PATCH 268/370] Enumerate service modes with constant values --- .changelog/1249.txt | 3 +++ devices_policy.go | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 .changelog/1249.txt diff --git a/.changelog/1249.txt b/.changelog/1249.txt new file mode 100644 index 0000000000..362b4726b1 --- /dev/null +++ b/.changelog/1249.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +service_mode_v2: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values +``` diff --git a/devices_policy.go b/devices_policy.go index 2e537757e1..2664a260c7 100644 --- a/devices_policy.go +++ b/devices_policy.go @@ -17,9 +17,19 @@ type DeviceClientCertificatesZone struct { Result Enabled } +type ServiceMode string + +const ( + oneDotOne ServiceMode = "1dot1" + warp ServiceMode = "warp" + proxy ServiceMode = "proxy" + postureOnly ServiceMode = "posture_only" + warpTunnelOnly ServiceMode = "warp_tunnel_only" +) + type ServiceModeV2 struct { - Mode string `json:"mode,omitempty"` - Port int `json:"port,omitempty"` + Mode ServiceMode `json:"mode,omitempty"` + Port int `json:"port,omitempty"` } type DeviceSettingsPolicy struct { From 6aadab9b2a5f471131588ad511e242f97c2f2b47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 16:57:16 +0000 Subject: [PATCH 269/370] build(deps): bump github.com/urfave/cli/v2 from 2.25.0 to 2.25.1 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.0 to 2.25.1. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.25.0...v2.25.1) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6de6702280..6621944699 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( 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.0 + github.com/urfave/cli/v2 v2.25.1 golang.org/x/net v0.8.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index d03f2e1d22..1056aff36b 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8= -github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +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/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.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= From 91bc448723a9df210e0254c2b72f340d4b0ab6ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 27 Mar 2023 16:57:36 +0000 Subject: [PATCH 270/370] add CHANGELOG for #1250 --- .changelog/1250.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1250.txt diff --git a/.changelog/1250.txt b/.changelog/1250.txt new file mode 100644 index 0000000000..8f1a611d51 --- /dev/null +++ b/.changelog/1250.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.25.0 to 2.25.1 +``` From 84bf66d2395aba3b6eb8ec47ad227cf40c717085 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 27 Mar 2023 19:49:36 +0000 Subject: [PATCH 271/370] Update CHANGELOG.md for #1250 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4623d3a888..580a992c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ BUG FIXES: DEPENDENCIES: * deps: bumps actions/setup-go from 3 to 4 ([#1236](https://github.com/cloudflare/cloudflare-go/issues/1236)) +* deps: bumps github.com/urfave/cli/v2 from 2.25.0 to 2.25.1 ([#1250](https://github.com/cloudflare/cloudflare-go/issues/1250)) ## 0.63.0 (15th March, 2023) From 0c3db86282352878154a63c9bc67764dfded0780 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 28 Mar 2023 14:41:35 +1100 Subject: [PATCH 272/370] update changelog entry --- .changelog/1249.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1249.txt b/.changelog/1249.txt index 362b4726b1..0f2cbedf95 100644 --- a/.changelog/1249.txt +++ b/.changelog/1249.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -service_mode_v2: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values +devices_policy: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values ``` From 493135328918e67d71043dc32ef4ea62dc92ca0f Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 28 Mar 2023 03:42:31 +0000 Subject: [PATCH 273/370] Update CHANGELOG.md for #1249 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 580a992c6e..33b58de431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) * access_identity_provider: add scim_config field ([#1178](https://github.com/cloudflare/cloudflare-go/issues/1178)) +* devices_policy: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values ([#1249](https://github.com/cloudflare/cloudflare-go/issues/1249)) BUG FIXES: From c1233314e657953a4375369e736055db3ce104c2 Mon Sep 17 00:00:00 2001 From: Nicky Semenza Date: Thu, 23 Mar 2023 12:58:34 -0700 Subject: [PATCH 274/370] update geo_restrictions to be a pointer in the response struct, just like in the request struct noticed this while working on https://github.com/cloudflare/terraform-provider-cloudflare/pull/2319 but this isn't a requirement for that. --- .changelog/1244.txt | 3 +++ ssl.go | 26 +++++++++++++------------- ssl_test.go | 4 ++-- 3 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 .changelog/1244.txt diff --git a/.changelog/1244.txt b/.changelog/1244.txt new file mode 100644 index 0000000000..fa7858c06f --- /dev/null +++ b/.changelog/1244.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +ssl: make `GeoRestrictions` a pointer inside of ZoneCustomSSL +``` \ No newline at end of file diff --git a/ssl.go b/ssl.go index 125ab02ac8..178e98c6ca 100644 --- a/ssl.go +++ b/ssl.go @@ -10,19 +10,19 @@ import ( // ZoneCustomSSL represents custom SSL certificate metadata. type ZoneCustomSSL struct { - ID string `json:"id"` - Hosts []string `json:"hosts"` - Issuer string `json:"issuer"` - Signature string `json:"signature"` - Status string `json:"status"` - BundleMethod string `json:"bundle_method"` - GeoRestrictions ZoneCustomSSLGeoRestrictions `json:"geo_restrictions"` - ZoneID string `json:"zone_id"` - UploadedOn time.Time `json:"uploaded_on"` - ModifiedOn time.Time `json:"modified_on"` - ExpiresOn time.Time `json:"expires_on"` - Priority int `json:"priority"` - KeylessServer KeylessSSL `json:"keyless_server"` + ID string `json:"id"` + Hosts []string `json:"hosts"` + Issuer string `json:"issuer"` + Signature string `json:"signature"` + Status string `json:"status"` + BundleMethod string `json:"bundle_method"` + GeoRestrictions *ZoneCustomSSLGeoRestrictions `json:"geo_restrictions,omitempty"` + ZoneID string `json:"zone_id"` + UploadedOn time.Time `json:"uploaded_on"` + ModifiedOn time.Time `json:"modified_on"` + ExpiresOn time.Time `json:"expires_on"` + Priority int `json:"priority"` + KeylessServer KeylessSSL `json:"keyless_server"` } // ZoneCustomSSLGeoRestrictions represents the parameter to create or update diff --git a/ssl_test.go b/ssl_test.go index 78dd51022f..ea43e63cfe 100644 --- a/ssl_test.go +++ b/ssl_test.go @@ -64,7 +64,7 @@ func TestCreateSSL(t *testing.T) { Signature: "SHA256WithRSA", Status: "active", BundleMethod: "ubiquitous", - GeoRestrictions: ZoneCustomSSLGeoRestrictions{Label: "us"}, + GeoRestrictions: &ZoneCustomSSLGeoRestrictions{Label: "us"}, ZoneID: "023e105f4ecef8ad9ca31a8372d0c353", UploadedOn: uploadedOn, ModifiedOn: modifiedOn, @@ -266,7 +266,7 @@ func TestUpdateSSL(t *testing.T) { Signature: "SHA256WithRSA", Status: "active", BundleMethod: "ubiquitous", - GeoRestrictions: ZoneCustomSSLGeoRestrictions{Label: "us"}, + GeoRestrictions: &ZoneCustomSSLGeoRestrictions{Label: "us"}, ZoneID: "023e105f4ecef8ad9ca31a8372d0c353", UploadedOn: uploadedOn, ModifiedOn: modifiedOn, From dbc7a5f0dfebd1e59f26ed51bec58302e8ea06f2 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 28 Mar 2023 21:02:22 +0000 Subject: [PATCH 275/370] Update CHANGELOG.md for #1244 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33b58de431..a61097886e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: * access_identity_provider: add `claims` and `scopes` fields ([#1237](https://github.com/cloudflare/cloudflare-go/issues/1237)) * access_identity_provider: add scim_config field ([#1178](https://github.com/cloudflare/cloudflare-go/issues/1178)) * devices_policy: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values ([#1249](https://github.com/cloudflare/cloudflare-go/issues/1249)) +* ssl: make `GeoRestrictions` a pointer inside of ZoneCustomSSL ([#1244](https://github.com/cloudflare/cloudflare-go/issues/1244)) BUG FIXES: From c30057398cc93c6933873286e5ee0b0aa6ef39ba Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 29 Mar 2023 10:08:07 +1100 Subject: [PATCH 276/370] zone: make settings more flexible For the life of this library, the settings have always been under the `/zones/:zone_id/settings` route which was an aggregate of all the settings. This was designed as a way to aggregate all of the settings in one place and had its place however, now we are breaking up the zone settings to their true paths and need to make the `Get` and `Update` zone settings compatible with this approach. This will enable teams to use their true paths instead of the prefixed or aggregate paths with no friction from the library. --- .changelog/1251.txt | 11 +++++ errors.go | 2 + zone.go | 63 +++++++++++++++++++++++----- zone_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 .changelog/1251.txt diff --git a/.changelog/1251.txt b/.changelog/1251.txt new file mode 100644 index 0000000000..b750d6ebf6 --- /dev/null +++ b/.changelog/1251.txt @@ -0,0 +1,11 @@ +```release-note:breaking-change +zone: `ZoneSingleSetting` has been renamed to `GetZoneSetting` and updated method signature inline with our expected conventions +``` + +```release-note:breaking-change +zone: `UpdateZoneSingleSetting` has been renamed to `UpdateZoneSetting` and updated method signature inline with our expected conventions +``` + +```release-note:enhancement +zone: `GetZoneSetting` and `UpdateZoneSetting` now allow configuring the path for where a setting resides instead of assuming `settings` +``` diff --git a/errors.go b/errors.go index 723c18bae3..85fdc3efac 100644 --- a/errors.go +++ b/errors.go @@ -31,6 +31,7 @@ const ( errInvalidResourceContainerAccess = "requested resource container (%q) is not supported for this endpoint" errRequiredAccountLevelResourceContainer = "this endpoint requires using an account level resource container and identifiers" + errRequiredZoneLevelResourceContainer = "this endpoint requires using a zone level resource container and identifiers" ) var ( @@ -43,6 +44,7 @@ var ( ErrMissingResourceIdentifier = errors.New(errMissingResourceIdentifier) ErrRequiredAccountLevelResourceContainer = errors.New(errRequiredAccountLevelResourceContainer) + ErrRequiredZoneLevelResourceContainer = errors.New(errRequiredZoneLevelResourceContainer) ) type ErrorType string diff --git a/zone.go b/zone.go index ba544c7896..59489f50c9 100644 --- a/zone.go +++ b/zone.go @@ -14,6 +14,11 @@ import ( "golang.org/x/net/idna" ) +var ( + // ErrMissingSettingName is for when setting name is required but missing. + ErrMissingSettingName = errors.New("zone setting name required but missing") +) + // Owner describes the resource owner. type Owner struct { ID string `json:"id"` @@ -300,6 +305,17 @@ type zoneSubscriptionRatePlanPayload struct { } `json:"rate_plan"` } +type GetZoneSettingParams struct { + Name string `json:"-"` + PathPrefix string `json:"-"` +} + +type UpdateZoneSettingParams struct { + Name string `json:"-"` + PathPrefix string `json:"-"` + Value interface{} `json:"value"` +} + // CreateZone creates a zone on an account. // // Setting jumpstart to true will attempt to automatically scan for existing @@ -897,11 +913,25 @@ func normalizeZoneName(name string) string { return name } -// ZoneSingleSetting returns information about specified setting to the specified zone. +// GetZoneSetting returns information about specified setting to the specified +// zone. // // API reference: https://api.cloudflare.com/#zone-settings-get-all-zone-settings -func (api *API) ZoneSingleSetting(ctx context.Context, zoneID, settingName string) (ZoneSetting, error) { - uri := fmt.Sprintf("/zones/%s/settings/%s", zoneID, settingName) +func (api *API) GetZoneSetting(ctx context.Context, rc *ResourceContainer, params GetZoneSettingParams) (ZoneSetting, error) { + if rc.Level != ZoneRouteLevel { + return ZoneSetting{}, ErrRequiredZoneLevelResourceContainer + } + + if rc.Identifier == "" { + return ZoneSetting{}, ErrMissingName + } + + pathPrefix := "settings" + if params.PathPrefix != "" { + pathPrefix = params.PathPrefix + } + + uri := fmt.Sprintf("/zones/%s/%s/%s", rc.Identifier, pathPrefix, params.Name) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return ZoneSetting{}, err @@ -914,23 +944,36 @@ func (api *API) ZoneSingleSetting(ctx context.Context, zoneID, settingName strin return r.Result, nil } -// UpdateZoneSingleSetting updates the specified setting for a given zone. +// UpdateZoneSetting updates the specified setting for a given zone. // // API reference: https://api.cloudflare.com/#zone-settings-edit-zone-settings-info -func (api *API) UpdateZoneSingleSetting(ctx context.Context, zoneID, settingName string, setting ZoneSetting) (*ZoneSettingSingleResponse, error) { - uri := fmt.Sprintf("/zones/%s/settings/%s", zoneID, settingName) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, setting) +func (api *API) UpdateZoneSetting(ctx context.Context, rc *ResourceContainer, params UpdateZoneSettingParams) (ZoneSetting, error) { + if rc.Level != ZoneRouteLevel { + return ZoneSetting{}, ErrRequiredZoneLevelResourceContainer + } + + if rc.Identifier == "" { + return ZoneSetting{}, ErrMissingName + } + + pathPrefix := "settings" + if params.PathPrefix != "" { + pathPrefix = params.PathPrefix + } + + uri := fmt.Sprintf("/zones/%s/%s/%s", rc.Identifier, pathPrefix, params.Name) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { - return nil, err + return ZoneSetting{}, err } response := &ZoneSettingSingleResponse{} err = json.Unmarshal(res, &response) if err != nil { - return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) + return ZoneSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - return response, nil + return response.Result, nil } // ZoneExport returns the text BIND config for the given zone diff --git a/zone_test.go b/zone_test.go index 93a2bb6fd5..6dd5bc4fcc 100644 --- a/zone_test.go +++ b/zone_test.go @@ -1510,3 +1510,103 @@ func TestUpdateZoneSSLSettings(t *testing.T) { assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") } } + +func TestGetZoneSetting(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, `{ + "result": { + "id": "ssl", + "value": "off", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/settings/ssl", handler) + s, err := client.GetZoneSetting(context.Background(), ZoneIdentifier("foo"), GetZoneSettingParams{Name: "ssl"}) + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl") + assert.Equal(t, s.Value, "off") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + } +} + +func TestGetZoneSettingWithCustomPathPrefix(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, `{ + "result": { + "id": "ssl", + "value": "off", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/my_custom_path/ssl", handler) + s, err := client.GetZoneSetting(context.Background(), ZoneIdentifier("foo"), GetZoneSettingParams{Name: "ssl", PathPrefix: "my_custom_path"}) + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl") + assert.Equal(t, s.Value, "off") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + } +} + +func TestUpdateZoneSetting(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, `{ + "result": { + "id": "ssl", + "value": "off", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/settings/ssl", handler) + s, err := client.UpdateZoneSetting(context.Background(), ZoneIdentifier("foo"), UpdateZoneSettingParams{Name: "ssl", Value: "off"}) + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl") + assert.Equal(t, s.Value, "off") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + } +} + +func TestUpdateZoneSettingWithCustomPathPrefix(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, `{ + "result": { + "id": "ssl", + "value": "off", + "editable": true, + "modified_on": "2014-01-01T05:20:00.12345Z" + } + }`) + } + mux.HandleFunc("/zones/foo/my_custom_path/ssl", handler) + s, err := client.UpdateZoneSetting(context.Background(), ZoneIdentifier("foo"), UpdateZoneSettingParams{Name: "ssl", PathPrefix: "my_custom_path", Value: "off"}) + if assert.NoError(t, err) { + assert.Equal(t, s.ID, "ssl") + assert.Equal(t, s.Value, "off") + assert.Equal(t, s.Editable, true) + assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z") + } +} From da04f2576fee6a47981993c6fa5002b82da62445 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 28 Mar 2023 23:25:45 +0000 Subject: [PATCH 277/370] Update CHANGELOG.md for #1251 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a61097886e..875295f411 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ BREAKING CHANGES: * dns: Changed Create/UpdateDNSRecord method signatures to return (DNSRecord, error) ([#1243](https://github.com/cloudflare/cloudflare-go/issues/1243)) +* zone: `UpdateZoneSingleSetting` has been renamed to `UpdateZoneSetting` and updated method signature inline with our expected conventions ([#1251](https://github.com/cloudflare/cloudflare-go/issues/1251)) +* zone: `ZoneSingleSetting` has been renamed to `GetZoneSetting` and updated method signature inline with our expected conventions ([#1251](https://github.com/cloudflare/cloudflare-go/issues/1251)) ENHANCEMENTS: @@ -10,6 +12,7 @@ ENHANCEMENTS: * access_identity_provider: add scim_config field ([#1178](https://github.com/cloudflare/cloudflare-go/issues/1178)) * devices_policy: update `Mode` field to use new `ServiceMode` string type with explicit const service mode values ([#1249](https://github.com/cloudflare/cloudflare-go/issues/1249)) * ssl: make `GeoRestrictions` a pointer inside of ZoneCustomSSL ([#1244](https://github.com/cloudflare/cloudflare-go/issues/1244)) +* zone: `GetZoneSetting` and `UpdateZoneSetting` now allow configuring the path for where a setting resides instead of assuming `settings` ([#1251](https://github.com/cloudflare/cloudflare-go/issues/1251)) BUG FIXES: From 8aaea558c437a90cb85eca8c949659f044081ba8 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 29 Mar 2023 16:02:45 +1100 Subject: [PATCH 278/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 875295f411..a1d781302b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.64.0 (Unreleased) +## 0.65.0 (Unreleased) + +## 0.64.0 (29th March, 2023) BREAKING CHANGES: From 5b56c6be6b51f48384e43aa71c2b106116b36cb0 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 29 Mar 2023 16:06:29 +1100 Subject: [PATCH 279/370] Update milestone-closed.yml --- .github/workflows/milestone-closed.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/milestone-closed.yml b/.github/workflows/milestone-closed.yml index a919459c1b..99e768a9c5 100644 --- a/.github/workflows/milestone-closed.yml +++ b/.github/workflows/milestone-closed.yml @@ -27,9 +27,9 @@ jobs: for element in "${issues[@]}" do echo "Locking $element" - echo "no" | gh pr lock -r resolved $element - echo "no" | gh issue lock -r resolved $element + echo "no" | gh pr lock -r resolved $element || true + echo "no" | gh issue lock -r resolved $element || true done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUES: ${{ needs.comment-on-closed-milestone.outputs.ids }} + ISSUES: ${{ jobs.comment-on-closed-milestone.outputs.ids }} From 0d05fc09483641dde8abb4c64cf2f6016f590d79 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 29 Mar 2023 16:07:09 +1100 Subject: [PATCH 280/370] Create lock-released-issues.yml --- .github/workflows/lock-released-issues.yml | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/lock-released-issues.yml diff --git a/.github/workflows/lock-released-issues.yml b/.github/workflows/lock-released-issues.yml new file mode 100644 index 0000000000..e165223f1a --- /dev/null +++ b/.github/workflows/lock-released-issues.yml @@ -0,0 +1,29 @@ +name: Lock released issues and PRs + +on: + workflow_dispatch: + inputs: + issue_list: + description: Comma seperated (no spaces) list of issues/PRs to lock + required: true + +permissions: + issues: write + pull-requests: write + +jobs: + lock-closed-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: | + IFS=',' read -r -a issues <<< "$ISSUES" + for element in "${issues[@]}" + do + echo "Locking $element" + echo "no" | gh pr lock -r resolved $element || true + echo "no" | gh issue lock -r resolved $element || true + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUES: ${{ github.event.inputs.issue_list }} From fb03b8ed782ca47584e5de2c520261bddca45ea6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 30 Mar 2023 14:16:08 +1100 Subject: [PATCH 281/370] ignore .flox directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5acd30652d..0953e13b27 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ cmd/flarectl/dist/ cmd/flarectl/flarectl cmd/flarectl/flarectl.exe +.flox/ From c2c3c9d2d9db0dc30f980e7ba2d94dcac9739ea2 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 30 Mar 2023 14:16:20 +1100 Subject: [PATCH 282/370] add basic flox setup --- catalog.json | 67 +++++++ flake.lock | 540 +++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 7 + flox.nix | 3 + 4 files changed, 617 insertions(+) create mode 100644 catalog.json create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 flox.nix diff --git a/catalog.json b/catalog.json new file mode 100644 index 0000000000..97847246e4 --- /dev/null +++ b/catalog.json @@ -0,0 +1,67 @@ +{ + "nixpkgs-flox": { + "x86_64-darwin": { + "stable": { + "go_1_20": { + "latest": { + "cache": { + "out": { + "https://cache.nixos.org": {} + } + }, + "element": { + "attrPath": [ + "legacyPackages", + "x86_64-darwin", + "go_1_20" + ], + "originalUrl": "flake:nixpkgs", + "storePaths": [ + "/nix/store/0pp0svlrkdls28dixb6a7kqa567gs59v-go-1.20.1" + ], + "url": "github:flox/nixpkgs/d0d55259081f0b97c828f38559cad899d351cad1" + }, + "eval": { + "meta": { + "description": "The Go Programming language", + "outputsToInstall": [ + "out" + ], + "position": "/nix/store/32cp7y0cf36h3xp0fqwy2nf432fpcaci-source/pkgs/development/compilers/go/1.20.nix:176", + "unfree": false + }, + "name": "go-1.20.1", + "outputs": { + "out": "/nix/store/0pp0svlrkdls28dixb6a7kqa567gs59v-go-1.20.1" + }, + "pname": "go", + "system": "x86_64-darwin", + "version": "1.20.1" + }, + "publish_element": { + "attrPath": [ + "evalCatalog", + "x86_64-darwin", + "stable", + "go_1_20" + ], + "originalUrl": "flake:nixpkgs-flox", + "storePaths": [ + "/nix/store/0pp0svlrkdls28dixb6a7kqa567gs59v-go-1.20.1" + ], + "url": "flake:nixpkgs-flox/b7e7e40e2aa1ca2a44db440f5dc52213564af02f" + }, + "source": { + "locked": { + "lastModified": 1676973346, + "revCount": 456418 + } + }, + "type": "catalogRender", + "version": 1 + } + } + } + } + } +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..153b6ef7dd --- /dev/null +++ b/flake.lock @@ -0,0 +1,540 @@ +{ + "nodes": { + "builtfilter": { + "inputs": { + "flox-floxpkgs": [ + "flox-floxpkgs" + ] + }, + "locked": { + "lastModified": 1679586988, + "narHash": "sha256-TkoF4E4yN40s042YG6DaOzk+vtbzsoey0lUO+tm03is=", + "owner": "flox", + "repo": "builtfilter", + "rev": "931a381bb96d909f51fcf25d7ca4fa9dcfb12aff", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "builtfilter-rs", + "repo": "builtfilter", + "type": "github" + } + }, + "capacitor": { + "inputs": { + "nixpkgs": "nixpkgs", + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1675110136, + "narHash": "sha256-83n/ZLBMoIkgYGy12F1hNaqMUgJsfkno5P1+sm9liOU=", + "owner": "flox", + "repo": "capacitor", + "rev": "9d4b9bce0f439e01fe2c2b2a1bfe08592a6204c4", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "v0", + "repo": "capacitor", + "type": "github" + } + }, + "capacitor_2": { + "inputs": { + "nixpkgs": [ + "flox-floxpkgs", + "nixpkgs", + "nixpkgs" + ], + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1675110136, + "narHash": "sha256-83n/ZLBMoIkgYGy12F1hNaqMUgJsfkno5P1+sm9liOU=", + "owner": "flox", + "repo": "capacitor", + "rev": "9d4b9bce0f439e01fe2c2b2a1bfe08592a6204c4", + "type": "github" + }, + "original": { + "owner": "flox", + "repo": "capacitor", + "type": "github" + } + }, + "catalog": { + "flake": false, + "locked": { + "lastModified": 1665076737, + "narHash": "sha256-S0bD7Z434Lvm7U4VHwvmxdTMrexdr72Yk6z0ExE3j7s=", + "owner": "flox", + "repo": "floxpkgs", + "rev": "bd8326c2fea27d01933eacb922f5ae70f97140c6", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "publish", + "repo": "floxpkgs", + "type": "github" + } + }, + "commitizen-src": { + "flake": false, + "locked": { + "lastModified": 1679149521, + "narHash": "sha256-F/fbBEwG7ijHELy4RnpvlXOPkTsXFxjALdK7UIGIzMo=", + "owner": "commitizen-tools", + "repo": "commitizen", + "rev": "378a42881891633d8a81939cb46426eb36ed01aa", + "type": "github" + }, + "original": { + "owner": "commitizen-tools", + "repo": "commitizen", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flox": { + "inputs": { + "commitizen-src": "commitizen-src", + "flox-bash": [ + "flox-floxpkgs", + "flox-bash" + ], + "flox-floxpkgs": [ + "flox-floxpkgs" + ], + "shellHooks": "shellHooks" + }, + "locked": { + "lastModified": 1679679655, + "narHash": "sha256-zug5lg3CqDMkmtbort6CHFJgUPyzRip0tg7t3dbSTWo=", + "ref": "main", + "rev": "98a44ab06d9f9f5e4824fd3add2d32aef95e606f", + "revCount": 427, + "type": "git", + "url": "ssh://git@github.com/flox/flox" + }, + "original": { + "ref": "main", + "type": "git", + "url": "ssh://git@github.com/flox/flox" + } + }, + "flox-bash": { + "inputs": { + "flox-floxpkgs": [ + "flox-floxpkgs" + ] + }, + "locked": { + "lastModified": 1679665116, + "narHash": "sha256-v1qgb6rOVa9q8oIlps/Z4kw7+YQqN3AsScNEgy5xwGQ=", + "ref": "main", + "rev": "db7efcacb5f5935b286006288f23f931a573a918", + "revCount": 216, + "type": "git", + "url": "ssh://git@github.com/flox/flox-bash" + }, + "original": { + "ref": "main", + "type": "git", + "url": "ssh://git@github.com/flox/flox-bash" + } + }, + "flox-floxpkgs": { + "inputs": { + "builtfilter": "builtfilter", + "capacitor": "capacitor", + "catalog": "catalog", + "flox": "flox", + "flox-bash": "flox-bash", + "nixpkgs": "nixpkgs_3", + "tracelinks": "tracelinks" + }, + "locked": { + "lastModified": 1680131458, + "narHash": "sha256-B0xvpF2h5iotKAMP13l0VtsXRAPwKQLitmxKdBSWLQQ=", + "owner": "flox", + "repo": "floxpkgs", + "rev": "6d8216d24ce8959b599107ccff8b15c959540b1a", + "type": "github" + }, + "original": { + "owner": "flox", + "repo": "floxpkgs", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "flox-floxpkgs", + "flox", + "shellHooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1676973346, + "narHash": "sha256-rft8oGMocTAhUVqG3LW6I8K/Fo9ICGmNjRqaWTJwav0=", + "owner": "flox", + "repo": "nixpkgs", + "rev": "d0d55259081f0b97c828f38559cad899d351cad1", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "stable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1679791877, + "narHash": "sha256-tTV1Mf0hPWIMtqyU16Kd2JUBDWvfHlDC9pF57vcbgpQ=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "cc060ddbf652a532b54057081d5abd6144d01971", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1679791877, + "narHash": "sha256-tTV1Mf0hPWIMtqyU16Kd2JUBDWvfHlDC9pF57vcbgpQ=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "cc060ddbf652a532b54057081d5abd6144d01971", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1676973346, + "narHash": "sha256-rft8oGMocTAhUVqG3LW6I8K/Fo9ICGmNjRqaWTJwav0=", + "owner": "flox", + "repo": "nixpkgs", + "rev": "d0d55259081f0b97c828f38559cad899d351cad1", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "stable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-staging": { + "locked": { + "lastModified": 1679262748, + "narHash": "sha256-DQCrrAFrkxijC6haUzOC5ZoFqpcv/tg2WxnyW3np1Cc=", + "owner": "flox", + "repo": "nixpkgs", + "rev": "60c1d71f2ba4c80178ec84523c2ca0801522e0a6", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "staging", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1679944645, + "narHash": "sha256-e5Qyoe11UZjVfgRfwNoSU57ZeKuEmjYb77B9IVW7L/M=", + "owner": "flox", + "repo": "nixpkgs", + "rev": "4bb072f0a8b267613c127684e099a70e1f6ff106", + "type": "github" + }, + "original": { + "owner": "flox", + "ref": "unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1678898370, + "narHash": "sha256-xTICr1j+uat5hk9FyuPOFGxpWHdJRibwZC+ATi0RbtE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ac718d02867a84b42522a0ece52d841188208f2c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "inputs": { + "capacitor": "capacitor_2", + "flox": [ + "flox-floxpkgs", + "flox" + ], + "flox-bash": [ + "flox-floxpkgs", + "flox-bash" + ], + "flox-floxpkgs": [ + "flox-floxpkgs" + ], + "nixpkgs": [ + "flox-floxpkgs", + "nixpkgs", + "nixpkgs-stable" + ], + "nixpkgs-stable": "nixpkgs-stable_2", + "nixpkgs-staging": "nixpkgs-staging", + "nixpkgs-unstable": "nixpkgs-unstable", + "nixpkgs__flox__aarch64-darwin": "nixpkgs__flox__aarch64-darwin", + "nixpkgs__flox__aarch64-linux": "nixpkgs__flox__aarch64-linux", + "nixpkgs__flox__i686-linux": "nixpkgs__flox__i686-linux", + "nixpkgs__flox__x86_64-darwin": "nixpkgs__flox__x86_64-darwin", + "nixpkgs__flox__x86_64-linux": "nixpkgs__flox__x86_64-linux" + }, + "locked": { + "lastModified": 1680113891, + "narHash": "sha256-JiAmKV8ECf877cDbTum06NQ28n8FvwC4DYlCYzEVWxg=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "b7e7e40e2aa1ca2a44db440f5dc52213564af02f", + "type": "github" + }, + "original": { + "owner": "flox", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "nixpkgs__flox__aarch64-darwin": { + "flake": false, + "locked": { + "host": "catalog.floxsdlc.com", + "lastModified": 1680113678, + "narHash": "sha256-rCkwbly3gyvNcw21VBMXcf6EmF7crKZAS8Ylh2B5H+I=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "31d3b5fafdf504842e1e47a0c9b5888cf5dbae06", + "type": "github" + }, + "original": { + "host": "catalog.floxsdlc.com", + "owner": "flox", + "ref": "aarch64-darwin", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "nixpkgs__flox__aarch64-linux": { + "flake": false, + "locked": { + "host": "catalog.floxsdlc.com", + "lastModified": 1680113660, + "narHash": "sha256-ZofvvoatURsk1p5JvqajdrcO9iIT7UHjV2cb7io4FK0=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "8112f3ce4a227cd5088165d929761d877eea6709", + "type": "github" + }, + "original": { + "host": "catalog.floxsdlc.com", + "owner": "flox", + "ref": "aarch64-linux", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "nixpkgs__flox__i686-linux": { + "flake": false, + "locked": { + "host": "catalog.floxsdlc.com", + "lastModified": 1680113793, + "narHash": "sha256-xbjWq4lOP+K2772K8kDF17+CPoVyalqXYWyoH3x8au8=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "c189975540c856ac025be398761788c118ff5733", + "type": "github" + }, + "original": { + "host": "catalog.floxsdlc.com", + "owner": "flox", + "ref": "i686-linux", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "nixpkgs__flox__x86_64-darwin": { + "flake": false, + "locked": { + "host": "catalog.floxsdlc.com", + "lastModified": 1680113786, + "narHash": "sha256-HBNnTigb0MxCM6j6XmIH/0BRlUp7Rpe1et13TBf7xfM=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "5ab94a52855a10ad1ac0edd7277654bd587faf3e", + "type": "github" + }, + "original": { + "host": "catalog.floxsdlc.com", + "owner": "flox", + "ref": "x86_64-darwin", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "nixpkgs__flox__x86_64-linux": { + "flake": false, + "locked": { + "host": "catalog.floxsdlc.com", + "lastModified": 1680113768, + "narHash": "sha256-YnzWsglWn0TAeg2xQaVg8UFgALVU0TYZ/PdKV32EEtk=", + "owner": "flox", + "repo": "nixpkgs-flox", + "rev": "50ecffffa7c51a92a7a6bb9eb105625ed8b8f18d", + "type": "github" + }, + "original": { + "host": "catalog.floxsdlc.com", + "owner": "flox", + "ref": "x86_64-linux", + "repo": "nixpkgs-flox", + "type": "github" + } + }, + "root": { + "inputs": { + "flox-floxpkgs": "flox-floxpkgs" + } + }, + "shellHooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1678976941, + "narHash": "sha256-skNr08frCwN9NO+7I77MjOHHAw+L410/37JknNld+W4=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "32b1dbedfd77892a6e375737ef04d8efba634e9e", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "tracelinks": { + "inputs": { + "flox-floxpkgs": [ + "flox-floxpkgs" + ] + }, + "locked": { + "lastModified": 1674847293, + "narHash": "sha256-wPirp+8gIUpoAgE8zoXZalAJzCzcdDHKLEPOapJUtfs=", + "ref": "main", + "rev": "46108503f52bc2fcc948abb9b00fc65a13e5f5bd", + "revCount": 9, + "type": "git", + "url": "ssh://git@github.com/flox/tracelinks" + }, + "original": { + "ref": "main", + "type": "git", + "url": "ssh://git@github.com/flox/tracelinks" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..3fd85dbded --- /dev/null +++ b/flake.nix @@ -0,0 +1,7 @@ +{ + description = "A flox project"; + + inputs.flox-floxpkgs.url = "github:flox/floxpkgs"; + + outputs = args @ {flox-floxpkgs, ...}: flox-floxpkgs.project args (_: {}); +} diff --git a/flox.nix b/flox.nix new file mode 100644 index 0000000000..3f82311a7e --- /dev/null +++ b/flox.nix @@ -0,0 +1,3 @@ +{ + packages.nixpkgs-flox.go_1_20 = { }; +} From a671af3b45cb07db8df2fa00fe11a25ae28a76ac Mon Sep 17 00:00:00 2001 From: Rowan Hassan Date: Fri, 31 Mar 2023 14:03:43 +0100 Subject: [PATCH 283/370] FLPROD-688 Add add Operation to rulesets --- rulesets.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rulesets.go b/rulesets.go index e4582e82ac..ac3255250e 100644 --- a/rulesets.go +++ b/rulesets.go @@ -66,6 +66,7 @@ const ( RulesetRuleActionParametersHTTPHeaderOperationRemove RulesetRuleActionParametersHTTPHeaderOperation = "remove" RulesetRuleActionParametersHTTPHeaderOperationSet RulesetRuleActionParametersHTTPHeaderOperation = "set" + RulesetRuleActionParametersHTTPHeaderOperationAdd RulesetRuleActionParametersHTTPHeaderOperation = "add" ) // RulesetKindValues exposes all the available `RulesetKind` values as a slice @@ -149,6 +150,7 @@ func RulesetRuleActionParametersHTTPHeaderOperationValues() []string { return []string{ string(RulesetRuleActionParametersHTTPHeaderOperationRemove), string(RulesetRuleActionParametersHTTPHeaderOperationSet), + string(RulesetRuleActionParametersHTTPHeaderOperationAdd), } } From 1ee8ee9eb44b004f58cc9d427c6ad487b7c3b9f9 Mon Sep 17 00:00:00 2001 From: James Royal Date: Mon, 3 Apr 2023 16:15:34 -0500 Subject: [PATCH 284/370] feat(Access): Add isolation_required flag to access policies --- .changelog/1258.txt | 3 +++ access_policy.go | 1 + access_policy_test.go | 6 ++++++ 3 files changed, 10 insertions(+) create mode 100644 .changelog/1258.txt diff --git a/.changelog/1258.txt b/.changelog/1258.txt new file mode 100644 index 0000000000..09748a6ecf --- /dev/null +++ b/.changelog/1258.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access: Add `isolation_required` flag to Access policies +``` diff --git a/access_policy.go b/access_policy.go index abbbaf42d5..a7823f79fc 100644 --- a/access_policy.go +++ b/access_policy.go @@ -24,6 +24,7 @@ type AccessPolicy struct { UpdatedAt *time.Time `json:"updated_at"` Name string `json:"name"` + IsolationRequired *bool `json:"isolation_required,omitempty"` PurposeJustificationRequired *bool `json:"purpose_justification_required,omitempty"` PurposeJustificationPrompt *string `json:"purpose_justification_prompt,omitempty"` ApprovalRequired *bool `json:"approval_required,omitempty"` diff --git a/access_policy_test.go b/access_policy_test.go index 8184b47f0e..1164b29d44 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -19,6 +19,7 @@ var ( updatedAt, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") expiresAt, _ = time.Parse(time.RFC3339, "2015-01-01T05:20:00.12345Z") + isolationRequired = true purposeJustificationRequired = true purposeJustificationPrompt = "Please provide a business reason for your need to access before continuing." approvalRequired = true @@ -39,6 +40,7 @@ var ( Require: []interface{}{ map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, }, + IsolationRequired: &isolationRequired, PurposeJustificationRequired: &purposeJustificationRequired, ApprovalRequired: &approvalRequired, PurposeJustificationPrompt: &purposeJustificationPrompt, @@ -95,6 +97,7 @@ func TestAccessPolicies(t *testing.T) { } } ], + "isolation_required": true, "purpose_justification_required": true, "purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.", "approval_required": true, @@ -176,6 +179,7 @@ func TestAccessPolicy(t *testing.T) { } } ], + "isolation_required": true, "purpose_justification_required": true, "purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.", "approval_required": true, @@ -250,6 +254,7 @@ func TestCreateAccessPolicy(t *testing.T) { } } ], + "isolation_required": true, "purpose_justification_required": true, "purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.", "approval_required": true, @@ -356,6 +361,7 @@ func TestUpdateAccessPolicy(t *testing.T) { } } ], + "isolation_required": true, "purpose_justification_required": true, "purpose_justification_prompt": "Please provide a business reason for your need to access before continuing.", "approval_required": true, From e3e8fd70afc96d8188154886f0180372a9aa3a0a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 3 Apr 2023 23:26:59 +0000 Subject: [PATCH 285/370] Update CHANGELOG.md for #1258 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1d781302b..331de67974 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.65.0 (Unreleased) +ENHANCEMENTS: + +* access: Add `isolation_required` flag to Access policies ([#1258](https://github.com/cloudflare/cloudflare-go/issues/1258)) + ## 0.64.0 (29th March, 2023) BREAKING CHANGES: From cc3d1c8dd233cc3e3336dbf5cd42b1fdcd762d43 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 4 Apr 2023 09:32:20 +1000 Subject: [PATCH 286/370] add changelog entry --- .changelog/1253.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1253.txt diff --git a/.changelog/1253.txt b/.changelog/1253.txt new file mode 100644 index 0000000000..a43f5d8cb7 --- /dev/null +++ b/.changelog/1253.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +rulesets: add support for add operation to HTTP header configuration +``` From 93d8999c1ab3a9a176996744c269e6d57946a7a7 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 3 Apr 2023 23:52:15 +0000 Subject: [PATCH 287/370] Update CHANGELOG.md for #1253 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 331de67974..2ac6b20f4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * access: Add `isolation_required` flag to Access policies ([#1258](https://github.com/cloudflare/cloudflare-go/issues/1258)) +* rulesets: add support for add operation to HTTP header configuration ([#1253](https://github.com/cloudflare/cloudflare-go/issues/1253)) ## 0.64.0 (29th March, 2023) From fdde842d1eab348fe9616e61b737a43fe0ecaae9 Mon Sep 17 00:00:00 2001 From: Eduardo Gomes Date: Wed, 5 Apr 2023 12:06:21 +0100 Subject: [PATCH 288/370] Add flag to Access organizations --- .changelog/1260.txt | 3 +++ access_organization.go | 1 + access_organization_test.go | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 .changelog/1260.txt diff --git a/.changelog/1260.txt b/.changelog/1260.txt new file mode 100644 index 0000000000..806345d464 --- /dev/null +++ b/.changelog/1260.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +access: Add `auto_redirect_to_identity` flag to Access organizations +``` diff --git a/access_organization.go b/access_organization.go index f4de4a7b68..ff2fef9ded 100644 --- a/access_organization.go +++ b/access_organization.go @@ -18,6 +18,7 @@ type AccessOrganization struct { IsUIReadOnly *bool `json:"is_ui_read_only,omitempty"` UIReadOnlyToggleReason string `json:"ui_read_only_toggle_reason,omitempty"` UserSeatExpirationInactiveTime string `json:"user_seat_expiration_inactive_time,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` } // AccessOrganizationLoginDesign represents the login design options. diff --git a/access_organization_test.go b/access_organization_test.go index 7d6cfa60e3..3ea79970a4 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -28,6 +28,7 @@ func TestAccessOrganization(t *testing.T) { "auth_domain": "test.cloudflareaccess.com", "is_ui_read_only": false, "user_seat_expiration_inactive_time": "720h", + "auto_redirect_to_identity": true, "login_design": { "background_color": "#c5ed1b", "logo_path": "https://example.com/logo.png", @@ -57,6 +58,7 @@ func TestAccessOrganization(t *testing.T) { }, IsUIReadOnly: BoolPtr(false), UserSeatExpirationInactiveTime: "720h", + AutoRedirectToIdentity: BoolPtr(true), } mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) From c19c80d3c9819dfb037cee8a4ae965729187407b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 6 Apr 2023 04:02:30 +0000 Subject: [PATCH 289/370] Update CHANGELOG.md for #1260 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac6b20f4f..836204323a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* access: Add `auto_redirect_to_identity` flag to Access organizations ([#1260](https://github.com/cloudflare/cloudflare-go/issues/1260)) * access: Add `isolation_required` flag to Access policies ([#1258](https://github.com/cloudflare/cloudflare-go/issues/1258)) * rulesets: add support for add operation to HTTP header configuration ([#1253](https://github.com/cloudflare/cloudflare-go/issues/1253)) From 26fe2843e8a1201f2dc0d2ec3ce0edc8726d353f Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Wed, 5 Apr 2023 17:21:20 +0100 Subject: [PATCH 290/370] Added support for `http_response_compress` phase and `compress_response` action. --- .changelog/1261.txt | 7 +++ rulesets.go | 105 ++++++++++++++++++++++++-------------------- rulesets_test.go | 80 +++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 47 deletions(-) create mode 100644 .changelog/1261.txt diff --git a/.changelog/1261.txt b/.changelog/1261.txt new file mode 100644 index 0000000000..efa0a01bad --- /dev/null +++ b/.changelog/1261.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +rulesets: add support for the `http_response_compression` phase +``` + +```release-note:enhancement +rulesets: add support for the `compress_response` action +``` diff --git a/rulesets.go b/rulesets.go index 29aa2dfd60..8110d0206a 100644 --- a/rulesets.go +++ b/rulesets.go @@ -35,6 +35,7 @@ const ( RulesetPhaseHTTPResponseFirewallManaged RulesetPhase = "http_response_firewall_managed" RulesetPhaseHTTPResponseHeadersTransform RulesetPhase = "http_response_headers_transform" RulesetPhaseHTTPResponseHeadersTransformManaged RulesetPhase = "http_response_headers_transform_managed" + RulesetPhaseHTTPResponseCompression RulesetPhase = "http_response_compression" RulesetPhaseMagicTransit RulesetPhase = "magic_transit" RulesetPhaseRateLimit RulesetPhase = "http_ratelimit" RulesetPhaseSuperBotFightMode RulesetPhase = "http_request_sbfm" @@ -58,6 +59,7 @@ const ( RulesetRuleActionSetConfig RulesetRuleAction = "set_config" RulesetRuleActionServeError RulesetRuleAction = "serve_error" RulesetRuleActionSkip RulesetRuleAction = "skip" + RulesetRuleActionCompressResponse RulesetRuleAction = "compress_response" RulesetActionParameterProductBIC RulesetActionParameterProduct = "bic" RulesetActionParameterProductHOT RulesetActionParameterProduct = "hot" @@ -106,6 +108,7 @@ func RulesetPhaseValues() []string { string(RulesetPhaseHTTPResponseFirewallManaged), string(RulesetPhaseHTTPResponseHeadersTransform), string(RulesetPhaseHTTPResponseHeadersTransformManaged), + string(RulesetPhaseHTTPResponseCompression), string(RulesetPhaseMagicTransit), string(RulesetPhaseRateLimit), string(RulesetPhaseSuperBotFightMode), @@ -135,6 +138,7 @@ func RulesetRuleActionValues() []string { string(RulesetRuleActionSetConfig), string(RulesetRuleActionServeError), string(RulesetRuleActionSkip), + string(RulesetRuleActionCompressResponse), } } @@ -205,53 +209,54 @@ type RulesetActionParametersLogCustomField struct { // RulesetRuleActionParameters specifies the action parameters for a Ruleset // rule. type RulesetRuleActionParameters struct { - ID string `json:"id,omitempty"` - Ruleset string `json:"ruleset,omitempty"` - Rulesets []string `json:"rulesets,omitempty"` - Rules map[string][]string `json:"rules,omitempty"` - Increment int `json:"increment,omitempty"` - URI *RulesetRuleActionParametersURI `json:"uri,omitempty"` - Headers map[string]RulesetRuleActionParametersHTTPHeader `json:"headers,omitempty"` - Products []string `json:"products,omitempty"` - Phases []string `json:"phases,omitempty"` - Overrides *RulesetRuleActionParametersOverrides `json:"overrides,omitempty"` - MatchedData *RulesetRuleActionParametersMatchedData `json:"matched_data,omitempty"` - Version *string `json:"version,omitempty"` - Response *RulesetRuleActionParametersBlockResponse `json:"response,omitempty"` - HostHeader string `json:"host_header,omitempty"` - Origin *RulesetRuleActionParametersOrigin `json:"origin,omitempty"` - SNI *RulesetRuleActionParametersSni `json:"sni,omitempty"` - RequestFields []RulesetActionParametersLogCustomField `json:"request_fields,omitempty"` - ResponseFields []RulesetActionParametersLogCustomField `json:"response_fields,omitempty"` - CookieFields []RulesetActionParametersLogCustomField `json:"cookie_fields,omitempty"` - Cache *bool `json:"cache,omitempty"` - EdgeTTL *RulesetRuleActionParametersEdgeTTL `json:"edge_ttl,omitempty"` - BrowserTTL *RulesetRuleActionParametersBrowserTTL `json:"browser_ttl,omitempty"` - ServeStale *RulesetRuleActionParametersServeStale `json:"serve_stale,omitempty"` - Content string `json:"content,omitempty"` - ContentType string `json:"content_type,omitempty"` - StatusCode uint16 `json:"status_code,omitempty"` - RespectStrongETags *bool `json:"respect_strong_etags,omitempty"` - CacheKey *RulesetRuleActionParametersCacheKey `json:"cache_key,omitempty"` - OriginErrorPagePassthru *bool `json:"origin_error_page_passthru,omitempty"` - FromList *RulesetRuleActionParametersFromList `json:"from_list,omitempty"` - FromValue *RulesetRuleActionParametersFromValue `json:"from_value,omitempty"` - AutomaticHTTPSRewrites *bool `json:"automatic_https_rewrites,omitempty"` - AutoMinify *RulesetRuleActionParametersAutoMinify `json:"autominify,omitempty"` - BrowserIntegrityCheck *bool `json:"bic,omitempty"` - DisableApps *bool `json:"disable_apps,omitempty"` - DisableZaraz *bool `json:"disable_zaraz,omitempty"` - DisableRailgun *bool `json:"disable_railgun,omitempty"` - EmailObfuscation *bool `json:"email_obfuscation,omitempty"` - Mirage *bool `json:"mirage,omitempty"` - OpportunisticEncryption *bool `json:"opportunistic_encryption,omitempty"` - Polish *Polish `json:"polish,omitempty"` - RocketLoader *bool `json:"rocket_loader,omitempty"` - SecurityLevel *SecurityLevel `json:"security_level,omitempty"` - ServerSideExcludes *bool `json:"server_side_excludes,omitempty"` - SSL *SSL `json:"ssl,omitempty"` - SXG *bool `json:"sxg,omitempty"` - HotLinkProtection *bool `json:"hotlink_protection,omitempty"` + ID string `json:"id,omitempty"` + Ruleset string `json:"ruleset,omitempty"` + Rulesets []string `json:"rulesets,omitempty"` + Rules map[string][]string `json:"rules,omitempty"` + Increment int `json:"increment,omitempty"` + URI *RulesetRuleActionParametersURI `json:"uri,omitempty"` + Headers map[string]RulesetRuleActionParametersHTTPHeader `json:"headers,omitempty"` + Products []string `json:"products,omitempty"` + Phases []string `json:"phases,omitempty"` + Overrides *RulesetRuleActionParametersOverrides `json:"overrides,omitempty"` + MatchedData *RulesetRuleActionParametersMatchedData `json:"matched_data,omitempty"` + Version *string `json:"version,omitempty"` + Response *RulesetRuleActionParametersBlockResponse `json:"response,omitempty"` + HostHeader string `json:"host_header,omitempty"` + Origin *RulesetRuleActionParametersOrigin `json:"origin,omitempty"` + SNI *RulesetRuleActionParametersSni `json:"sni,omitempty"` + RequestFields []RulesetActionParametersLogCustomField `json:"request_fields,omitempty"` + ResponseFields []RulesetActionParametersLogCustomField `json:"response_fields,omitempty"` + CookieFields []RulesetActionParametersLogCustomField `json:"cookie_fields,omitempty"` + Cache *bool `json:"cache,omitempty"` + EdgeTTL *RulesetRuleActionParametersEdgeTTL `json:"edge_ttl,omitempty"` + BrowserTTL *RulesetRuleActionParametersBrowserTTL `json:"browser_ttl,omitempty"` + ServeStale *RulesetRuleActionParametersServeStale `json:"serve_stale,omitempty"` + Content string `json:"content,omitempty"` + ContentType string `json:"content_type,omitempty"` + StatusCode uint16 `json:"status_code,omitempty"` + RespectStrongETags *bool `json:"respect_strong_etags,omitempty"` + CacheKey *RulesetRuleActionParametersCacheKey `json:"cache_key,omitempty"` + OriginErrorPagePassthru *bool `json:"origin_error_page_passthru,omitempty"` + FromList *RulesetRuleActionParametersFromList `json:"from_list,omitempty"` + FromValue *RulesetRuleActionParametersFromValue `json:"from_value,omitempty"` + AutomaticHTTPSRewrites *bool `json:"automatic_https_rewrites,omitempty"` + AutoMinify *RulesetRuleActionParametersAutoMinify `json:"autominify,omitempty"` + BrowserIntegrityCheck *bool `json:"bic,omitempty"` + DisableApps *bool `json:"disable_apps,omitempty"` + DisableZaraz *bool `json:"disable_zaraz,omitempty"` + DisableRailgun *bool `json:"disable_railgun,omitempty"` + EmailObfuscation *bool `json:"email_obfuscation,omitempty"` + Mirage *bool `json:"mirage,omitempty"` + OpportunisticEncryption *bool `json:"opportunistic_encryption,omitempty"` + Polish *Polish `json:"polish,omitempty"` + RocketLoader *bool `json:"rocket_loader,omitempty"` + SecurityLevel *SecurityLevel `json:"security_level,omitempty"` + ServerSideExcludes *bool `json:"server_side_excludes,omitempty"` + SSL *SSL `json:"ssl,omitempty"` + SXG *bool `json:"sxg,omitempty"` + HotLinkProtection *bool `json:"hotlink_protection,omitempty"` + Algorithms []RulesetRuleActionParametersCompressionAlgorithm `json:"algorithms,omitempty"` } // RulesetRuleActionParametersFromList holds the FromList struct for @@ -451,6 +456,12 @@ type RulesetRuleActionParametersSni struct { Value string `json:"value"` } +// RulesetRuleActionParametersCompressionAlgorithm defines a compression +// algorithm for the compress_response action. +type RulesetRuleActionParametersCompressionAlgorithm struct { + Name string `json:"name"` +} + type Polish int const ( diff --git a/rulesets_test.go b/rulesets_test.go index 32a0774c72..c126c72394 100644 --- a/rulesets_test.go +++ b/rulesets_test.go @@ -554,6 +554,86 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { } } +func TestGetRuleset_CompressResponse(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.Fprint(w, `{ + "result": { + "id": "70339d97bdb34195bbf054b1ebe81f76", + "name": "Cloudflare compress response ruleset", + "description": "This ruleset provides response compression rules", + "kind": "zone", + "version": "1", + "rules": [ + { + "id": "78723a9e0c7c4c6dbec5684cb766231d", + "version": "1", + "action": "compress_response", + "action_parameters": { + "algorithms": [ { "name": "brotli" }, { "name": "default" } ] + }, + "description": "Compress response rule", + "last_updated": "2020-12-18T09:28:09.655749Z", + "ref": "272936dc447b41fe976255ff6b768ec0", + "enabled": true + } + ], + "last_updated": "2020-12-18T09:28:09.655749Z", + "phase": "http_response_compression" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rulesets/b232b534beea4e00a21dcbb7a8a545e9", handler) + mux.HandleFunc("/zones/"+testZoneID+"/rulesets/b232b534beea4e00a21dcbb7a8a545e9", handler) + + lastUpdated, _ := time.Parse(time.RFC3339, "2020-12-18T09:28:09.655749Z") + + rules := []RulesetRule{{ + ID: "78723a9e0c7c4c6dbec5684cb766231d", + Version: StringPtr("1"), + Action: string(RulesetRuleActionCompressResponse), + ActionParameters: &RulesetRuleActionParameters{ + Algorithms: []RulesetRuleActionParametersCompressionAlgorithm{ + {Name: "brotli"}, + {Name: "default"}, + }, + }, + Description: "Compress response rule", + LastUpdated: &lastUpdated, + Ref: "272936dc447b41fe976255ff6b768ec0", + Enabled: BoolPtr(true), + }} + + want := Ruleset{ + ID: "70339d97bdb34195bbf054b1ebe81f76", + Name: "Cloudflare compress response ruleset", + Description: "This ruleset provides response compression rules", + Kind: string(RulesetKindZone), + Version: StringPtr("1"), + LastUpdated: &lastUpdated, + Phase: string(RulesetPhaseHTTPResponseCompression), + Rules: rules, + } + + zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + if assert.NoError(t, err) { + assert.Equal(t, want, zoneActual) + } + + accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + if assert.NoError(t, err) { + assert.Equal(t, want, accountActual) + } +} + func TestCreateRuleset(t *testing.T) { setup() defer teardown() From 0ec93104e3ed0296e13b4b083a220aff8decab58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 16:56:41 +0000 Subject: [PATCH 291/370] build(deps): bump golang.org/x/net from 0.8.0 to 0.9.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 6621944699..1d9563fd56 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( 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.8.0 + golang.org/x/net v0.9.0 golang.org/x/time v0.3.0 ) @@ -30,6 +30,6 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1056aff36b..73c95cbd5d 100644 --- a/go.sum +++ b/go.sum @@ -63,17 +63,17 @@ 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/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.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +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/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.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +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= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 9ea2aeb4459d7b657f6ca7e689a2f682d16eb252 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Apr 2023 16:56:57 +0000 Subject: [PATCH 292/370] add CHANGELOG for #1263 --- .changelog/1263.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1263.txt diff --git a/.changelog/1263.txt b/.changelog/1263.txt new file mode 100644 index 0000000000..785f7c0c13 --- /dev/null +++ b/.changelog/1263.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.8.0 to 0.9.0 +``` From 888a69f23b9646b93f23897b7ca7c160e7a2f926 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 6 Apr 2023 19:50:48 +0000 Subject: [PATCH 293/370] Update CHANGELOG.md for #1263 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 836204323a..a3a93e2789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ ENHANCEMENTS: * access: Add `isolation_required` flag to Access policies ([#1258](https://github.com/cloudflare/cloudflare-go/issues/1258)) * rulesets: add support for add operation to HTTP header configuration ([#1253](https://github.com/cloudflare/cloudflare-go/issues/1253)) +DEPENDENCIES: + +* deps: bumps golang.org/x/net from 0.8.0 to 0.9.0 ([#1263](https://github.com/cloudflare/cloudflare-go/issues/1263)) + ## 0.64.0 (29th March, 2023) BREAKING CHANGES: From b68ae74e01f731322a91627a2500e474d97c62f0 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 6 Apr 2023 22:46:54 +0000 Subject: [PATCH 294/370] Update CHANGELOG.md for #1261 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3a93e2789..5e593a8f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ENHANCEMENTS: * access: Add `auto_redirect_to_identity` flag to Access organizations ([#1260](https://github.com/cloudflare/cloudflare-go/issues/1260)) * access: Add `isolation_required` flag to Access policies ([#1258](https://github.com/cloudflare/cloudflare-go/issues/1258)) * rulesets: add support for add operation to HTTP header configuration ([#1253](https://github.com/cloudflare/cloudflare-go/issues/1253)) +* rulesets: add support for the `compress_response` action ([#1261](https://github.com/cloudflare/cloudflare-go/issues/1261)) +* rulesets: add support for the `http_response_compression` phase ([#1261](https://github.com/cloudflare/cloudflare-go/issues/1261)) DEPENDENCIES: From 749fafdc2f571835ab8f014c7fe7a343094065fb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Apr 2023 06:16:41 +1000 Subject: [PATCH 295/370] Update release-process.md --- docs/release-process.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/release-process.md b/docs/release-process.md index 181b92c23d..d2ae372d8d 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -2,9 +2,14 @@ We aim to release on a fortnightly cadence, alternating weeks with the [terraform-provider-cloudflare](https://github.com/cloudflare/terraform-provider-cloudflare). -This is to accommodate downstream tools and allow cahnges from this library to +This is to accommodate downstream tools and allow changes from this library to be used in the other systems without a month long delay. +To determine when the next release is due, you can either: + +- Review the latest [releases](https://github.com/cloudflare/cloudflare-go/releases); or +- Review the [current milestones](https://github.com/cloudflare/cloudflare-go/milestones). + If a hotfix is needed, the same process outlined below is used however only the semantic versioning patch version is bumped. From 93b000a9c77a8fa820c836c083432977ac4af117 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Apr 2023 14:04:40 +1000 Subject: [PATCH 296/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e593a8f16..892d27d469 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.65.0 (Unreleased) +## 0.66.0 (Unreleased) + +## 0.65.0 (12th April, 2023) ENHANCEMENTS: From 901f9bfa08ba177772a1423a18109cd979cfba76 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Apr 2023 14:06:32 +1000 Subject: [PATCH 297/370] Update milestone-closed.yml --- .github/workflows/milestone-closed.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/milestone-closed.yml b/.github/workflows/milestone-closed.yml index 99e768a9c5..112a514d72 100644 --- a/.github/workflows/milestone-closed.yml +++ b/.github/workflows/milestone-closed.yml @@ -32,4 +32,4 @@ jobs: done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUES: ${{ jobs.comment-on-closed-milestone.outputs.ids }} + ISSUES: ${{ needs.comment-on-closed-milestone.outputs.ids }} From e6bb99e2eb4fedd59877b83b32bfdc41c9607b4e Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Wed, 12 Apr 2023 22:25:38 -0400 Subject: [PATCH 298/370] Add GetR2Bucket --- .changelog/1265.txt | 7 +++++++ r2_bucket.go | 46 +++++++++++++++++++++++++++++++++++++------ r2_bucket_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 .changelog/1265.txt diff --git a/.changelog/1265.txt b/.changelog/1265.txt new file mode 100644 index 0000000000..f93fc420a6 --- /dev/null +++ b/.changelog/1265.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +r2_bucket: add support for getting a bucket +``` + +```release-note:breaking-change +r2_bucket: change creation time from string to *time.Time +``` diff --git a/r2_bucket.go b/r2_bucket.go index 08de630e1c..129617dab6 100644 --- a/r2_bucket.go +++ b/r2_bucket.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net/http" + "time" ) var ( @@ -14,8 +15,9 @@ var ( // R2Bucket defines a container for objects stored in R2 Storage. type R2Bucket struct { - Name string `json:"name"` - CreationDate string `json:"creation_date,omitempty"` + Name string `json:"name"` + CreationDate *time.Time `json:"creation_date,omitempty"` + Location string `json:"location,omitempty"` } // R2Buckets represents the map of buckets response from @@ -40,6 +42,15 @@ type ListR2BucketsParams struct { Cursor string `url:"cursor,omitempty"` } +type CreateR2BucketParameters struct { + Name string `json:"name,omitempty"` +} + +type R2BucketResponse struct { + Result R2Bucket `json:"result"` + Response +} + // ListR2Buckets Lists R2 buckets. func (api *API) ListR2Buckets(ctx context.Context, rc *ResourceContainer, params ListR2BucketsParams) ([]R2Bucket, error) { if rc.Identifier == "" { @@ -61,10 +72,6 @@ func (api *API) ListR2Buckets(ctx context.Context, rc *ResourceContainer, params return r2BucketListResponse.Result.Buckets, nil } -type CreateR2BucketParameters struct { - Name string `json:"name,omitempty"` -} - // CreateR2Bucket Creates a new R2 bucket. // // API reference: https://api.cloudflare.com/#r2-bucket-create-bucket @@ -83,6 +90,33 @@ func (api *API) CreateR2Bucket(ctx context.Context, rc *ResourceContainer, param return err } +// GetR2Bucket Gets an existing R2 bucket. +// +// API reference: https://api.cloudflare.com/#r2-bucket-get-bucket +func (api *API) GetR2Bucket(ctx context.Context, rc *ResourceContainer, bucketName string) (R2Bucket, error) { + if rc.Identifier == "" { + return R2Bucket{}, ErrMissingAccountID + } + + if bucketName == "" { + return R2Bucket{}, ErrMissingBucketName + } + + uri := fmt.Sprintf("/accounts/%s/r2/buckets/%s", rc.Identifier, bucketName) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return R2Bucket{}, err + } + + var r2BucketResponse R2BucketResponse + err = json.Unmarshal(res, &r2BucketResponse) + if err != nil { + return R2Bucket{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return r2BucketResponse.Result, nil +} + // DeleteR2Bucket Deletes an existing R2 bucket. // // API reference: https://api.cloudflare.com/#r2-bucket-delete-bucket diff --git a/r2_bucket_test.go b/r2_bucket_test.go index 42168838c8..33f538225e 100644 --- a/r2_bucket_test.go +++ b/r2_bucket_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -32,11 +33,11 @@ func TestR2_ListBuckets(t *testing.T) { } }`) }) - + createDate, _ := time.Parse(time.RFC3339, "2022-06-24T19:58:49.477Z") want := []R2Bucket{ { Name: "example-bucket", - CreationDate: "2022-06-24T19:58:49.477Z", + CreationDate: &createDate, }, } actual, err := client.ListR2Buckets(context.Background(), AccountIdentifier(testAccountID), ListR2BucketsParams{}) @@ -45,6 +46,49 @@ func TestR2_ListBuckets(t *testing.T) { } } +func TestR2_GetBucket(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/accounts/%s/r2/buckets/%s", testAccountID, testBucketName), 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": { + "name": "example-bucket", + "creation_date": "2022-06-24T19:58:49.477Z", + "location": "ENAM" + } +}`) + }) + + _, err := client.GetR2Bucket(context.Background(), AccountIdentifier(""), "") + if assert.Error(t, err) { + assert.Equal(t, ErrMissingAccountID, err) + } + + _, err = client.GetR2Bucket(context.Background(), AccountIdentifier(testAccountID), "") + + if assert.Error(t, err) { + assert.Equal(t, ErrMissingBucketName, err) + } + + createDate, _ := time.Parse(time.RFC3339, "2022-06-24T19:58:49.477Z") + want := R2Bucket{ + Name: testBucketName, + CreationDate: &createDate, + Location: "ENAM", + } + + actual, err := client.GetR2Bucket(context.Background(), AccountIdentifier(testAccountID), testBucketName) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestR2_CreateBucket(t *testing.T) { setup() defer teardown() From 40c221a5a94ebf207502bf48d9021ea390651000 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 14 Apr 2023 14:41:07 +1000 Subject: [PATCH 299/370] dns: add support for importing and exporting DNS records using BIND file configurations Updates our DNS API coverage for importing and exporting via BIND file formats. --- .changelog/1266.txt | 3 + dns.go | 146 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 .changelog/1266.txt diff --git a/.changelog/1266.txt b/.changelog/1266.txt new file mode 100644 index 0000000000..749e3b8c8a --- /dev/null +++ b/.changelog/1266.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +dns: add support for importing and exporting DNS records using BIND file configurations +``` diff --git a/dns.go b/dns.go index afc47b66bd..7e2ddb7c55 100644 --- a/dns.go +++ b/dns.go @@ -1,16 +1,22 @@ package cloudflare import ( + "bytes" "context" "encoding/json" "errors" "fmt" "net/http" + "regexp" + "strings" "time" "golang.org/x/net/idna" ) +// ErrMissingBINDContents is for when the BIND file contents is required but not set. +var ErrMissingBINDContents = errors.New("required BIND config contents missing") + // DNSRecord represents a DNS record in a zone. type DNSRecord struct { CreatedOn time.Time `json:"created_on,omitempty"` @@ -104,6 +110,73 @@ func toUTS46ASCII(name string) string { return name } +// proxiedRecordsRe is the regular expression for determining if a DNS record +// is proxied or not. +var proxiedRecordsRe = regexp.MustCompile(`(?m)^.*\.\s+1\s+IN\s+CNAME.*$`) + +// proxiedRecordImportTemplate is the multipart template for importing *only* +// proxied records. See `nonProxiedRecordImportTemplate` for importing records +// that are not proxied. +var proxiedRecordImportTemplate = `--------------------------BOUNDARY +Content-Disposition: form-data; name="file"; filename="bind.txt" + +%s +--------------------------BOUNDARY +Content-Disposition: form-data; name="proxied" + +true +--------------------------BOUNDARY--` + +// nonProxiedRecordImportTemplate is the multipart template for importing DNS +// records that are not proxed. For importing proxied records, use +// `proxiedRecordImportTemplate`. +var nonProxiedRecordImportTemplate = `--------------------------BOUNDARY +Content-Disposition: form-data; name="file"; filename="bind.txt" + +%s +--------------------------BOUNDARY--` + +// sanitiseBINDFileInput accepts the BIND file as a string and removes parts +// that are not required for importing or would break the import (like SOA +// records). +func sanitiseBINDFileInput(s string) string { + // Remove SOA records. + soaRe := regexp.MustCompile(`(?m)[\r\n]+^.*IN\s+SOA.*$`) + s = soaRe.ReplaceAllString(s, "") + + // Remove all comments. + commentRe := regexp.MustCompile(`(?m)[\r\n]+^.*;;.*$`) + s = commentRe.ReplaceAllString(s, "") + + // Swap all the tabs to spaces. + r := strings.NewReplacer( + "\t", " ", + "\n\n", "\n", + ) + s = r.Replace(s) + s = strings.TrimSpace(s) + + return s +} + +// extractProxiedRecords accepts a BIND file (as a string) and returns only the +// proxied DNS records. +func extractProxiedRecords(s string) string { + proxiedOnlyRecords := proxiedRecordsRe.FindAllString(s, -1) + return strings.Join(proxiedOnlyRecords, "\n") +} + +// removeProxiedRecords accepts a BIND file (as a string) and returns the file +// contents without any proxied records included. +func removeProxiedRecords(s string) string { + return proxiedRecordsRe.ReplaceAllString(s, "") +} + +type ExportDNSRecordsParams struct{} +type ImportDNSRecordsParams struct { + BINDContents string +} + type CreateDNSRecordParams struct { CreatedOn time.Time `json:"created_on,omitempty" url:"created_on,omitempty"` ModifiedOn time.Time `json:"modified_on,omitempty" url:"modified_on,omitempty"` @@ -277,3 +350,76 @@ func (api *API) DeleteDNSRecord(ctx context.Context, rc *ResourceContainer, reco } return nil } + +// ExportDNSRecords returns all DNS records for a zone in the BIND format. +// +// API reference: https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-export-dns-records +func (api *API) ExportDNSRecords(ctx context.Context, rc *ResourceContainer, params ExportDNSRecordsParams) (string, error) { + if rc.Level != ZoneRouteLevel { + return "", ErrRequiredZoneLevelResourceContainer + } + + if rc.Identifier == "" { + return "", ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/dns_records/export", rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return "", err + } + + return string(res), nil +} + +// ImportDNSRecords takes the contents of a BIND configuration file and imports +// all records at once. +// +// The current state of the API doesn't allow the proxying field to be +// automatically set on records where the TTL is 1. Instead you need to +// explicitly tell the endpoint which records are proxied in the form data. To +// achieve a simpler abstraction, we do the legwork in the method of making the +// two separate API calls (one for proxied and one for non-proxied) instead of +// making the end user know about this detail. +// +// API reference: https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-import-dns-records +func (api *API) ImportDNSRecords(ctx context.Context, rc *ResourceContainer, params ImportDNSRecordsParams) error { + if rc.Level != ZoneRouteLevel { + return ErrRequiredZoneLevelResourceContainer + } + + if rc.Identifier == "" { + return ErrMissingZoneID + } + + if params.BINDContents == "" { + return ErrMissingBINDContents + } + + sanitisedBindData := sanitiseBINDFileInput(params.BINDContents) + nonProxiedRecords := removeProxiedRecords(sanitisedBindData) + proxiedOnlyRecords := extractProxiedRecords(sanitisedBindData) + + nonProxiedRecordPayload := []byte(fmt.Sprintf(nonProxiedRecordImportTemplate, nonProxiedRecords)) + nonProxiedReqBody := bytes.NewReader(nonProxiedRecordPayload) + + uri := fmt.Sprintf("/zones/%s/dns_records/import", rc.Identifier) + multipartUploadHeaders := http.Header{ + "Content-Type": {"multipart/form-data; boundary=------------------------BOUNDARY"}, + } + + _, err := api.makeRequestContextWithHeaders(ctx, http.MethodPost, uri, nonProxiedReqBody, multipartUploadHeaders) + if err != nil { + return err + } + + proxiedRecordPayload := []byte(fmt.Sprintf(proxiedRecordImportTemplate, proxiedOnlyRecords)) + proxiedReqBody := bytes.NewReader(proxiedRecordPayload) + + _, err = api.makeRequestContextWithHeaders(ctx, http.MethodPost, uri, proxiedReqBody, multipartUploadHeaders) + if err != nil { + return err + } + + return nil +} From a3fb2ecd25553f96348bdd44f02e57f7345c0ef2 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 14 Apr 2023 05:02:04 +0000 Subject: [PATCH 300/370] Update CHANGELOG.md for #1266 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 892d27d469..54d6e080bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.66.0 (Unreleased) +ENHANCEMENTS: + +* dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266)) + ## 0.65.0 (12th April, 2023) ENHANCEMENTS: From ddd2cd0d06f4b428b2cd881e8cf76007e220f347 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 14 Apr 2023 17:08:12 -0400 Subject: [PATCH 301/370] Add support for turnstile --- .changelog/1267.txt | 3 +++ .changelog/XXXX.txt | 3 --- challenge_widgets.go | 15 ++++++++------- challenge_widgets_test.go | 26 +++++++++++++++++--------- 4 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 .changelog/1267.txt delete mode 100644 .changelog/XXXX.txt diff --git a/.changelog/1267.txt b/.changelog/1267.txt new file mode 100644 index 0000000000..491b402991 --- /dev/null +++ b/.changelog/1267.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +challenge_widget: add support for turnstile +``` diff --git a/.changelog/XXXX.txt b/.changelog/XXXX.txt deleted file mode 100644 index 24d83ff734..0000000000 --- a/.changelog/XXXX.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:enhancement -challenge_widget: add support for the challenge widget API -``` diff --git a/challenge_widgets.go b/challenge_widgets.go index 77978618fc..a9e9534f2f 100644 --- a/challenge_widgets.go +++ b/challenge_widgets.go @@ -12,13 +12,14 @@ import ( var ErrMissingSiteKey = errors.New("required site key missing") type ChallengeWidget struct { - SiteKey string `json:"sitekey,omitempty"` - Secret string `json:"secret,omitempty"` - CreatedOn *time.Time `json:"created_on,omitempty"` - ModifiedOn *time.Time `json:"modified_on,omitempty"` - Name string `json:"name"` - Domains []string `json:"domains"` - Type string `json:"type"` + SiteKey string `json:"sitekey,omitempty"` + Secret string `json:"secret,omitempty"` + CreatedOn *time.Time `json:"created_on,omitempty"` + ModifiedOn *time.Time `json:"modified_on,omitempty"` + Name string `json:"name,omitempty"` + Domains []string `json:"domains,omitempty"` + Type string `json:"type,omitempty"` + BotFightMode bool `json:"bot_fight_mode,omitempty"` } type ChallengeWidgetResponse struct { diff --git a/challenge_widgets_test.go b/challenge_widgets_test.go index 30150995e3..4c9563b770 100644 --- a/challenge_widgets_test.go +++ b/challenge_widgets_test.go @@ -26,7 +26,8 @@ var ( "cloudflare.com", "blog.example.com", }, - Type: "invisible", + Type: "invisible", + BotFightMode: true, } ) @@ -53,7 +54,8 @@ func TestChallengeWidgets_Create(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } }`) }) @@ -65,8 +67,9 @@ func TestChallengeWidgets_Create(t *testing.T) { } out, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{ - Name: "blog.cloudflare.com login form", - Type: "invisible", + Name: "blog.cloudflare.com login form", + Type: "invisible", + BotFightMode: true, Domains: []string{ "203.0.113.1", "cloudflare.com", @@ -102,7 +105,8 @@ func TestChallengeWidgets_List(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } ], "result_info": { @@ -150,7 +154,8 @@ func TestChallengeWidgets_Get(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } }`) }) @@ -195,7 +200,8 @@ func TestChallengeWidgets_Update(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } }`) }) @@ -241,7 +247,8 @@ func TestChallengeWidgets_RotateSecret(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } }`) }) @@ -286,7 +293,8 @@ func TestChallengeWidgets_Delete(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible" + "type": "invisible", + "bot_fight_mode": true } }`) }) From 74bff0f895cf411577e84a6a997f939bd91a33bf Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sat, 15 Apr 2023 11:16:56 -0400 Subject: [PATCH 302/370] Undo changes to internal/tools --- internal/tools/go.mod | 2 +- internal/tools/tools.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 8b9cdcf6c3..eb343b7063 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -8,7 +8,7 @@ require ( github.com/curioswitch/go-reassign v0.2.0 github.com/cweill/gotests v1.6.0 github.com/go-delve/delve v1.9.0 - github.com/golangci/golangci-lint v1.50.1 + github.com/golangci/golangci-lint v1.48.0 github.com/google/go-github v17.0.0+incompatible github.com/hashicorp/go-changelog v0.0.0-20220419201213-5edfc0d651d8 github.com/jgautheron/goconst v1.5.1 diff --git a/internal/tools/tools.go b/internal/tools/tools.go index 4a0baee4de..336d01f4f9 100644 --- a/internal/tools/tools.go +++ b/internal/tools/tools.go @@ -19,7 +19,6 @@ package tools //go:generate go install golang.org/x/lint/golint //go:generate go install golang.org/x/oauth2 //go:generate go install golang.org/x/tools/gopls@latest -//go:generate go install golang.org/x/tools/cmd/goimports@latest import ( // local development tooling for linting and debugging. @@ -36,7 +35,6 @@ import ( _ "github.com/securego/gosec/v2/cmd/gosec" _ "github.com/uudashr/gopkgs/v2/cmd/gopkgs" _ "golang.org/x/lint/golint" - _ "golang.org/x/tools/cmd/goimports" _ "golang.org/x/tools/gopls" // used for changelog-check tooling From f0f3bbbc234e07bb1dc425756b59f42bb32439c0 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sat, 15 Apr 2023 12:02:50 -0400 Subject: [PATCH 303/370] Add region to challenge_widget --- challenge_widgets.go | 1 + challenge_widgets_test.go | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/challenge_widgets.go b/challenge_widgets.go index a9e9534f2f..292d942008 100644 --- a/challenge_widgets.go +++ b/challenge_widgets.go @@ -20,6 +20,7 @@ type ChallengeWidget struct { Domains []string `json:"domains,omitempty"` Type string `json:"type,omitempty"` BotFightMode bool `json:"bot_fight_mode,omitempty"` + Region string `json:"region,omitempty"` } type ChallengeWidgetResponse struct { diff --git a/challenge_widgets_test.go b/challenge_widgets_test.go index 4c9563b770..86616f98b4 100644 --- a/challenge_widgets_test.go +++ b/challenge_widgets_test.go @@ -28,6 +28,7 @@ var ( }, Type: "invisible", BotFightMode: true, + Region: "world", } ) @@ -55,7 +56,8 @@ func TestChallengeWidgets_Create(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } }`) }) @@ -75,6 +77,7 @@ func TestChallengeWidgets_Create(t *testing.T) { "cloudflare.com", "blog.example.com", }, + Region: "world", }) if assert.NoError(t, err) { assert.Equal(t, expectedChallengeWidget, out, "create challenge_widgets structs not equal") @@ -87,6 +90,7 @@ func TestChallengeWidgets_List(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + assert.Equal(t, "asc", r.URL.Query().Get("order")) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` { @@ -106,7 +110,8 @@ func TestChallengeWidgets_List(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } ], "result_info": { @@ -123,7 +128,9 @@ func TestChallengeWidgets_List(t *testing.T) { assert.Equal(t, ErrMissingAccountID, err) } - out, results, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ListChallengeWidgetRequest{}) + out, results, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ListChallengeWidgetRequest{ + Order: "asc", + }) if assert.NoError(t, err) { assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") assert.Equal(t, 20, results.PerPage, "expected 20 per page") @@ -155,7 +162,8 @@ func TestChallengeWidgets_Get(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } }`) }) @@ -201,7 +209,8 @@ func TestChallengeWidgets_Update(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } }`) }) @@ -248,7 +257,8 @@ func TestChallengeWidgets_RotateSecret(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } }`) }) @@ -294,7 +304,8 @@ func TestChallengeWidgets_Delete(t *testing.T) { "blog.example.com" ], "type": "invisible", - "bot_fight_mode": true + "bot_fight_mode": true, + "region": "world" } }`) }) From c312f11b41c824130707abee640892ac980e37b2 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sat, 15 Apr 2023 13:56:20 -0400 Subject: [PATCH 304/370] use CreateChallengeWidgetRequest to create ChallengeWidgets --- challenge_widgets.go | 13 +++++++++++-- challenge_widgets_test.go | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/challenge_widgets.go b/challenge_widgets.go index 292d942008..a05c5fb0a9 100644 --- a/challenge_widgets.go +++ b/challenge_widgets.go @@ -18,11 +18,20 @@ type ChallengeWidget struct { ModifiedOn *time.Time `json:"modified_on,omitempty"` Name string `json:"name,omitempty"` Domains []string `json:"domains,omitempty"` - Type string `json:"type,omitempty"` + Mode string `json:"mode,omitempty"` BotFightMode bool `json:"bot_fight_mode,omitempty"` Region string `json:"region,omitempty"` } +type CreateChallengeWidgetRequest struct { + Name string `json:"name,omitempty"` + Domains []string `json:"domains,omitempty"` + Mode string `json:"mode,omitempty"` + BotFightMode bool `json:"bot_fight_mode,omitempty"` + Region string `json:"region,omitempty"` + OffLabel bool `json:"off_label,omitempty"` +} + type ChallengeWidgetResponse struct { Response Result ChallengeWidget `json:"result"` @@ -48,7 +57,7 @@ type RotateChallengeWidgetRequest struct { // CreateChallengeWidget creates a new challenge widgets. // // API reference: https://api.cloudflare.com/#challenge-widgets-properties -func (api *API) CreateChallengeWidget(ctx context.Context, rc *ResourceContainer, params ChallengeWidget) (ChallengeWidget, error) { +func (api *API) CreateChallengeWidget(ctx context.Context, rc *ResourceContainer, params CreateChallengeWidgetRequest) (ChallengeWidget, error) { if rc.Identifier == "" { return ChallengeWidget{}, ErrMissingAccountID } diff --git a/challenge_widgets_test.go b/challenge_widgets_test.go index 86616f98b4..2c60bb9dba 100644 --- a/challenge_widgets_test.go +++ b/challenge_widgets_test.go @@ -26,7 +26,7 @@ var ( "cloudflare.com", "blog.example.com", }, - Type: "invisible", + Mode: "invisible", BotFightMode: true, Region: "world", } @@ -55,7 +55,7 @@ func TestChallengeWidgets_Create(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } @@ -63,14 +63,14 @@ func TestChallengeWidgets_Create(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(""), ChallengeWidget{}) + _, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(""), CreateChallengeWidgetRequest{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{ + out, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), CreateChallengeWidgetRequest{ Name: "blog.cloudflare.com login form", - Type: "invisible", + Mode: "invisible", BotFightMode: true, Domains: []string{ "203.0.113.1", @@ -109,7 +109,7 @@ func TestChallengeWidgets_List(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } @@ -161,7 +161,7 @@ func TestChallengeWidgets_Get(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } @@ -208,7 +208,7 @@ func TestChallengeWidgets_Update(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } @@ -256,7 +256,7 @@ func TestChallengeWidgets_RotateSecret(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } @@ -303,7 +303,7 @@ func TestChallengeWidgets_Delete(t *testing.T) { "cloudflare.com", "blog.example.com" ], - "type": "invisible", + "mode": "invisible", "bot_fight_mode": true, "region": "world" } From 415696f3bb71b787c97a10d52ff576bd8d31f5fb Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Mon, 17 Apr 2023 16:16:19 -0400 Subject: [PATCH 305/370] Add support for missing posture check providers - Intune - Tanium - Kolide --- device_posture_rule.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/device_posture_rule.go b/device_posture_rule.go index 83aedde75c..5d04e270b5 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 From cf6ed3d929d83bd634ff587f4d48219c168eafc5 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Mon, 17 Apr 2023 17:24:30 -0400 Subject: [PATCH 306/370] challenge_widgets -> turnstile --- .changelog/1267.txt | 2 +- cloudflare.go | 7 ++ challenge_widgets.go => turnstile.go | 95 ++++++++++--------- ...lenge_widgets_test.go => turnstile_test.go | 78 +++++++-------- 4 files changed, 95 insertions(+), 87 deletions(-) rename challenge_widgets.go => turnstile.go (60%) rename challenge_widgets_test.go => turnstile_test.go (69%) diff --git a/.changelog/1267.txt b/.changelog/1267.txt index 491b402991..33e3526ec0 100644 --- a/.changelog/1267.txt +++ b/.changelog/1267.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -challenge_widget: add support for turnstile +turnstile: add support for turnstile ``` diff --git a/cloudflare.go b/cloudflare.go index e8d09ff697..8e5afe369e 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -596,3 +596,10 @@ func checkResultInfo(perPage, page, count int, info *ResultInfo) bool { panic("checkResultInfo: impossible") } } + +type OrderDirection string + +const ( + OrderDirectionAsc OrderDirection = "asc" + OrderDirectionDesc OrderDirection = "desc" +) diff --git a/challenge_widgets.go b/turnstile.go similarity index 60% rename from challenge_widgets.go rename to turnstile.go index a05c5fb0a9..d4524b060e 100644 --- a/challenge_widgets.go +++ b/turnstile.go @@ -11,7 +11,7 @@ import ( var ErrMissingSiteKey = errors.New("required site key missing") -type ChallengeWidget struct { +type TurnstileWidget struct { SiteKey string `json:"sitekey,omitempty"` Secret string `json:"secret,omitempty"` CreatedOn *time.Time `json:"created_on,omitempty"` @@ -21,9 +21,10 @@ type ChallengeWidget struct { Mode string `json:"mode,omitempty"` BotFightMode bool `json:"bot_fight_mode,omitempty"` Region string `json:"region,omitempty"` + OffLabel bool `json:"off_label,omitempty"` } -type CreateChallengeWidgetRequest struct { +type CreateTurnstileWidgetRequest struct { Name string `json:"name,omitempty"` Domains []string `json:"domains,omitempty"` Mode string `json:"mode,omitempty"` @@ -32,54 +33,54 @@ type CreateChallengeWidgetRequest struct { OffLabel bool `json:"off_label,omitempty"` } -type ChallengeWidgetResponse struct { +type TurnstileWidgetResponse struct { Response - Result ChallengeWidget `json:"result"` + Result TurnstileWidget `json:"result"` } -type ListChallengeWidgetRequest struct { +type ListTurnstileWidgetRequest struct { ResultInfo - Direction string `url:"direction,omitempty"` - Order string `url:"order,omitempty"` + Direction string `url:"direction,omitempty"` + Order OrderDirection `url:"order,omitempty"` } -type ListChallengeWidgetResponse struct { +type ListTurnstileWidgetResponse struct { Response ResultInfo `json:"result_info"` - Result []ChallengeWidget `json:"result"` + Result []TurnstileWidget `json:"result"` } -type RotateChallengeWidgetRequest struct { +type RotateTurnstileWidgetRequest struct { SiteKey string InvalidateImmediately bool `json:"invalidate_immediately,omitempty"` } -// CreateChallengeWidget creates a new challenge widgets. +// CreateTurnstileWidget creates a new challenge widgets. // // API reference: https://api.cloudflare.com/#challenge-widgets-properties -func (api *API) CreateChallengeWidget(ctx context.Context, rc *ResourceContainer, params CreateChallengeWidgetRequest) (ChallengeWidget, error) { +func (api *API) CreateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params CreateTurnstileWidgetRequest) (TurnstileWidget, error) { if rc.Identifier == "" { - return ChallengeWidget{}, ErrMissingAccountID + return TurnstileWidget{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier) res, err := api.makeRequestContext(ctx, "POST", uri, params) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var r ChallengeWidgetResponse + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// ListChallengeWidget lists challenge widgets. +// ListTurnstileWidgets lists challenge widgets. // // API reference: https://api.cloudflare.com/#challenge-widgets-list-challenge-widgets -func (api *API) ListChallengeWidget(ctx context.Context, rc *ResourceContainer, params ListChallengeWidgetRequest) ([]ChallengeWidget, *ResultInfo, error) { +func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, params ListTurnstileWidgetRequest) ([]TurnstileWidget, *ResultInfo, error) { if rc.Identifier == "" { - return []ChallengeWidget{}, &ResultInfo{}, ErrMissingAccountID + return []TurnstileWidget{}, &ResultInfo{}, ErrMissingAccountID } autoPaginate := true if params.PerPage >= 1 || params.Page >= 1 { @@ -94,18 +95,18 @@ func (api *API) ListChallengeWidget(ctx context.Context, rc *ResourceContainer, params.Page = 1 } - var widgets []ChallengeWidget - var r ListChallengeWidgetResponse + var widgets []TurnstileWidget + var r ListTurnstileWidgetResponse for { uri := buildURI(fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []ChallengeWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } err = json.Unmarshal(res, &r) if err != nil { - return []ChallengeWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } widgets = append(widgets, r.Result...) params.ResultInfo = r.ResultInfo.Next() @@ -117,87 +118,87 @@ func (api *API) ListChallengeWidget(ctx context.Context, rc *ResourceContainer, return widgets, &r.ResultInfo, nil } -// GetChallengeWidget shows a single challenge widget configuration.. +// GetTurnstileWidget shows a single challenge widget configuration.. // // API reference: https://api.cloudflare.com/#challenge-widgets-challenge-widget-details -func (api *API) GetChallengeWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) (ChallengeWidget, error) { +func (api *API) GetTurnstileWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) (TurnstileWidget, error) { if rc.Identifier == "" { - return ChallengeWidget{}, ErrMissingAccountID + return TurnstileWidget{}, ErrMissingAccountID } if SiteKey == "" { - return ChallengeWidget{}, ErrMissingSiteKey + return TurnstileWidget{}, ErrMissingSiteKey } uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, SiteKey) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var r ChallengeWidgetResponse + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// UpdateChallengeWidget update the configuration of a widget. +// UpdateTurnstileWidget update the configuration of a widget. // // API reference: https://api.cloudflare.com/#challenge-widgets-update-a-challenge-widget -func (api *API) UpdateChallengeWidget(ctx context.Context, rc *ResourceContainer, widget ChallengeWidget) (ChallengeWidget, error) { +func (api *API) UpdateTurnstileWidget(ctx context.Context, rc *ResourceContainer, widget TurnstileWidget) (TurnstileWidget, error) { if rc.Identifier == "" { - return ChallengeWidget{}, ErrMissingAccountID + return TurnstileWidget{}, ErrMissingAccountID } if widget.SiteKey == "" { - return ChallengeWidget{}, ErrMissingSiteKey + return TurnstileWidget{}, ErrMissingSiteKey } uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, widget.SiteKey) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, widget) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var r ChallengeWidgetResponse + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// RotateChallengeWidget generates a new secret key for this widget. If invalidate_immediately is set to false, the previous secret remains valid for 2 hours. +// RotateTurnstileWidget generates a new secret key for this widget. If invalidate_immediately is set to false, the previous secret remains valid for 2 hours. // // Note that secrets cannot be rotated again during the grace period. // // API reference: https://api.cloudflare.com/#challenge-widgets-rotate-secret-for-a-challenge-widget -func (api *API) RotateChallengeWidget(ctx context.Context, rc *ResourceContainer, param RotateChallengeWidgetRequest) (ChallengeWidget, error) { +func (api *API) RotateTurnstileWidget(ctx context.Context, rc *ResourceContainer, param RotateTurnstileWidgetRequest) (TurnstileWidget, error) { if rc.Identifier == "" { - return ChallengeWidget{}, ErrMissingAccountID + return TurnstileWidget{}, ErrMissingAccountID } if param.SiteKey == "" { - return ChallengeWidget{}, ErrMissingSiteKey + return TurnstileWidget{}, ErrMissingSiteKey } uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s/rotate_secret", rc.Identifier, param.SiteKey) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, param) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var r ChallengeWidgetResponse + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { - return ChallengeWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } return r.Result, nil } -// DeleteChallengeWidget delete a challenge widget. +// DeleteTurnstileWidget delete a challenge widget. // // API reference: https://api.cloudflare.com/#challenge-widgets-delete-a-challenge-widget -func (api *API) DeleteChallengeWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) error { +func (api *API) DeleteTurnstileWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) error { if rc.Identifier == "" { return ErrMissingAccountID } @@ -212,7 +213,7 @@ func (api *API) DeleteChallengeWidget(ctx context.Context, rc *ResourceContainer return fmt.Errorf("%s: %w", errMakeRequestError, err) } - var r ChallengeWidgetResponse + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { return fmt.Errorf("%s: %w", errUnmarshalError, err) diff --git a/challenge_widgets_test.go b/turnstile_test.go similarity index 69% rename from challenge_widgets_test.go rename to turnstile_test.go index 2c60bb9dba..2087044ff8 100644 --- a/challenge_widgets_test.go +++ b/turnstile_test.go @@ -10,16 +10,16 @@ import ( "github.com/stretchr/testify/assert" ) -const testChallengeWidgetSiteKey = "0x4AAF00AAAABn0R22HWm-YUc" +const testTurnstileWidgetSiteKey = "0x4AAF00AAAABn0R22HWm-YUc" var ( - challengeWidgetCreatedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") - challengeWidgetModifiedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") - expectedChallengeWidget = ChallengeWidget{ + turnstileWidgetCreatedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") + turnstileWidgetModifiedOn, _ = time.Parse(time.RFC3339, "2014-01-01T05:20:00.123123Z") + expectedTurnstileWidget = TurnstileWidget{ SiteKey: "0x4AAF00AAAABn0R22HWm-YUc", Secret: "0x4AAF00AAAABn0R22HWm098HVBjhdsYUc", - CreatedOn: &challengeWidgetCreatedOn, - ModifiedOn: &challengeWidgetModifiedOn, + CreatedOn: &turnstileWidgetCreatedOn, + ModifiedOn: &turnstileWidgetModifiedOn, Name: "blog.cloudflare.com login form", Domains: []string{ "203.0.113.1", @@ -32,7 +32,7 @@ var ( } ) -func TestChallengeWidgets_Create(t *testing.T) { +func TestTurnstileWidget_Create(t *testing.T) { setup() defer teardown() @@ -63,12 +63,12 @@ func TestChallengeWidgets_Create(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(""), CreateChallengeWidgetRequest{}) + _, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(""), CreateTurnstileWidgetRequest{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, err := client.CreateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), CreateChallengeWidgetRequest{ + out, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), CreateTurnstileWidgetRequest{ Name: "blog.cloudflare.com login form", Mode: "invisible", BotFightMode: true, @@ -80,11 +80,11 @@ func TestChallengeWidgets_Create(t *testing.T) { Region: "world", }) if assert.NoError(t, err) { - assert.Equal(t, expectedChallengeWidget, out, "create challenge_widgets structs not equal") + assert.Equal(t, expectedTurnstileWidget, out, "create challenge_widgets structs not equal") } } -func TestChallengeWidgets_List(t *testing.T) { +func TestTurnstileWidget_List(t *testing.T) { setup() defer teardown() @@ -123,26 +123,26 @@ func TestChallengeWidgets_List(t *testing.T) { }`) }) - _, _, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(""), ListChallengeWidgetRequest{}) + _, _, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(""), ListTurnstileWidgetRequest{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, results, err := client.ListChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ListChallengeWidgetRequest{ - Order: "asc", + out, results, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(testAccountID), ListTurnstileWidgetRequest{ + Order: OrderDirectionAsc, }) if assert.NoError(t, err) { assert.Equal(t, 1, len(out), "expected 1 challenge_widgets") assert.Equal(t, 20, results.PerPage, "expected 20 per page") - assert.Equal(t, expectedChallengeWidget, out[0], "list challenge_widgets structs not equal") + assert.Equal(t, expectedTurnstileWidget, out[0], "list challenge_widgets structs not equal") } } -func TestChallengeWidgets_Get(t *testing.T) { +func TestTurnstileWidget_Get(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testTurnstileWidgetSiteKey, 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.Fprint(w, ` @@ -168,28 +168,28 @@ func TestChallengeWidgets_Get(t *testing.T) { }`) }) - _, err := client.GetChallengeWidget(context.Background(), AccountIdentifier(""), "") + _, err := client.GetTurnstileWidget(context.Background(), AccountIdentifier(""), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.GetChallengeWidget(context.Background(), AccountIdentifier(testAccountID), "") + _, err = client.GetTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - out, err := client.GetChallengeWidget(context.Background(), AccountIdentifier(testAccountID), testChallengeWidgetSiteKey) + out, err := client.GetTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), testTurnstileWidgetSiteKey) if assert.NoError(t, err) { - assert.Equal(t, expectedChallengeWidget, out, "get challenge_widgets structs not equal") + assert.Equal(t, expectedTurnstileWidget, out, "get challenge_widgets structs not equal") } } -func TestChallengeWidgets_Update(t *testing.T) { +func TestTurnstileWidgets_Update(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testTurnstileWidgetSiteKey, 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.Fprint(w, ` @@ -215,29 +215,29 @@ func TestChallengeWidgets_Update(t *testing.T) { }`) }) - _, err := client.UpdateChallengeWidget(context.Background(), AccountIdentifier(""), ChallengeWidget{}) + _, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(""), TurnstileWidget{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.UpdateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{}) + _, err = client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), TurnstileWidget{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - out, err := client.UpdateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), ChallengeWidget{ - SiteKey: testChallengeWidgetSiteKey, + out, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), TurnstileWidget{ + SiteKey: testTurnstileWidgetSiteKey, }) if assert.NoError(t, err) { - assert.Equal(t, expectedChallengeWidget, out, "update challenge_widgets structs not equal") + assert.Equal(t, expectedTurnstileWidget, out, "update challenge_widgets structs not equal") } } -func TestChallengeWidgets_RotateSecret(t *testing.T) { +func TestTurnstileWidgets_RotateSecret(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey+"/rotate_secret", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testTurnstileWidgetSiteKey+"/rotate_secret", func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` @@ -264,27 +264,27 @@ func TestChallengeWidgets_RotateSecret(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.RotateChallengeWidget(context.Background(), AccountIdentifier(""), RotateChallengeWidgetRequest{}) + _, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(""), RotateTurnstileWidgetRequest{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.RotateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), RotateChallengeWidgetRequest{}) + _, err = client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetRequest{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - out, err := client.RotateChallengeWidget(context.Background(), AccountIdentifier(testAccountID), RotateChallengeWidgetRequest{SiteKey: testChallengeWidgetSiteKey}) + out, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetRequest{SiteKey: testTurnstileWidgetSiteKey}) if assert.NoError(t, err) { - assert.Equal(t, expectedChallengeWidget, out, "rotate challenge_widgets structs not equal") + assert.Equal(t, expectedTurnstileWidget, out, "rotate challenge_widgets structs not equal") } } -func TestChallengeWidgets_Delete(t *testing.T) { +func TestTurnstileWidgets_Delete(t *testing.T) { setup() defer teardown() - mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testChallengeWidgetSiteKey, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/accounts/"+testAccountID+"/challenges/widgets/"+testTurnstileWidgetSiteKey, func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) w.Header().Set("content-type", "application/json") fmt.Fprint(w, ` @@ -311,16 +311,16 @@ func TestChallengeWidgets_Delete(t *testing.T) { }) // Make sure missing account ID is thrown - err := client.DeleteChallengeWidget(context.Background(), AccountIdentifier(""), "") + err := client.DeleteTurnstileWidget(context.Background(), AccountIdentifier(""), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - err = client.DeleteChallengeWidget(context.Background(), AccountIdentifier(testAccountID), "") + err = client.DeleteTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), "") if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - err = client.DeleteChallengeWidget(context.Background(), AccountIdentifier(testAccountID), testChallengeWidgetSiteKey) + err = client.DeleteTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), testTurnstileWidgetSiteKey) assert.NoError(t, err) } From 83bd66f4ef0857e7879335e4f77237dc88fcbc41 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Mon, 17 Apr 2023 18:16:10 -0400 Subject: [PATCH 307/370] Address PR comments --- turnstile.go | 6 +++--- turnstile_test.go | 22 +++++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/turnstile.go b/turnstile.go index d4524b060e..3ea17f018e 100644 --- a/turnstile.go +++ b/turnstile.go @@ -21,7 +21,7 @@ type TurnstileWidget struct { Mode string `json:"mode,omitempty"` BotFightMode bool `json:"bot_fight_mode,omitempty"` Region string `json:"region,omitempty"` - OffLabel bool `json:"off_label,omitempty"` + OffLabel bool `json:"offlabel,omitempty"` } type CreateTurnstileWidgetRequest struct { @@ -30,7 +30,7 @@ type CreateTurnstileWidgetRequest struct { Mode string `json:"mode,omitempty"` BotFightMode bool `json:"bot_fight_mode,omitempty"` Region string `json:"region,omitempty"` - OffLabel bool `json:"off_label,omitempty"` + OffLabel bool `json:"offlabel,omitempty"` } type TurnstileWidgetResponse struct { @@ -88,7 +88,7 @@ func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, } if params.PerPage < 1 { - params.PerPage = 50 + params.PerPage = 25 } if params.Page < 1 { diff --git a/turnstile_test.go b/turnstile_test.go index 2087044ff8..e43db81cc4 100644 --- a/turnstile_test.go +++ b/turnstile_test.go @@ -29,6 +29,7 @@ var ( Mode: "invisible", BotFightMode: true, Region: "world", + OffLabel: false, } ) @@ -57,7 +58,8 @@ func TestTurnstileWidget_Create(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } }`) }) @@ -77,7 +79,8 @@ func TestTurnstileWidget_Create(t *testing.T) { "cloudflare.com", "blog.example.com", }, - Region: "world", + Region: "world", + OffLabel: false, }) if assert.NoError(t, err) { assert.Equal(t, expectedTurnstileWidget, out, "create challenge_widgets structs not equal") @@ -111,7 +114,8 @@ func TestTurnstileWidget_List(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } ], "result_info": { @@ -163,7 +167,8 @@ func TestTurnstileWidget_Get(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } }`) }) @@ -210,7 +215,8 @@ func TestTurnstileWidgets_Update(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } }`) }) @@ -258,7 +264,8 @@ func TestTurnstileWidgets_RotateSecret(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } }`) }) @@ -305,7 +312,8 @@ func TestTurnstileWidgets_Delete(t *testing.T) { ], "mode": "invisible", "bot_fight_mode": true, - "region": "world" + "region": "world", + "offlabel": false } }`) }) From 17b75913f9e40c2b073dc53e1c62dfca0fe597ba Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Mon, 17 Apr 2023 19:43:16 -0400 Subject: [PATCH 308/370] Add release notes --- .changelog/1268.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1268.txt diff --git a/.changelog/1268.txt b/.changelog/1268.txt new file mode 100644 index 0000000000..586bac29d8 --- /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 From fb44b2da95366def0612b8473f38e86a28d04d95 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 18 Apr 2023 10:56:02 +1000 Subject: [PATCH 309/370] update parameter naming conventions --- turnstile.go | 63 ++++++++++++++++++++++++++++++++--------------- turnstile_test.go | 20 +++++++-------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/turnstile.go b/turnstile.go index 3ea17f018e..565a36e6ec 100644 --- a/turnstile.go +++ b/turnstile.go @@ -24,7 +24,18 @@ type TurnstileWidget struct { OffLabel bool `json:"offlabel,omitempty"` } -type CreateTurnstileWidgetRequest struct { +type CreateTurnstileWidgetParams struct { + Name string `json:"name,omitempty"` + Domains []string `json:"domains,omitempty"` + Mode string `json:"mode,omitempty"` + BotFightMode bool `json:"bot_fight_mode,omitempty"` + Region string `json:"region,omitempty"` + OffLabel bool `json:"offlabel,omitempty"` +} + +type UpdateTurnstileWidgetParams struct { + SiteKey string `json:"sitekey,omitempty"` + Secret string `json:"secret,omitempty"` Name string `json:"name,omitempty"` Domains []string `json:"domains,omitempty"` Mode string `json:"mode,omitempty"` @@ -38,7 +49,7 @@ type TurnstileWidgetResponse struct { Result TurnstileWidget `json:"result"` } -type ListTurnstileWidgetRequest struct { +type ListTurnstileWidgetParams struct { ResultInfo Direction string `url:"direction,omitempty"` Order OrderDirection `url:"order,omitempty"` @@ -50,7 +61,7 @@ type ListTurnstileWidgetResponse struct { Result []TurnstileWidget `json:"result"` } -type RotateTurnstileWidgetRequest struct { +type RotateTurnstileWidgetParams struct { SiteKey string InvalidateImmediately bool `json:"invalidate_immediately,omitempty"` } @@ -58,27 +69,30 @@ type RotateTurnstileWidgetRequest struct { // CreateTurnstileWidget creates a new challenge widgets. // // API reference: https://api.cloudflare.com/#challenge-widgets-properties -func (api *API) CreateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params CreateTurnstileWidgetRequest) (TurnstileWidget, error) { +func (api *API) CreateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params CreateTurnstileWidgetParams) (TurnstileWidget, error) { if rc.Identifier == "" { return TurnstileWidget{}, ErrMissingAccountID } + uri := fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier) res, err := api.makeRequestContext(ctx, "POST", uri, params) if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } + return r.Result, nil } // ListTurnstileWidgets lists challenge widgets. // // API reference: https://api.cloudflare.com/#challenge-widgets-list-challenge-widgets -func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, params ListTurnstileWidgetRequest) ([]TurnstileWidget, *ResultInfo, error) { +func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, params ListTurnstileWidgetParams) ([]TurnstileWidget, *ResultInfo, error) { if rc.Identifier == "" { return []TurnstileWidget{}, &ResultInfo{}, ErrMissingAccountID } @@ -99,8 +113,8 @@ func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, var r ListTurnstileWidgetResponse for { uri := buildURI(fmt.Sprintf("/accounts/%s/challenges/widgets", rc.Identifier), params) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -108,6 +122,7 @@ func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, if err != nil { return []TurnstileWidget{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } + widgets = append(widgets, r.Result...) params.ResultInfo = r.ResultInfo.Next() if params.ResultInfo.Done() || !autoPaginate { @@ -118,24 +133,24 @@ func (api *API) ListTurnstileWidgets(ctx context.Context, rc *ResourceContainer, return widgets, &r.ResultInfo, nil } -// GetTurnstileWidget shows a single challenge widget configuration.. +// GetTurnstileWidget shows a single challenge widget configuration. // // API reference: https://api.cloudflare.com/#challenge-widgets-challenge-widget-details -func (api *API) GetTurnstileWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) (TurnstileWidget, error) { +func (api *API) GetTurnstileWidget(ctx context.Context, rc *ResourceContainer, siteKey string) (TurnstileWidget, error) { if rc.Identifier == "" { return TurnstileWidget{}, ErrMissingAccountID } - if SiteKey == "" { + if siteKey == "" { return TurnstileWidget{}, ErrMissingSiteKey } - uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, SiteKey) + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, siteKey) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { @@ -148,18 +163,21 @@ func (api *API) GetTurnstileWidget(ctx context.Context, rc *ResourceContainer, S // UpdateTurnstileWidget update the configuration of a widget. // // API reference: https://api.cloudflare.com/#challenge-widgets-update-a-challenge-widget -func (api *API) UpdateTurnstileWidget(ctx context.Context, rc *ResourceContainer, widget TurnstileWidget) (TurnstileWidget, error) { +func (api *API) UpdateTurnstileWidget(ctx context.Context, rc *ResourceContainer, params UpdateTurnstileWidgetParams) (TurnstileWidget, error) { if rc.Identifier == "" { return TurnstileWidget{}, ErrMissingAccountID } - if widget.SiteKey == "" { + + if params.SiteKey == "" { return TurnstileWidget{}, ErrMissingSiteKey } - uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, widget.SiteKey) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, widget) + + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, params.SiteKey) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { @@ -168,12 +186,14 @@ func (api *API) UpdateTurnstileWidget(ctx context.Context, rc *ResourceContainer return r.Result, nil } -// RotateTurnstileWidget generates a new secret key for this widget. If invalidate_immediately is set to false, the previous secret remains valid for 2 hours. +// RotateTurnstileWidget generates a new secret key for this widget. If +// invalidate_immediately is set to false, the previous secret remains valid for +// 2 hours. // // Note that secrets cannot be rotated again during the grace period. // // API reference: https://api.cloudflare.com/#challenge-widgets-rotate-secret-for-a-challenge-widget -func (api *API) RotateTurnstileWidget(ctx context.Context, rc *ResourceContainer, param RotateTurnstileWidgetRequest) (TurnstileWidget, error) { +func (api *API) RotateTurnstileWidget(ctx context.Context, rc *ResourceContainer, param RotateTurnstileWidgetParams) (TurnstileWidget, error) { if rc.Identifier == "" { return TurnstileWidget{}, ErrMissingAccountID } @@ -187,26 +207,28 @@ func (api *API) RotateTurnstileWidget(ctx context.Context, rc *ResourceContainer if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } + var r TurnstileWidgetResponse err = json.Unmarshal(res, &r) if err != nil { return TurnstileWidget{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } + return r.Result, nil } // DeleteTurnstileWidget delete a challenge widget. // // API reference: https://api.cloudflare.com/#challenge-widgets-delete-a-challenge-widget -func (api *API) DeleteTurnstileWidget(ctx context.Context, rc *ResourceContainer, SiteKey string) error { +func (api *API) DeleteTurnstileWidget(ctx context.Context, rc *ResourceContainer, siteKey string) error { if rc.Identifier == "" { return ErrMissingAccountID } - if SiteKey == "" { + if siteKey == "" { return ErrMissingSiteKey } - uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, SiteKey) + uri := fmt.Sprintf("/accounts/%s/challenges/widgets/%s", rc.Identifier, siteKey) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -218,5 +240,6 @@ func (api *API) DeleteTurnstileWidget(ctx context.Context, rc *ResourceContainer if err != nil { return fmt.Errorf("%s: %w", errUnmarshalError, err) } + return nil } diff --git a/turnstile_test.go b/turnstile_test.go index e43db81cc4..f2193431f4 100644 --- a/turnstile_test.go +++ b/turnstile_test.go @@ -65,12 +65,12 @@ func TestTurnstileWidget_Create(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(""), CreateTurnstileWidgetRequest{}) + _, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(""), CreateTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), CreateTurnstileWidgetRequest{ + out, err := client.CreateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), CreateTurnstileWidgetParams{ Name: "blog.cloudflare.com login form", Mode: "invisible", BotFightMode: true, @@ -127,12 +127,12 @@ func TestTurnstileWidget_List(t *testing.T) { }`) }) - _, _, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(""), ListTurnstileWidgetRequest{}) + _, _, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(""), ListTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - out, results, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(testAccountID), ListTurnstileWidgetRequest{ + out, results, err := client.ListTurnstileWidgets(context.Background(), AccountIdentifier(testAccountID), ListTurnstileWidgetParams{ Order: OrderDirectionAsc, }) if assert.NoError(t, err) { @@ -221,17 +221,17 @@ func TestTurnstileWidgets_Update(t *testing.T) { }`) }) - _, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(""), TurnstileWidget{}) + _, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(""), UpdateTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), TurnstileWidget{}) + _, err = client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), UpdateTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - out, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), TurnstileWidget{ + out, err := client.UpdateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), UpdateTurnstileWidgetParams{ SiteKey: testTurnstileWidgetSiteKey, }) if assert.NoError(t, err) { @@ -271,17 +271,17 @@ func TestTurnstileWidgets_RotateSecret(t *testing.T) { }) // Make sure missing account ID is thrown - _, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(""), RotateTurnstileWidgetRequest{}) + _, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(""), RotateTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - _, err = client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetRequest{}) + _, err = client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetParams{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingSiteKey, err) } - out, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetRequest{SiteKey: testTurnstileWidgetSiteKey}) + out, err := client.RotateTurnstileWidget(context.Background(), AccountIdentifier(testAccountID), RotateTurnstileWidgetParams{SiteKey: testTurnstileWidgetSiteKey}) if assert.NoError(t, err) { assert.Equal(t, expectedTurnstileWidget, out, "rotate challenge_widgets structs not equal") } From 13bfa2cf0e5d4c1968677fdb36748f6ac46c6c53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:57:03 +0000 Subject: [PATCH 310/370] build(deps): bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.3.6 to 1.4.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/v1.3.6...v1.4.0) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dependabot-changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-changelog.yml b/.github/workflows/dependabot-changelog.yml index 8219a4ac6a..47348b419a 100644 --- a/.github/workflows/dependabot-changelog.yml +++ b/.github/workflows/dependabot-changelog.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Fetch dependabot metadata id: dependabot-metadata - uses: dependabot/fetch-metadata@v1.3.6 + uses: dependabot/fetch-metadata@v1.4.0 - uses: actions/checkout@v3 - run: | gh pr checkout $PR_URL From b16601bd37e6a654fe2c8ea792f823a1a98666f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Apr 2023 16:57:19 +0000 Subject: [PATCH 311/370] add CHANGELOG for #1269 --- .changelog/1269.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1269.txt diff --git a/.changelog/1269.txt b/.changelog/1269.txt new file mode 100644 index 0000000000..686ac6a9af --- /dev/null +++ b/.changelog/1269.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps dependabot/fetch-metadata from 1.3.6 to 1.4.0 +``` From b346f6d9bc166d9e7f23536ec7756be55b6f4097 Mon Sep 17 00:00:00 2001 From: Andrew Berglund Date: Tue, 28 Feb 2023 21:59:37 -0600 Subject: [PATCH 312/370] PA-2043 - Add support for regional hostnames This covers the API calls documented here: https://developers.cloudflare.com/data-localization/regional-services/get-started/ --- regional_hostnames.go | 184 ++++++++++++++++++++++++++++++++ regional_hostnames_test.go | 209 +++++++++++++++++++++++++++++++++++++ 2 files changed, 393 insertions(+) create mode 100644 regional_hostnames.go create mode 100644 regional_hostnames_test.go diff --git a/regional_hostnames.go b/regional_hostnames.go new file mode 100644 index 0000000000..091d4be332 --- /dev/null +++ b/regional_hostnames.go @@ -0,0 +1,184 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +type Region struct { + Key string `json:"key"` + Label string `json:"label"` +} + +type RegionalHostname struct { + Hostname string `json:"hostname"` + RegionKey string `json:"region_key"` + CreatedOn *time.Time `json:"created_on,omitempty"` +} + +// regionalHostnameResponse contains an API Response from a Create, Get, Update, or Delete call. +type regionalHostnameResponse struct { + Response + Result RegionalHostname `json:"result"` +} + +// ListDataLocalizationRegions lists all available regions. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) ListDataLocalizationRegions(ctx context.Context, rc *ResourceContainer) ([]Region, error) { + if rc.Level != AccountRouteLevel { + return []Region{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return []Region{}, ErrMissingAccountID + } + + uri := fmt.Sprintf("/accounts/%s/addressing/regional_hostnames/regions", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []Region{}, err + } + result := struct { + Result []Region `json:"result"` + }{} + if err := json.Unmarshal(res, &result); err != nil { + return []Region{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return result.Result, nil +} + +// ListDataLocalizationRegionalHostnames lists all regional hostnames for a zone. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) ListDataLocalizationRegionalHostnames(ctx context.Context, rc *ResourceContainer) ([]RegionalHostname, error) { + if rc.Level != ZoneRouteLevel { + return []RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return []RegionalHostname{}, ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []RegionalHostname{}, err + } + result := struct { + Result []RegionalHostname `json:"result"` + }{} + if err := json.Unmarshal(res, &result); err != nil { + return []RegionalHostname{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return result.Result, nil +} + +// CreateDataLocalizationRegionalHostname lists all regional hostnames for a zone. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) CreateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, regionalHostname RegionalHostname) (RegionalHostname, error) { + if rc.Level != ZoneRouteLevel { + return RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return RegionalHostname{}, ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames", rc.Identifier) + + // Ensure we don't send this value, otherwise the service will reject the request. + regionalHostname.CreatedOn = nil + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, regionalHostname) + if err != nil { + return RegionalHostname{}, err + } + result := regionalHostnameResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return RegionalHostname{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return result.Result, nil +} + +// GetDataLocalizationRegionalHostname returns the details of a specific regional hostname. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) GetDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, hostname string) (RegionalHostname, error) { + if rc.Level != ZoneRouteLevel { + return RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return RegionalHostname{}, ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames/%s", rc.Identifier, hostname) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return RegionalHostname{}, err + } + + result := regionalHostnameResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return RegionalHostname{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return result.Result, nil +} + +// UpdateDataLocalizationRegionalHostname returns the details of a specific regional hostname. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, regionalHostname RegionalHostname) (RegionalHostname, error) { + if rc.Level != ZoneRouteLevel { + return RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return RegionalHostname{}, ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames/%s", rc.Identifier, regionalHostname.Hostname) + + params := struct { + RegionKey string `json:"region_key"` + }{ + RegionKey: regionalHostname.RegionKey, + } + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return RegionalHostname{}, err + } + result := regionalHostnameResponse{} + if err := json.Unmarshal(res, &result); err != nil { + return RegionalHostname{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return result.Result, nil +} + +// DeleteDataLocalizationRegionalHostname deletes a regional hostname. +// +// API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api +func (api *API) DeleteDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, hostname string) error { + if rc.Level != ZoneRouteLevel { + return fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) + } + + if rc.Identifier == "" { + return ErrMissingZoneID + } + + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames/%s", rc.Identifier, hostname) + + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return err + } + return nil +} diff --git a/regional_hostnames_test.go b/regional_hostnames_test.go new file mode 100644 index 0000000000..95ff0bc2f1 --- /dev/null +++ b/regional_hostnames_test.go @@ -0,0 +1,209 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestListRegions(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.Fprint(w, `{ + "result": [ + { + "key": "ca", + "label": "Canada" + }, + { + "key": "eu", + "label": "Europe" + } + ], + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/addressing/regional_hostnames/regions", handler) + + want := []Region{ + { + Key: "ca", + Label: "Canada", + }, + { + Key: "eu", + Label: "Europe", + }, + } + + actual, err := client.ListDataLocalizationRegions(context.Background(), AccountIdentifier(testAccountID)) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListRegionalHostnames(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.Fprint(w, `{ + "result": [ + { + "hostname": "ca.regional.ipam.rocks", + "region_key": "ca", + "created_on": "2023-01-14T00:47:57.060267Z" + } + ], + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) + + createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") + want := []RegionalHostname{ + { + Hostname: "ca.regional.ipam.rocks", + RegionKey: "ca", + CreatedOn: &createdOn, + }, + } + + actual, err := client.ListDataLocalizationRegionalHostnames(context.Background(), ZoneIdentifier(testZoneID)) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestCreateRegionalHostname(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "result": { + "hostname": "ca.regional.ipam.rocks", + "region_key": "ca", + "created_on": "2023-01-14T00:47:57.060267Z" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) + + want := RegionalHostname{ + RegionKey: "ca", + Hostname: "ca.regional.ipam.rocks", + } + + actual, err := client.CreateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) + createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") + want.CreatedOn = &createdOn + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestGetRegionalHostname(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.Fprint(w, `{ + "result": { + "hostname": "ca.regional.ipam.rocks", + "region_key": "ca", + "created_on": "2023-01-14T00:47:57.060267Z" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + testHostname := "ca.regional.ipam.rocks" + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + + actual, err := client.GetDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), testHostname) + createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") + want := RegionalHostname{ + RegionKey: "ca", + Hostname: "ca.regional.ipam.rocks", + CreatedOn: &createdOn, + } + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateRegionalHostname(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.Fprint(w, `{ + "result": { + "hostname": "ca.regional.ipam.rocks", + "region_key": "eu", + "created_on": "2023-01-14T00:47:57.060267Z" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + testHostname := "ca.regional.ipam.rocks" + want := RegionalHostname{ + RegionKey: "eu", + Hostname: testHostname, + } + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + + actual, err := client.UpdateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) + createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") + want.CreatedOn = &createdOn + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestDeleteRegionalHostname(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) + } + + testHostname := "ca.regional.ipam.rocks" + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + + err := client.DeleteDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), testHostname) + assert.NoError(t, err) +} From dbc5802829fccc01014c48d1b328c3600b0ebf5f Mon Sep 17 00:00:00 2001 From: Andrew Berglund Date: Tue, 18 Apr 2023 14:53:51 -0500 Subject: [PATCH 313/370] Add changelog entry --- .changelog/1270.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1270.txt diff --git a/.changelog/1270.txt b/.changelog/1270.txt new file mode 100644 index 0000000000..4c09f1f51d --- /dev/null +++ b/.changelog/1270.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +data localization: add support for regional hostnames API +``` From 7cf8ab2db2498b1bdf04fe7ba6e65c6417c047ab Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Tue, 18 Apr 2023 17:49:38 -0400 Subject: [PATCH 314/370] Address PR comments --- r2_bucket.go | 19 +++++++++++++------ r2_bucket_test.go | 22 +++++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/r2_bucket.go b/r2_bucket.go index 129617dab6..bae5fb5b6b 100644 --- a/r2_bucket.go +++ b/r2_bucket.go @@ -43,7 +43,8 @@ type ListR2BucketsParams struct { } type CreateR2BucketParameters struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` + LocationHind string `json:"locationHint,omitempty"` } type R2BucketResponse struct { @@ -75,19 +76,25 @@ func (api *API) ListR2Buckets(ctx context.Context, rc *ResourceContainer, params // CreateR2Bucket Creates a new R2 bucket. // // API reference: https://api.cloudflare.com/#r2-bucket-create-bucket -func (api *API) CreateR2Bucket(ctx context.Context, rc *ResourceContainer, params CreateR2BucketParameters) error { +func (api *API) CreateR2Bucket(ctx context.Context, rc *ResourceContainer, params CreateR2BucketParameters) (R2Bucket, error) { if rc.Identifier == "" { - return ErrMissingAccountID + return R2Bucket{}, ErrMissingAccountID } if params.Name == "" { - return ErrMissingBucketName + return R2Bucket{}, ErrMissingBucketName } uri := fmt.Sprintf("/accounts/%s/r2/buckets", rc.Identifier) - _, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) - return err + var r2BucketResponse R2BucketResponse + err = json.Unmarshal(res, &r2BucketResponse) + if err != nil { + return R2Bucket{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return r2BucketResponse.Result, nil } // GetR2Bucket Gets an existing R2 bucket. diff --git a/r2_bucket_test.go b/r2_bucket_test.go index 33f538225e..5860d843ae 100644 --- a/r2_bucket_test.go +++ b/r2_bucket_test.go @@ -100,22 +100,34 @@ func TestR2_CreateBucket(t *testing.T) { "success": true, "errors": [], "messages": [], - "result": {} + "result": { + "name": "example-bucket", + "creation_date": "2022-06-24T19:58:49.477Z", + "location": "ENAM" + } }`) }) - err := client.CreateR2Bucket(context.Background(), AccountIdentifier(""), CreateR2BucketParameters{}) + _, err := client.CreateR2Bucket(context.Background(), AccountIdentifier(""), CreateR2BucketParameters{}) if assert.Error(t, err) { assert.Equal(t, ErrMissingAccountID, err) } - err = client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: ""}) + _, err = client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: ""}) if assert.Error(t, err) { assert.Equal(t, ErrMissingBucketName, err) } + createDate, _ := time.Parse(time.RFC3339, "2022-06-24T19:58:49.477Z") + want := R2Bucket{ + Name: testBucketName, + CreationDate: &createDate, + Location: "ENAM", + } - err = client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: testBucketName}) - assert.NoError(t, err) + actual, err := client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: testBucketName}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } } func TestR2_DeleteBucket(t *testing.T) { From 196e9817ef87ced3393f576293e8977345d39cdc Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Tue, 18 Apr 2023 18:06:28 -0400 Subject: [PATCH 315/370] Fix typo --- r2_bucket.go | 2 +- r2_bucket_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/r2_bucket.go b/r2_bucket.go index bae5fb5b6b..c4c09d1672 100644 --- a/r2_bucket.go +++ b/r2_bucket.go @@ -44,7 +44,7 @@ type ListR2BucketsParams struct { type CreateR2BucketParameters struct { Name string `json:"name,omitempty"` - LocationHind string `json:"locationHint,omitempty"` + LocationHint string `json:"locationHint,omitempty"` } type R2BucketResponse struct { diff --git a/r2_bucket_test.go b/r2_bucket_test.go index 5860d843ae..ac9b2f9607 100644 --- a/r2_bucket_test.go +++ b/r2_bucket_test.go @@ -124,7 +124,7 @@ func TestR2_CreateBucket(t *testing.T) { Location: "ENAM", } - actual, err := client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: testBucketName}) + actual, err := client.CreateR2Bucket(context.Background(), AccountIdentifier(testAccountID), CreateR2BucketParameters{Name: testBucketName, LocationHint: "ENAM"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } From ede35bf7273b0c5b88a4a4fa3fb1f2215f226a07 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 18 Apr 2023 23:50:16 +0000 Subject: [PATCH 316/370] Update CHANGELOG.md for #1269 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54d6e080bc..049b338ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ENHANCEMENTS: * dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266)) +* turnstile: add support for turnstile ([#1267](https://github.com/cloudflare/cloudflare-go/issues/1267)) + +DEPENDENCIES: + +* deps: bumps dependabot/fetch-metadata from 1.3.6 to 1.4.0 ([#1269](https://github.com/cloudflare/cloudflare-go/issues/1269)) ## 0.65.0 (12th April, 2023) From 9c4dbb48670c6eff01d1fcda7f80fea0ecea0377 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 19 Apr 2023 02:20:06 +0000 Subject: [PATCH 317/370] Update CHANGELOG.md for #1223 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 049b338ef1..f73c8a2b73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* access_application: Add `path_cookie_attribute` app setting ([#1223](https://github.com/cloudflare/cloudflare-go/issues/1223)) * dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266)) * turnstile: add support for turnstile ([#1267](https://github.com/cloudflare/cloudflare-go/issues/1267)) From b59070a23da496a65a9e68df0d3160d56c389f51 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 19 Apr 2023 12:42:00 +1000 Subject: [PATCH 318/370] use example.com for test cases --- regional_hostnames_test.go | 47 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/regional_hostnames_test.go b/regional_hostnames_test.go index 95ff0bc2f1..ee070171a1 100644 --- a/regional_hostnames_test.go +++ b/regional_hostnames_test.go @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" ) +const regionalHostname = "eu.example.com" + func TestListRegions(t *testing.T) { setup() defer teardown() @@ -60,10 +62,10 @@ func TestListRegionalHostnames(t *testing.T) { 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.Fprint(w, `{ + fmt.Fprint(w, fmt.Sprintf(`{ "result": [ { - "hostname": "ca.regional.ipam.rocks", + "hostname": "%s", "region_key": "ca", "created_on": "2023-01-14T00:47:57.060267Z" } @@ -71,7 +73,7 @@ func TestListRegionalHostnames(t *testing.T) { "success": true, "errors": [], "messages": [] - }`) + }`, regionalHostname)) } mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) @@ -79,7 +81,7 @@ func TestListRegionalHostnames(t *testing.T) { createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") want := []RegionalHostname{ { - Hostname: "ca.regional.ipam.rocks", + Hostname: regionalHostname, RegionKey: "ca", CreatedOn: &createdOn, }, @@ -98,23 +100,23 @@ func TestCreateRegionalHostname(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ + fmt.Fprint(w, fmt.Sprintf(`{ "result": { - "hostname": "ca.regional.ipam.rocks", + "hostname": "%s", "region_key": "ca", "created_on": "2023-01-14T00:47:57.060267Z" }, "success": true, "errors": [], "messages": [] - }`) + }`, regionalHostname)) } mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) want := RegionalHostname{ RegionKey: "ca", - Hostname: "ca.regional.ipam.rocks", + Hostname: regionalHostname, } actual, err := client.CreateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) @@ -132,26 +134,25 @@ func TestGetRegionalHostname(t *testing.T) { 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.Fprint(w, `{ + fmt.Fprint(w, fmt.Sprintf(`{ "result": { - "hostname": "ca.regional.ipam.rocks", + "hostname": "%s", "region_key": "ca", "created_on": "2023-01-14T00:47:57.060267Z" }, "success": true, "errors": [], "messages": [] - }`) + }`, regionalHostname)) } - testHostname := "ca.regional.ipam.rocks" - mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+regionalHostname, handler) - actual, err := client.GetDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), testHostname) + actual, err := client.GetDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), regionalHostname) createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") want := RegionalHostname{ RegionKey: "ca", - Hostname: "ca.regional.ipam.rocks", + Hostname: regionalHostname, CreatedOn: &createdOn, } if assert.NoError(t, err) { @@ -166,24 +167,23 @@ func TestUpdateRegionalHostname(t *testing.T) { 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.Fprint(w, `{ + fmt.Fprint(w, fmt.Sprintf(`{ "result": { - "hostname": "ca.regional.ipam.rocks", + "hostname": "%s", "region_key": "eu", "created_on": "2023-01-14T00:47:57.060267Z" }, "success": true, "errors": [], "messages": [] - }`) + }`, regionalHostname)) } - testHostname := "ca.regional.ipam.rocks" want := RegionalHostname{ RegionKey: "eu", - Hostname: testHostname, + Hostname: regionalHostname, } - mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+regionalHostname, handler) actual, err := client.UpdateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") @@ -201,9 +201,8 @@ func TestDeleteRegionalHostname(t *testing.T) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) } - testHostname := "ca.regional.ipam.rocks" - mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+testHostname, handler) + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+regionalHostname, handler) - err := client.DeleteDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), testHostname) + err := client.DeleteDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), regionalHostname) assert.NoError(t, err) } From f9943bed07eb64248657f1d73c59fbd7fe2e76b2 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 19 Apr 2023 12:47:41 +1000 Subject: [PATCH 319/370] simplify methods using experimental client conventions Updates the methods to have dedicated third parameters which simplifies the methods and will allow them to move independently. --- regional_hostnames.go | 32 +++++++++++++++++++------------- regional_hostnames_test.go | 37 ++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/regional_hostnames.go b/regional_hostnames.go index 091d4be332..72d6dcc119 100644 --- a/regional_hostnames.go +++ b/regional_hostnames.go @@ -25,10 +25,23 @@ type regionalHostnameResponse struct { Result RegionalHostname `json:"result"` } +type ListDataLocalizationRegionsParams struct{} +type ListDataLocalizationRegionalHostnamesParams struct{} + +type CreateDataLocalizationRegionalHostnameParams struct { + Hostname string `json:"hostname"` + RegionKey string `json:"region_key"` +} + +type UpdateDataLocalizationRegionalHostnameParams struct { + Hostname string `json:"-"` + RegionKey string `json:"region_key"` +} + // ListDataLocalizationRegions lists all available regions. // // API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api -func (api *API) ListDataLocalizationRegions(ctx context.Context, rc *ResourceContainer) ([]Region, error) { +func (api *API) ListDataLocalizationRegions(ctx context.Context, rc *ResourceContainer, params ListDataLocalizationRegionsParams) ([]Region, error) { if rc.Level != AccountRouteLevel { return []Region{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -55,7 +68,7 @@ func (api *API) ListDataLocalizationRegions(ctx context.Context, rc *ResourceCon // ListDataLocalizationRegionalHostnames lists all regional hostnames for a zone. // // API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api -func (api *API) ListDataLocalizationRegionalHostnames(ctx context.Context, rc *ResourceContainer) ([]RegionalHostname, error) { +func (api *API) ListDataLocalizationRegionalHostnames(ctx context.Context, rc *ResourceContainer, params ListDataLocalizationRegionalHostnamesParams) ([]RegionalHostname, error) { if rc.Level != ZoneRouteLevel { return []RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -82,7 +95,7 @@ func (api *API) ListDataLocalizationRegionalHostnames(ctx context.Context, rc *R // CreateDataLocalizationRegionalHostname lists all regional hostnames for a zone. // // API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api -func (api *API) CreateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, regionalHostname RegionalHostname) (RegionalHostname, error) { +func (api *API) CreateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, params CreateDataLocalizationRegionalHostnameParams) (RegionalHostname, error) { if rc.Level != ZoneRouteLevel { return RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -93,9 +106,7 @@ func (api *API) CreateDataLocalizationRegionalHostname(ctx context.Context, rc * uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames", rc.Identifier) - // Ensure we don't send this value, otherwise the service will reject the request. - regionalHostname.CreatedOn = nil - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, regionalHostname) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return RegionalHostname{}, err } @@ -135,7 +146,7 @@ func (api *API) GetDataLocalizationRegionalHostname(ctx context.Context, rc *Res // UpdateDataLocalizationRegionalHostname returns the details of a specific regional hostname. // // API reference: https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api -func (api *API) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, regionalHostname RegionalHostname) (RegionalHostname, error) { +func (api *API) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *ResourceContainer, params UpdateDataLocalizationRegionalHostnameParams) (RegionalHostname, error) { if rc.Level != ZoneRouteLevel { return RegionalHostname{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level) } @@ -144,13 +155,8 @@ func (api *API) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc * return RegionalHostname{}, ErrMissingZoneID } - uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames/%s", rc.Identifier, regionalHostname.Hostname) + uri := fmt.Sprintf("/zones/%s/addressing/regional_hostnames/%s", rc.Identifier, params.Hostname) - params := struct { - RegionKey string `json:"region_key"` - }{ - RegionKey: regionalHostname.RegionKey, - } res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return RegionalHostname{}, err diff --git a/regional_hostnames_test.go b/regional_hostnames_test.go index ee070171a1..0391d3ccbc 100644 --- a/regional_hostnames_test.go +++ b/regional_hostnames_test.go @@ -19,7 +19,7 @@ func TestListRegions(t *testing.T) { 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.Fprint(w, `{ + fmt.Fprintf(w, `{ "result": [ { "key": "ca", @@ -49,7 +49,7 @@ func TestListRegions(t *testing.T) { }, } - actual, err := client.ListDataLocalizationRegions(context.Background(), AccountIdentifier(testAccountID)) + actual, err := client.ListDataLocalizationRegions(context.Background(), AccountIdentifier(testAccountID), ListDataLocalizationRegionsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -62,7 +62,7 @@ func TestListRegionalHostnames(t *testing.T) { 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.Fprint(w, fmt.Sprintf(`{ + fmt.Fprintf(w, `{ "result": [ { "hostname": "%s", @@ -73,7 +73,7 @@ func TestListRegionalHostnames(t *testing.T) { "success": true, "errors": [], "messages": [] - }`, regionalHostname)) + }`, regionalHostname) } mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) @@ -87,7 +87,7 @@ func TestListRegionalHostnames(t *testing.T) { }, } - actual, err := client.ListDataLocalizationRegionalHostnames(context.Background(), ZoneIdentifier(testZoneID)) + actual, err := client.ListDataLocalizationRegionalHostnames(context.Background(), ZoneIdentifier(testZoneID), ListDataLocalizationRegionalHostnamesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -100,7 +100,7 @@ func TestCreateRegionalHostname(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, fmt.Sprintf(`{ + fmt.Fprintf(w, `{ "result": { "hostname": "%s", "region_key": "ca", @@ -109,17 +109,22 @@ func TestCreateRegionalHostname(t *testing.T) { "success": true, "errors": [], "messages": [] - }`, regionalHostname)) + }`, regionalHostname) } mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames", handler) + params := CreateDataLocalizationRegionalHostnameParams{ + RegionKey: "ca", + Hostname: regionalHostname, + } + want := RegionalHostname{ RegionKey: "ca", Hostname: regionalHostname, } - actual, err := client.CreateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) + actual, err := client.CreateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), params) createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") want.CreatedOn = &createdOn if assert.NoError(t, err) { @@ -134,7 +139,7 @@ func TestGetRegionalHostname(t *testing.T) { 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.Fprint(w, fmt.Sprintf(`{ + fmt.Fprintf(w, `{ "result": { "hostname": "%s", "region_key": "ca", @@ -143,7 +148,7 @@ func TestGetRegionalHostname(t *testing.T) { "success": true, "errors": [], "messages": [] - }`, regionalHostname)) + }`, regionalHostname) } mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+regionalHostname, handler) @@ -167,7 +172,7 @@ func TestUpdateRegionalHostname(t *testing.T) { 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.Fprint(w, fmt.Sprintf(`{ + fmt.Fprintf(w, `{ "result": { "hostname": "%s", "region_key": "eu", @@ -176,16 +181,22 @@ func TestUpdateRegionalHostname(t *testing.T) { "success": true, "errors": [], "messages": [] - }`, regionalHostname)) + }`, regionalHostname) + } + + params := UpdateDataLocalizationRegionalHostnameParams{ + RegionKey: "eu", + Hostname: regionalHostname, } want := RegionalHostname{ RegionKey: "eu", Hostname: regionalHostname, } + mux.HandleFunc("/zones/"+testZoneID+"/addressing/regional_hostnames/"+regionalHostname, handler) - actual, err := client.UpdateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), want) + actual, err := client.UpdateDataLocalizationRegionalHostname(context.Background(), ZoneIdentifier(testZoneID), params) createdOn, _ := time.Parse(time.RFC3339, "2023-01-14T00:47:57.060267Z") want.CreatedOn = &createdOn if assert.NoError(t, err) { From 031061a4e8f96d5ac409312a70af69a9acc74706 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 19 Apr 2023 02:55:08 +0000 Subject: [PATCH 320/370] Update CHANGELOG.md for #1270 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73c8a2b73..e15ad21d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * access_application: Add `path_cookie_attribute` app setting ([#1223](https://github.com/cloudflare/cloudflare-go/issues/1223)) +* data localization: add support for regional hostnames API ([#1270](https://github.com/cloudflare/cloudflare-go/issues/1270)) * dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266)) * turnstile: add support for turnstile ([#1267](https://github.com/cloudflare/cloudflare-go/issues/1267)) From f72d69ae3bf09f217f29aa3eddb5d4fb04bd1b25 Mon Sep 17 00:00:00 2001 From: Yecheng Fu Date: Fri, 21 Apr 2023 20:12:27 +0800 Subject: [PATCH 321/370] certificate_packs: add `Status` field This field is essential for automating tasks related to certificate packs. For instance, upon creating a certificate pack, the validation process must be repeatedly initiated until the status transitions to active. --- .changelog/1271.txt | 1 + certificate_packs.go | 1 + certificate_packs_test.go | 2 ++ 3 files changed, 4 insertions(+) create mode 100644 .changelog/1271.txt diff --git a/.changelog/1271.txt b/.changelog/1271.txt new file mode 100644 index 0000000000..1d2f5841cb --- /dev/null +++ b/.changelog/1271.txt @@ -0,0 +1 @@ +certificate_packs: add Status field to indicate the status of certificate pack diff --git a/certificate_packs.go b/certificate_packs.go index cf499de936..802ed5dfe3 100644 --- a/certificate_packs.go +++ b/certificate_packs.go @@ -38,6 +38,7 @@ type CertificatePack struct { Hosts []string `json:"hosts"` Certificates []CertificatePackCertificate `json:"certificates"` PrimaryCertificate string `json:"primary_certificate"` + Status string `json:"status"` ValidationRecords []SSLValidationRecord `json:"validation_records,omitempty"` ValidationErrors []SSLValidationError `json:"validation_errors,omitempty"` ValidationMethod string `json:"validation_method"` diff --git a/certificate_packs_test.go b/certificate_packs_test.go index 07aece7c01..6dc9758247 100644 --- a/certificate_packs_test.go +++ b/certificate_packs_test.go @@ -42,6 +42,7 @@ var ( ID: "3822ff90-ea29-44df-9e55-21300bb9419b", Type: "advanced", Hosts: []string{"example.com", "*.example.com", "www.example.com"}, + Status: "initializing", ValidationMethod: "txt", ValidityDays: 90, CertificateAuthority: "lets_encrypt", @@ -244,6 +245,7 @@ func TestRestartAdvancedCertificateValidation(t *testing.T) { ID: "3822ff90-ea29-44df-9e55-21300bb9419b", Type: "advanced", Hosts: []string{"example.com", "*.example.com", "www.example.com"}, + Status: "initializing", ValidityDays: 365, ValidationMethod: "txt", CertificateAuthority: "lets_encrypt", From 1e9c7379316a38ce0aec03b39e3bdd1bce242960 Mon Sep 17 00:00:00 2001 From: Mike Eves Date: Fri, 21 Apr 2023 15:01:44 +0100 Subject: [PATCH 322/370] Add new fields for max upload params --- logpush.go | 29 ++++++++++++++++------------- logpush_test.go | 18 +++++++++++------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/logpush.go b/logpush.go index fbb5354f11..8b3a70cb1a 100644 --- a/logpush.go +++ b/logpush.go @@ -11,19 +11,22 @@ import ( // LogpushJob describes a Logpush job. type LogpushJob struct { - ID int `json:"id,omitempty"` - Dataset string `json:"dataset"` - Enabled bool `json:"enabled"` - Kind string `json:"kind,omitempty"` - Name string `json:"name"` - LogpullOptions string `json:"logpull_options"` - DestinationConf string `json:"destination_conf"` - OwnershipChallenge string `json:"ownership_challenge,omitempty"` - LastComplete *time.Time `json:"last_complete,omitempty"` - LastError *time.Time `json:"last_error,omitempty"` - ErrorMessage string `json:"error_message,omitempty"` - Frequency string `json:"frequency,omitempty"` - Filter *LogpushJobFilters `json:"filter,omitempty"` + ID int `json:"id,omitempty"` + Dataset string `json:"dataset"` + Enabled bool `json:"enabled"` + Kind string `json:"kind,omitempty"` + Name string `json:"name"` + LogpullOptions string `json:"logpull_options"` + DestinationConf string `json:"destination_conf"` + OwnershipChallenge string `json:"ownership_challenge,omitempty"` + LastComplete *time.Time `json:"last_complete,omitempty"` + LastError *time.Time `json:"last_error,omitempty"` + ErrorMessage string `json:"error_message,omitempty"` + Frequency string `json:"frequency,omitempty"` + Filter *LogpushJobFilters `json:"filter,omitempty"` + MaxUploadBytes int `json:"max_upload_bytes,omitempty"` + MaxUploadRecords int `json:"max_upload_records,omitempty"` + MaxUploadIntervalSeconds int `json:"max_upload_interval_seconds,omitempty"` } type LogpushJobFilters struct { diff --git a/logpush_test.go b/logpush_test.go index dea1e82deb..c68e3b18b7 100644 --- a/logpush_test.go +++ b/logpush_test.go @@ -28,7 +28,8 @@ const ( "last_complete": "%[2]s", "last_error": "%[2]s", "error_message": "test", - "frequency": "high" + "frequency": "high", + "max_upload_bytes": 5000000 } ` serverEdgeLogpushJobDescription = `{ @@ -72,6 +73,7 @@ var ( LastError: &testLogpushTimestamp, ErrorMessage: "test", Frequency: "high", + MaxUploadBytes: 5000000, } expectedEdgeLogpushJobStruct = LogpushJob{ ID: jobID, @@ -177,18 +179,20 @@ func TestCreateLogpushJob(t *testing.T) { }{ "core logpush job": { newJob: LogpushJob{ - Dataset: "http_requests", - Enabled: false, - Name: "example.com", - LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp×tamps=rfc3339", - DestinationConf: "s3://mybucket/logs?region=us-west-2", + Dataset: "http_requests", + Enabled: false, + Name: "example.com", + LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp×tamps=rfc3339", + DestinationConf: "s3://mybucket/logs?region=us-west-2", + MaxUploadRecords: 1000, }, payload: `{ "dataset": "http_requests", "enabled":false, "name":"example.com", "logpull_options":"fields=RayID,ClientIP,EdgeStartTimestamp×tamps=rfc3339", - "destination_conf":"s3://mybucket/logs?region=us-west-2" + "destination_conf":"s3://mybucket/logs?region=us-west-2", + "max_upload_records": 1000 }`, result: serverLogpushJobDescription, want: expectedLogpushJobStruct, From 1773aea69df20ef50bfacf628c81483f635761ce Mon Sep 17 00:00:00 2001 From: Mike Eves Date: Fri, 21 Apr 2023 15:17:25 +0100 Subject: [PATCH 323/370] Add changelog entry --- .changelog/1272.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1272.txt diff --git a/.changelog/1272.txt b/.changelog/1272.txt new file mode 100644 index 0000000000..dfa3888383 --- /dev/null +++ b/.changelog/1272.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +logpush: add support for max upload parameters +``` From 1c9400993da35fda1efcf923c7cd8bba11a1a32c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 24 Apr 2023 09:26:07 +1000 Subject: [PATCH 324/370] Update 1271.txt --- .changelog/1271.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changelog/1271.txt b/.changelog/1271.txt index 1d2f5841cb..664212a1e7 100644 --- a/.changelog/1271.txt +++ b/.changelog/1271.txt @@ -1 +1,3 @@ -certificate_packs: add Status field to indicate the status of certificate pack +```release-note:enhancement +certificate_packs: add `Status` field to indicate the status of certificate pack +``` From c57d46fbb757211f2ca326ca9090f451128fe80a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Sun, 23 Apr 2023 23:32:30 +0000 Subject: [PATCH 325/370] Update CHANGELOG.md for #1272 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e15ad21d15..1cd89fa903 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ ENHANCEMENTS: * access_application: Add `path_cookie_attribute` app setting ([#1223](https://github.com/cloudflare/cloudflare-go/issues/1223)) +* certificate_packs: add `Status` field to indicate the status of certificate pack ([#1271](https://github.com/cloudflare/cloudflare-go/issues/1271)) * data localization: add support for regional hostnames API ([#1270](https://github.com/cloudflare/cloudflare-go/issues/1270)) * dns: add support for importing and exporting DNS records using BIND file configurations ([#1266](https://github.com/cloudflare/cloudflare-go/issues/1266)) +* logpush: add support for max upload parameters ([#1272](https://github.com/cloudflare/cloudflare-go/issues/1272)) * turnstile: add support for turnstile ([#1267](https://github.com/cloudflare/cloudflare-go/issues/1267)) DEPENDENCIES: From 5eb9269868f5ce0b2dc4cada6fee03d30cbb8f66 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 26 Apr 2023 10:28:10 +1000 Subject: [PATCH 326/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd89fa903..6962e889e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.66.0 (Unreleased) +## 0.67.0 (Unreleased) + +## 0.66.0 (26th April, 2023) ENHANCEMENTS: From c1db7172b4ca89a50ae87a1cf8f6bde03662ec11 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Tue, 25 Apr 2023 20:54:08 -0400 Subject: [PATCH 327/370] Fix lint issue --- r2_bucket.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/r2_bucket.go b/r2_bucket.go index c4c09d1672..046438f094 100644 --- a/r2_bucket.go +++ b/r2_bucket.go @@ -87,6 +87,9 @@ func (api *API) CreateR2Bucket(ctx context.Context, rc *ResourceContainer, param uri := fmt.Sprintf("/accounts/%s/r2/buckets", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return R2Bucket{}, err + } var r2BucketResponse R2BucketResponse err = json.Unmarshal(res, &r2BucketResponse) From 182aab5d22c6cce322134b9b6d26d87dfd456ed7 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 26 Apr 2023 10:59:52 +0000 Subject: [PATCH 328/370] Update CHANGELOG.md for #1246 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6962e889e5..e6622f0abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.67.0 (Unreleased) +NOTES: + +* dns_firewall: The `OriginIPs` field has been renamed to `UpstreamIPs`. ([#1246](https://github.com/cloudflare/cloudflare-go/issues/1246)) + ## 0.66.0 (26th April, 2023) ENHANCEMENTS: From 4cf0ac7c525cc005ee0700f11cbfd44120a5c4d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 16:56:59 +0000 Subject: [PATCH 329/370] build(deps): bump github.com/urfave/cli/v2 from 2.25.1 to 2.25.3 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.1 to 2.25.3. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.25.1...v2.25.3) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1d9563fd56..6526788fbd 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( 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 + github.com/urfave/cli/v2 v2.25.3 golang.org/x/net v0.9.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index 73c95cbd5d..ab53d2ccc1 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/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= From 77f8b93b48b63811bcb009e3af7b9db6d80a7853 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 1 May 2023 16:57:12 +0000 Subject: [PATCH 330/370] add CHANGELOG for #1274 --- .changelog/1274.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1274.txt diff --git a/.changelog/1274.txt b/.changelog/1274.txt new file mode 100644 index 0000000000..51deac303d --- /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 +``` From 20a45ed21f8c44d188ac92d0ae08314a6b8f0c50 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 1 May 2023 19:59:27 +0000 Subject: [PATCH 331/370] Update CHANGELOG.md for #1274 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6622f0abf..8fe38a2859 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ NOTES: * dns_firewall: The `OriginIPs` field has been renamed to `UpstreamIPs`. ([#1246](https://github.com/cloudflare/cloudflare-go/issues/1246)) +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)) + ## 0.66.0 (26th April, 2023) ENHANCEMENTS: From 2af8e90c4677f29a4946981d910de617bfd3e386 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 2 May 2023 19:34:02 +0000 Subject: [PATCH 332/370] Update CHANGELOG.md for #1268 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fe38a2859..ca736cdde0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ 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)) + 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)) From 288fd1b077341ed98591b2096333afbf8c034149 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 3 May 2023 11:52:42 +1000 Subject: [PATCH 333/370] fix outputs passing between jobs --- .github/workflows/milestone-closed.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/milestone-closed.yml b/.github/workflows/milestone-closed.yml index 112a514d72..c29167a0d7 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[@]}" From 81239df7a66b7ad43584a316347f526a02b3893c Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 4 May 2023 16:06:37 +1000 Subject: [PATCH 334/370] rulesets: allow `PreserveQueryString` to be nullable --- .changelog/1275.txt | 3 +++ rulesets.go | 2 +- rulesets_test.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .changelog/1275.txt diff --git a/.changelog/1275.txt b/.changelog/1275.txt new file mode 100644 index 0000000000..718b80065f --- /dev/null +++ b/.changelog/1275.txt @@ -0,0 +1,3 @@ +```release-note:bug +rulesets: allow `PreserveQueryString` to be nullable +``` diff --git a/rulesets.go b/rulesets.go index 8110d0206a..72a7a4f3bf 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 c126c72394..52e9ed88ce 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", From 1633ac1d54993e80df3fa35678f4464ec809b72f Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 4 May 2023 21:57:02 +0000 Subject: [PATCH 335/370] Update CHANGELOG.md for #1275 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca736cdde0..37010ebae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ ENHANCEMENTS: * device_posture_rule: add input fields tanium, intune and kolide ([#1268](https://github.com/cloudflare/cloudflare-go/issues/1268)) +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)) From e57f4d7ed9e62341c352e3308b16178bd87df1ed Mon Sep 17 00:00:00 2001 From: Piper McCorkle Date: Thu, 4 May 2023 16:03:56 -0500 Subject: [PATCH 336/370] WR-1279 add waiting room zone-level settings --- .changelog/1276.txt | 3 ++ waiting_room.go | 85 ++++++++++++++++++++++++++++++++++++++++ waiting_room_test.go | 93 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 .changelog/1276.txt diff --git a/.changelog/1276.txt b/.changelog/1276.txt new file mode 100644 index 0000000000..713898c8db --- /dev/null +++ b/.changelog/1276.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +waiting_room: add support for zone-level settings +``` diff --git a/waiting_room.go b/waiting_room.go index a60b5028e3..8f49e0d3c8 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 +// ChangeWaitingRoomSettings 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 902510305d..057789906b 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) + } +} From 35080509b9204d1ff057fcf87d0c88806a8d9d9e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 8 May 2023 10:56:55 +1000 Subject: [PATCH 337/370] update UpdateWaitingRoomSettings comment --- waiting_room.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waiting_room.go b/waiting_room.go index 8f49e0d3c8..737e49dc49 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -597,7 +597,7 @@ type UpdateWaitingRoomSettingsParams struct { } // UpdateWaitingRoomSettings lets you replace all zone-level Waiting Room settings. This is in contrast to -// ChangeWaitingRoomSettings which lets you change individual settings. +// 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) { From 9388783618dc500a0a8a942c407104c81de77d9a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 8 May 2023 01:01:10 +0000 Subject: [PATCH 338/370] Update CHANGELOG.md for #1276 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37010ebae0..2077a5c037 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ NOTES: 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: From 536b53c542440e7dfb251d2fd0e0cc23904aa7a3 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Tue, 9 May 2023 02:40:29 +0100 Subject: [PATCH 339/370] Add Placement to Pages & Workers --- .changelog/1279.txt | 7 +++++ pages_project.go | 2 ++ pages_project_test.go | 17 +++++++++++- workers.go | 31 ++++++++++++++++----- workers_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 .changelog/1279.txt diff --git a/.changelog/1279.txt b/.changelog/1279.txt new file mode 100644 index 0000000000..08cd4cab05 --- /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/pages_project.go b/pages_project.go index 3177a8e0f8..4cbbb46497 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 91671a5d5c..32d09ab570 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/workers.go b/workers.go index 0a983bdc3c..b934218e69 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 348abed24a..8492cdee06 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) + }) +} From eecf0fbec01149f8a2c78dec64fc2330b3b6ed85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 May 2023 16:56:38 +0000 Subject: [PATCH 340/370] build(deps): bump golang.org/x/net from 0.9.0 to 0.10.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.9.0 to 0.10.0. - [Commits](https://github.com/golang/net/compare/v0.9.0...v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 6526788fbd..7ace5d4098 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.3 - golang.org/x/net v0.9.0 + golang.org/x/net v0.10.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index ab53d2ccc1..b49c19aff2 100644 --- a/go.sum +++ b/go.sum @@ -63,15 +63,15 @@ 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= From 4de6586165e6eade7ed91c51485b8c1ef620c5fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 May 2023 16:56:58 +0000 Subject: [PATCH 341/370] add CHANGELOG for #1280 --- .changelog/1280.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1280.txt diff --git a/.changelog/1280.txt b/.changelog/1280.txt new file mode 100644 index 0000000000..7f690ce831 --- /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 +``` From 78e9cc91525e656c0258052978788ee4effb0f8c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 9 May 2023 20:21:13 +0000 Subject: [PATCH 342/370] Update CHANGELOG.md for #1280 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2077a5c037..645d11f7eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ BUG FIXES: 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) From 10cc0fdc82ef5308226a1273f1f769f0de92c7eb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 10 May 2023 16:00:59 +1000 Subject: [PATCH 343/370] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 645d11f7eb..1a334a79c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.67.0 (Unreleased) +## 0.68.0 (Unreleased) + +## 0.67.0 (May 10th, 2023) NOTES: From f047e5560a5c76484ea329b8ee25f2d477f2d7ec Mon Sep 17 00:00:00 2001 From: Jean-Francois Chevrette Date: Mon, 8 May 2023 19:31:43 -0400 Subject: [PATCH 344/370] add support for cache reserve --- .changelog/1278.txt | 3 ++ zone_cache_reserve.go | 73 +++++++++++++++++++++++++++++++++ zone_cache_reserve_test.go | 82 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 .changelog/1278.txt create mode 100644 zone_cache_reserve.go create mode 100644 zone_cache_reserve_test.go diff --git a/.changelog/1278.txt b/.changelog/1278.txt new file mode 100644 index 0000000000..cc338c3823 --- /dev/null +++ b/.changelog/1278.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +zone: Added `GetZoneCacheReserve` and `UpdateZoneCacheReserve` to allow setting Cache Reserve for a zone. +``` diff --git a/zone_cache_reserve.go b/zone_cache_reserve.go new file mode 100644 index 0000000000..c1f119e252 --- /dev/null +++ b/zone_cache_reserve.go @@ -0,0 +1,73 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +// ZoneCacheReserve is the structure of the API object for the +// cache reserve setting. +type ZoneCacheReserve 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 ZoneCacheReserve `json:"result"` + Response +} + +type updateZoneCacheReserveRequest struct { + Value string `json:"value"` +} + +type zoneCacheReserveSingleResponse struct { + Response + Result ZoneCacheReserve `json:"result"` +} + +// GetZoneCacheReserve 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) GetZoneCacheReserve(ctx context.Context, zoneID string) (ZoneCacheReserve, error) { + uri := fmt.Sprintf("/zones/%s/cache/cache_reserve", zoneID) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return ZoneCacheReserve{}, err + } + + var cacheReserveDetailsResponse CacheReserveDetailsResponse + err = json.Unmarshal(res, &cacheReserveDetailsResponse) + if err != nil { + return ZoneCacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return cacheReserveDetailsResponse.Result, nil +} + +// UpdateZoneCacheReserve 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) UpdateZoneCacheReserve(ctx context.Context, zoneID string, value string) (ZoneCacheReserve, error) { + uri := fmt.Sprintf("/zones/%s/cache/cache_reserve", zoneID) + + updateReq := &updateZoneCacheReserveRequest{Value: value} + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, updateReq) + if err != nil { + return ZoneCacheReserve{}, err + } + + response := &zoneCacheReserveSingleResponse{} + err = json.Unmarshal(res, &response) + if err != nil { + return ZoneCacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} diff --git a/zone_cache_reserve_test.go b/zone_cache_reserve_test.go new file mode 100644 index 0000000000..ee4b720532 --- /dev/null +++ b/zone_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 TestZoneCacheReserve(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 := ZoneCacheReserve{ + ID: "cache_reserve", + Value: "on", + ModifiedOn: cacheReserveTimestamp, + } + + actual, err := client.GetZoneCacheReserve(context.Background(), "01a7362d577a6c3019a474fd6f485823") + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateZoneCacheReserve(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 := ZoneCacheReserve{ + ID: "cache_reserve", + Value: "off", + ModifiedOn: cacheReserveTimestamp, + } + + actual, err := client.UpdateZoneCacheReserve(context.Background(), "01a7362d577a6c3019a474fd6f485823", "off") + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From 5e5c2b2ccb3db167dc344463522a6af031d9ba9a Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 15 May 2023 10:24:23 +1000 Subject: [PATCH 345/370] use experimental method signatures --- cache_reserve.go | 86 +++++++++++++++++++ ...e_reserve_test.go => cache_reserve_test.go | 12 +-- zone_cache_reserve.go | 73 ---------------- 3 files changed, 92 insertions(+), 79 deletions(-) create mode 100644 cache_reserve.go rename zone_cache_reserve_test.go => cache_reserve_test.go (79%) delete mode 100644 zone_cache_reserve.go diff --git a/cache_reserve.go b/cache_reserve.go new file mode 100644 index 0000000000..029ed6cfe9 --- /dev/null +++ b/cache_reserve.go @@ -0,0 +1,86 @@ +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 updateCacheReserveRequest struct { + Value string `json:"value"` +} + +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/zone_cache_reserve_test.go b/cache_reserve_test.go similarity index 79% rename from zone_cache_reserve_test.go rename to cache_reserve_test.go index ee4b720532..4434c9cf28 100644 --- a/zone_cache_reserve_test.go +++ b/cache_reserve_test.go @@ -13,7 +13,7 @@ import ( var cacheReserveTimestampString = "2019-02-20T22:37:07.107449Z" var cacheReserveTimestamp, _ = time.Parse(time.RFC3339Nano, cacheReserveTimestampString) -func TestZoneCacheReserve(t *testing.T) { +func TestCacheReserve(t *testing.T) { setup() defer teardown() @@ -34,20 +34,20 @@ func TestZoneCacheReserve(t *testing.T) { } mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/cache_reserve", handler) - want := ZoneCacheReserve{ + want := CacheReserve{ ID: "cache_reserve", Value: "on", ModifiedOn: cacheReserveTimestamp, } - actual, err := client.GetZoneCacheReserve(context.Background(), "01a7362d577a6c3019a474fd6f485823") + actual, err := client.GetCacheReserve(context.Background(), ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), GetCacheReserveParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestUpdateZoneCacheReserve(t *testing.T) { +func TestUpdateCacheReserve(t *testing.T) { setup() defer teardown() @@ -68,13 +68,13 @@ func TestUpdateZoneCacheReserve(t *testing.T) { } mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/cache_reserve", handler) - want := ZoneCacheReserve{ + want := CacheReserve{ ID: "cache_reserve", Value: "off", ModifiedOn: cacheReserveTimestamp, } - actual, err := client.UpdateZoneCacheReserve(context.Background(), "01a7362d577a6c3019a474fd6f485823", "off") + actual, err := client.UpdateCacheReserve(context.Background(), ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), UpdateCacheReserveParams{Value: "off"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) diff --git a/zone_cache_reserve.go b/zone_cache_reserve.go deleted file mode 100644 index c1f119e252..0000000000 --- a/zone_cache_reserve.go +++ /dev/null @@ -1,73 +0,0 @@ -package cloudflare - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "time" -) - -// ZoneCacheReserve is the structure of the API object for the -// cache reserve setting. -type ZoneCacheReserve 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 ZoneCacheReserve `json:"result"` - Response -} - -type updateZoneCacheReserveRequest struct { - Value string `json:"value"` -} - -type zoneCacheReserveSingleResponse struct { - Response - Result ZoneCacheReserve `json:"result"` -} - -// GetZoneCacheReserve 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) GetZoneCacheReserve(ctx context.Context, zoneID string) (ZoneCacheReserve, error) { - uri := fmt.Sprintf("/zones/%s/cache/cache_reserve", zoneID) - - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return ZoneCacheReserve{}, err - } - - var cacheReserveDetailsResponse CacheReserveDetailsResponse - err = json.Unmarshal(res, &cacheReserveDetailsResponse) - if err != nil { - return ZoneCacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return cacheReserveDetailsResponse.Result, nil -} - -// UpdateZoneCacheReserve 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) UpdateZoneCacheReserve(ctx context.Context, zoneID string, value string) (ZoneCacheReserve, error) { - uri := fmt.Sprintf("/zones/%s/cache/cache_reserve", zoneID) - - updateReq := &updateZoneCacheReserveRequest{Value: value} - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, updateReq) - if err != nil { - return ZoneCacheReserve{}, err - } - - response := &zoneCacheReserveSingleResponse{} - err = json.Unmarshal(res, &response) - if err != nil { - return ZoneCacheReserve{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - - return response.Result, nil -} From 0a42124737f9108f817b47d77f0721c6f847e40b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 15 May 2023 10:29:41 +1000 Subject: [PATCH 346/370] fix changelog message --- .changelog/1278.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1278.txt b/.changelog/1278.txt index cc338c3823..64e605cf14 100644 --- a/.changelog/1278.txt +++ b/.changelog/1278.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -zone: Added `GetZoneCacheReserve` and `UpdateZoneCacheReserve` to allow setting Cache Reserve for a zone. +zone: Added `GetCacheReserve` and `UpdateacheReserve` to allow setting Cache Reserve for a zone. ``` From cf0ce93b346736f32dacc47b8bafc6a30945c7c0 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 15 May 2023 10:34:08 +1000 Subject: [PATCH 347/370] remove unused struct --- cache_reserve.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cache_reserve.go b/cache_reserve.go index 029ed6cfe9..a62a6144ab 100644 --- a/cache_reserve.go +++ b/cache_reserve.go @@ -23,10 +23,6 @@ type CacheReserveDetailsResponse struct { Response } -type updateCacheReserveRequest struct { - Value string `json:"value"` -} - type zoneCacheReserveSingleResponse struct { Response Result CacheReserve `json:"result"` From f9689774f03b5bb6824b6ea6a2576e706b153f68 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 15 May 2023 00:39:28 +0000 Subject: [PATCH 348/370] Update CHANGELOG.md for #1278 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a334a79c2..5b16b321d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.68.0 (Unreleased) +ENHANCEMENTS: + +* zone: Added `GetCacheReserve` and `UpdateacheReserve` to allow setting Cache Reserve for a zone. ([#1278](https://github.com/cloudflare/cloudflare-go/issues/1278)) + ## 0.67.0 (May 10th, 2023) NOTES: From d3c1c1c29810c59119fe62be9c8b774e972dd61f Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 17 May 2023 00:39:16 +0000 Subject: [PATCH 349/370] Update CHANGELOG.md for #1279 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b16b321d2..fea29b6d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ 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)) ## 0.67.0 (May 10th, 2023) From 41984cb1bb509885efdc874f0f0bbeec24186969 Mon Sep 17 00:00:00 2001 From: Maxime Guerreiro Date: Wed, 17 May 2023 04:47:13 +0200 Subject: [PATCH 350/370] Fix UpdateTurnstileWidget The request body must not include sitekey/secret, but did. This fixes it. --- .changelog/1284.txt | 3 +++ turnstile.go | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 .changelog/1284.txt diff --git a/.changelog/1284.txt b/.changelog/1284.txt new file mode 100644 index 0000000000..7485c1c5e8 --- /dev/null +++ b/.changelog/1284.txt @@ -0,0 +1,3 @@ +```release-note:bug +turnstile: Fix sitekey/secret being sent in update request body +``` diff --git a/turnstile.go b/turnstile.go index 565a36e6ec..9c8ac8f428 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"` From 2828acbdbe645d7a2076ec74cb06876189b69df4 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 17 May 2023 12:54:46 +1000 Subject: [PATCH 351/370] update CHANGELOG entry --- .changelog/1284.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1284.txt b/.changelog/1284.txt index 7485c1c5e8..0da545211a 100644 --- a/.changelog/1284.txt +++ b/.changelog/1284.txt @@ -1,3 +1,3 @@ ```release-note:bug -turnstile: Fix sitekey/secret being sent in update request body +turnstile: remove `SiteKey`/`Secret` being sent in update request body ``` From 707134ca0ec9b595b74f1fd6ecf0c035543ab7f7 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 17 May 2023 02:55:32 +0000 Subject: [PATCH 352/370] Update CHANGELOG.md for #1284 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fea29b6d5b..9564c0c371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ ENHANCEMENTS: * 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`/`Secret` being sent in update request body ([#1284](https://github.com/cloudflare/cloudflare-go/issues/1284)) + ## 0.67.0 (May 10th, 2023) NOTES: From 62eaa9ae6d5482aa8b63f3c57a4da62371e74f09 Mon Sep 17 00:00:00 2001 From: Maxime Guerreiro Date: Wed, 17 May 2023 05:03:39 +0200 Subject: [PATCH 353/370] Fix RotateTurnstileWidget Don't send the Sitekey in the request body. --- .changelog/1285.txt | 3 +++ turnstile.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .changelog/1285.txt diff --git a/.changelog/1285.txt b/.changelog/1285.txt new file mode 100644 index 0000000000..75140aed1b --- /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/turnstile.go b/turnstile.go index 9c8ac8f428..84c0bdca5d 100644 --- a/turnstile.go +++ b/turnstile.go @@ -61,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. From 8c3be80d3d3e82ffa2a2ba41449e635bd6ef4fd2 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 17 May 2023 03:11:10 +0000 Subject: [PATCH 354/370] Update CHANGELOG.md for #1285 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9564c0c371..ea96447ee6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ENHANCEMENTS: 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)) ## 0.67.0 (May 10th, 2023) From bb6e7cc1aaacf1f1b2149ae03ad6526cef6d6491 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 18 May 2023 14:07:05 +1000 Subject: [PATCH 355/370] update PR requirements for cloudflare/api-schemas --- .github/PULL_REQUEST_TEMPLATE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 13e93599b2..b71eecf0ee 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/ From 0d963f7851a8fb8049e6786c4600819c77751323 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 16:56:41 +0000 Subject: [PATCH 356/370] build(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 7ace5d4098..f434285b59 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ 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/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 b49c19aff2..36dbcedcf4 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,14 +50,9 @@ 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/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= @@ -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= From 2db7944fcb35715a8f1e6d3656d0f4a0fd41f13e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 19 May 2023 16:56:56 +0000 Subject: [PATCH 357/370] add CHANGELOG for #1286 --- .changelog/1286.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1286.txt diff --git a/.changelog/1286.txt b/.changelog/1286.txt new file mode 100644 index 0000000000..380cc29730 --- /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 +``` From 870f6bdbfcc15a3463e69d1f9bedfaa3c9208608 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 19 May 2023 22:33:40 +0000 Subject: [PATCH 358/370] Update CHANGELOG.md for #1286 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea96447ee6..da71afec34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ 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: From feb7d3a89c03a20f30988957e63a1d4d8a7add79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 16:57:10 +0000 Subject: [PATCH 359/370] build(deps): bump dependabot/fetch-metadata from 1.4.0 to 1.5.0 Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dependabot-changelog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot-changelog.yml b/.github/workflows/dependabot-changelog.yml index 47348b419a..2afaac2ddb 100644 --- a/.github/workflows/dependabot-changelog.yml +++ b/.github/workflows/dependabot-changelog.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Fetch dependabot metadata id: dependabot-metadata - uses: dependabot/fetch-metadata@v1.4.0 + uses: dependabot/fetch-metadata@v1.5.0 - uses: actions/checkout@v3 - run: | gh pr checkout $PR_URL From 97e7c31aa255cbe99e9dbe3c3b36dfa4f58db458 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 22 May 2023 16:57:25 +0000 Subject: [PATCH 360/370] add CHANGELOG for #1287 --- .changelog/1287.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1287.txt diff --git a/.changelog/1287.txt b/.changelog/1287.txt new file mode 100644 index 0000000000..3e78c82109 --- /dev/null +++ b/.changelog/1287.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps dependabot/fetch-metadata from 1.4.0 to 1.5.0 +``` From 656b03b68238539dad9b1e2cd5f0f5c659d7d825 Mon Sep 17 00:00:00 2001 From: Paschal Obba Date: Mon, 22 May 2023 19:48:59 +0100 Subject: [PATCH 361/370] FW-5588: Add hostname and ASN lists --- .changelog/1288.txt | 3 + list.go | 12 ++ list_test.go | 366 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 381 insertions(+) create mode 100644 .changelog/1288.txt diff --git a/.changelog/1288.txt b/.changelog/1288.txt new file mode 100644 index 0000000000..7401823441 --- /dev/null +++ b/.changelog/1288.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +lists: add support for hostname and ASN lists. +``` \ No newline at end of file diff --git a/list.go b/list.go index 75e802fe1d..6cd9fe986b 100644 --- a/list.go +++ b/list.go @@ -14,6 +14,10 @@ const ( ListTypeIP = "ip" // ListTypeRedirect specifies a list containing redirects. ListTypeRedirect = "redirect" + // ListTypeHostname specifies a list containing hostnames. + ListTypeHostname = "hostname" + // ListTypeHostname specifies a list containing autonomous system numbers (ASNs). + ListTypeASN = "asn" ) // ListBulkOperation contains information about a Bulk Operation. @@ -47,11 +51,17 @@ type Redirect struct { PreservePathSuffix *bool `json:"preserve_path_suffix,omitempty"` } +type Hostname struct { + UrlHostname string `json:"url_hostname"` +} + // ListItem contains information about a single List Item. type ListItem struct { ID string `json:"id"` IP *string `json:"ip,omitempty"` Redirect *Redirect `json:"redirect,omitempty"` + Hostname *Hostname `json:"hostname,omitempty"` + ASN *uint32 `json:"asn,omitempty"` Comment string `json:"comment"` CreatedOn *time.Time `json:"created_on"` ModifiedOn *time.Time `json:"modified_on"` @@ -68,6 +78,8 @@ type ListCreateRequest struct { type ListItemCreateRequest struct { IP *string `json:"ip,omitempty"` Redirect *Redirect `json:"redirect,omitempty"` + Hostname *Hostname `json:"hostname,omitempty"` + ASN *uint32 `json:"asn,omitempty"` Comment string `json:"comment"` } diff --git a/list_test.go b/list_test.go index 9a73a0a8fd..0a622f8d1e 100644 --- a/list_test.go +++ b/list_test.go @@ -423,6 +423,117 @@ func TestListsItemsRedirect(t *testing.T) { } } +func TestListsItemsHostname(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.Fprint(w, `{ + "result": [ + { + "id": "0c0fc9fa937b11eaa1b71c4d701ab86e", + "hostname": { + "url_hostname": "cloudflare.com" + }, + "comment": "CF hostname", + "created_on": "2023-01-01T08:00:00Z", + "modified_on": "2023-01-10T14:00:00Z" + } + ], + "result_info": { + "cursors": { + "before": "xxx" + } + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/0c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + createdOn, _ := time.Parse(time.RFC3339, "2023-01-01T08:00:00Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2023-01-10T14:00:00Z") + + want := []ListItem{ + { + ID: "0c0fc9fa937b11eaa1b71c4d701ab86e", + Hostname: &Hostname{ + UrlHostname: "cloudflare.com", + }, + Comment: "CF hostname", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + }, + } + + actual, err := client.ListListItems( + context.Background(), + AccountIdentifier(testAccountID), + ListListItemsParams{ID: "0c0fc9fa937b11eaa1b71c4d701ab86e"}, + ) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestListsItemsASN(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.Fprint(w, `{ + "result": [ + { + "id": "0c0fc9fa937b11eaa1b71c4d701ab86e", + "asn": 3456, + "comment": "ASN", + "created_on": "2023-01-01T08:00:00Z", + "modified_on": "2023-01-10T14:00:00Z" + } + ], + "result_info": { + "cursors": { + "before": "xxx" + } + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/0c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + createdOn, _ := time.Parse(time.RFC3339, "2023-01-01T08:00:00Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2023-01-10T14:00:00Z") + + want := []ListItem{ + { + ID: "0c0fc9fa937b11eaa1b71c4d701ab86e", + ASN: Uint32Ptr(3456), + Comment: "ASN", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + }, + } + + actual, err := client.ListListItems( + context.Background(), + AccountIdentifier(testAccountID), + ListListItemsParams{ID: "0c0fc9fa937b11eaa1b71c4d701ab86e"}, + ) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestCreateListItemsIP(t *testing.T) { setup() defer teardown() @@ -507,6 +618,93 @@ func TestCreateListItemsRedirect(t *testing.T) { } } +func TestCreateListItemsHostname(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "result": { + "operation_id": "4da8780eeb215e6cb7f48dd981c4ea02" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/0c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + want := ListItemCreateResponse{} + want.Success = true + want.Errors = []ResponseInfo{} + want.Messages = []ResponseInfo{} + want.Result.OperationID = "4da8780eeb215e6cb7f48dd981c4ea02" + + actual, err := client.CreateListItemsAsync(context.Background(), AccountIdentifier(testAccountID), ListCreateItemsParams{ + ID: "0c0fc9fa937b11eaa1b71c4d701ab86e", + Items: []ListItemCreateRequest{{ + Hostname: &Hostname{ + UrlHostname: "3fonteinen.be", // ie. only match 3fonteinen.be + }, + Comment: "hostname 3F", + }, { + Hostname: &Hostname{ + UrlHostname: "*.cf.com", // ie. match all subdomains of cf.com but not cf.com + }, + Comment: "Hostname cf", + }, { + Hostname: &Hostname{ + UrlHostname: "*.abc.com", // ie. equivalent to match all subdomains of abc.com excluding abc.com + }, + Comment: "Hostname abc", + }}}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestCreateListItemsASN(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "result": { + "operation_id": "4da8780eeb215e6cb7f48dd981c4ea02" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/0c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + want := ListItemCreateResponse{} + want.Success = true + want.Errors = []ResponseInfo{} + want.Messages = []ResponseInfo{} + want.Result.OperationID = "4da8780eeb215e6cb7f48dd981c4ea02" + + actual, err := client.CreateListItemsAsync(context.Background(), AccountIdentifier(testAccountID), ListCreateItemsParams{ + ID: "0c0fc9fa937b11eaa1b71c4d701ab86e", + Items: []ListItemCreateRequest{{ + ASN: Uint32Ptr(458), + Comment: "ASN 458", + }, { + ASN: Uint32Ptr(789), + Comment: "ASN 789", + }}}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestReplaceListItemsIP(t *testing.T) { setup() defer teardown() @@ -591,6 +789,88 @@ func TestReplaceListItemsRedirect(t *testing.T) { } } +func TestReplaceListItemsHostname(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.Fprint(w, `{ + "result": { + "operation_id": "4da8780eeb215e6cb7f48dd981c4ea02" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/2c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + want := ListItemCreateResponse{} + want.Success = true + want.Errors = []ResponseInfo{} + want.Messages = []ResponseInfo{} + want.Result.OperationID = "4da8780eeb215e6cb7f48dd981c4ea02" + + actual, err := client.ReplaceListItemsAsync(context.Background(), AccountIdentifier(testAccountID), ListReplaceItemsParams{ + ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", + Items: []ListItemCreateRequest{{ + Hostname: &Hostname{ + UrlHostname: "3fonteinen.be", + }, + Comment: "hostname 3F", + }, { + Hostname: &Hostname{ + UrlHostname: "cf.com", + }, + Comment: "Hostname cf", + }}}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestReplaceListItemsASN(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.Fprint(w, `{ + "result": { + "operation_id": "4da8780eeb215e6cb7f48dd981c4ea02" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/2c0fc9fa937b11eaa1b71c4d701ab86e/items", handler) + + want := ListItemCreateResponse{} + want.Success = true + want.Errors = []ResponseInfo{} + want.Messages = []ResponseInfo{} + want.Result.OperationID = "4da8780eeb215e6cb7f48dd981c4ea02" + + actual, err := client.ReplaceListItemsAsync(context.Background(), AccountIdentifier(testAccountID), ListReplaceItemsParams{ + ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", + Items: []ListItemCreateRequest{{ + ASN: Uint32Ptr(4567), + Comment: "ASN 4567", + }, { + ASN: Uint32Ptr(8901), + Comment: "ASN 8901", + }}}) + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestDeleteListItems(t *testing.T) { setup() defer teardown() @@ -667,6 +947,92 @@ func TestGetListItemIP(t *testing.T) { } } +func TestGetListItemHostname(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.Fprint(w, `{ + "result": { + "id": "2c0fc9fa937b11eaa1b71c4d701ab86e", + "hostname": { + "url_hostname": "cloudflare.com" + }, + "comment": "CF Hostname", + "created_on": "2023-01-01T08:00:00Z", + "modified_on": "2023-01-10T14:00:00Z" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/2c0fc9fa937b11eaa1b71c4d701ab86e/items/"+ + "34b12448945f11eaa1b71c4d701ab86e", handler) + + createdOn, _ := time.Parse(time.RFC3339, "2023-01-01T08:00:00Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2023-01-10T14:00:00Z") + + want := ListItem{ + ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", + Hostname: &Hostname{ + UrlHostname: "cloudflare.com", + }, + Comment: "CF Hostname", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + } + + actual, err := client.GetListItem(context.Background(), AccountIdentifier(testAccountID), "2c0fc9fa937b11eaa1b71c4d701ab86e", "34b12448945f11eaa1b71c4d701ab86e") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestGetListItemASN(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.Fprint(w, `{ + "result": { + "id": "2c0fc9fa937b11eaa1b71c4d701ab86e", + "asn": 5555, + "comment": "asn 5555", + "created_on": "2023-01-01T08:00:00Z", + "modified_on": "2023-01-10T14:00:00Z" + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/rules/lists/2c0fc9fa937b11eaa1b71c4d701ab86e/items/"+ + "34b12448945f11eaa1b71c4d701ab86e", handler) + + createdOn, _ := time.Parse(time.RFC3339, "2023-01-01T08:00:00Z") + modifiedOn, _ := time.Parse(time.RFC3339, "2023-01-10T14:00:00Z") + + want := ListItem{ + ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", + ASN: Uint32Ptr(5555), + Comment: "asn 5555", + CreatedOn: &createdOn, + ModifiedOn: &modifiedOn, + } + + actual, err := client.GetListItem(context.Background(), AccountIdentifier(testAccountID), "2c0fc9fa937b11eaa1b71c4d701ab86e", "34b12448945f11eaa1b71c4d701ab86e") + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestPollListTimeout(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 0) defer cancel() From fb6c523a010a35bf5d8a6701177924a70cc1636a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 23 May 2023 01:46:02 +0000 Subject: [PATCH 362/370] Update CHANGELOG.md for #1287 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da71afec34..d1b41c8a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ BUG FIXES: DEPENDENCIES: +* deps: bumps dependabot/fetch-metadata from 1.4.0 to 1.5.0 ([#1287](https://github.com/cloudflare/cloudflare-go/issues/1287)) * 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) From 183f3d2de437f021fa3e9709716e6647aadfdc62 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 23 May 2023 05:15:33 +0000 Subject: [PATCH 363/370] Update CHANGELOG.md for #1288 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1b41c8a5a..a30a3f6866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* lists: add support for hostname and ASN lists. ([#1288](https://github.com/cloudflare/cloudflare-go/issues/1288)) * 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)) From 46538f0b570c81a4c80c654c271aff60c967f9f3 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 23 May 2023 05:16:32 +0000 Subject: [PATCH 364/370] Update CHANGELOG.md for #1265 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a30a3f6866..8596471114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,14 @@ ## 0.68.0 (Unreleased) +BREAKING CHANGES: + +* r2_bucket: change creation time from string to *time.Time ([#1265](https://github.com/cloudflare/cloudflare-go/issues/1265)) + ENHANCEMENTS: * lists: add support for hostname and ASN lists. ([#1288](https://github.com/cloudflare/cloudflare-go/issues/1288)) * pages: add support for Smart Placement. Added `Placement` in `PagesProjectDeploymentConfigEnvironment`. ([#1279](https://github.com/cloudflare/cloudflare-go/issues/1279)) +* r2_bucket: add support for getting a bucket ([#1265](https://github.com/cloudflare/cloudflare-go/issues/1265)) * 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)) From b9c7a0e41ad50c11332662cd666d4a5af2ccf710 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 23 May 2023 15:33:54 +1000 Subject: [PATCH 365/370] flarectl/dns: dereference priority pointer Closes #1282 --- .changelog/1289.txt | 3 +++ cmd/flarectl/zone.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/1289.txt diff --git a/.changelog/1289.txt b/.changelog/1289.txt new file mode 100644 index 0000000000..1c9e25e7aa --- /dev/null +++ b/.changelog/1289.txt @@ -0,0 +1,3 @@ +```release-note:bug +flarectl/dns: ensure MX priority value is dereferenced +``` diff --git a/cmd/flarectl/zone.go b/cmd/flarectl/zone.go index 19915185ce..5ab4e24b43 100644 --- a/cmd/flarectl/zone.go +++ b/cmd/flarectl/zone.go @@ -310,7 +310,7 @@ func zoneRecords(c *cli.Context) error { for _, r := range records { switch r.Type { case "MX": - r.Content = fmt.Sprintf("%d %s", r.Priority, r.Content) + r.Content = fmt.Sprintf("%d %s", *r.Priority, r.Content) case "SRV": dp := r.Data.(map[string]interface{}) r.Content = fmt.Sprintf("%.f %s", dp["priority"], r.Content) From d2592e40c6131c7ecb676522b00ee6f7d34d4358 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 23 May 2023 05:38:34 +0000 Subject: [PATCH 366/370] Update CHANGELOG.md for #1289 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8596471114..480c44098d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ENHANCEMENTS: BUG FIXES: +* flarectl/dns: ensure MX priority value is dereferenced ([#1289](https://github.com/cloudflare/cloudflare-go/issues/1289)) * 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)) From a97f7d7df495462d3dfef1231aca035a2c2443f0 Mon Sep 17 00:00:00 2001 From: Hamish Moffatt Date: Tue, 23 May 2023 21:28:15 +1000 Subject: [PATCH 367/370] Fix priority not being set when updating MX records --- dns.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns.go b/dns.go index 7e2ddb7c55..f05dfd1c6f 100644 --- a/dns.go +++ b/dns.go @@ -74,7 +74,7 @@ type UpdateDNSRecordParams struct { Content string `json:"content,omitempty"` Data interface{} `json:"data,omitempty"` // data for: SRV, LOC ID string `json:"-"` - Priority *uint16 `json:"-"` // internal use only + Priority *uint16 `json:"priority,omitempty` TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty"` Comment string `json:"comment"` From 77433eb6d28e74df1dd65f9aba20b9e1e3acba7c Mon Sep 17 00:00:00 2001 From: Hamish Moffatt Date: Tue, 23 May 2023 21:43:09 +1000 Subject: [PATCH 368/370] Add changelog entry for #1290 --- .changelog/1290.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1290.txt diff --git a/.changelog/1290.txt b/.changelog/1290.txt new file mode 100644 index 0000000000..70224ff8f5 --- /dev/null +++ b/.changelog/1290.txt @@ -0,0 +1,3 @@ +```release-note:bug +dns: fix MX record priority not set by UpdateDNSRecord +``` From f0f5570e7d2f4d8f934dfbc6f148271cd3d235d9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 24 May 2023 08:05:03 +1000 Subject: [PATCH 369/370] fix struct tag enclosure quotes --- dns.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dns.go b/dns.go index f05dfd1c6f..cee3b1d9de 100644 --- a/dns.go +++ b/dns.go @@ -74,7 +74,7 @@ type UpdateDNSRecordParams struct { Content string `json:"content,omitempty"` Data interface{} `json:"data,omitempty"` // data for: SRV, LOC ID string `json:"-"` - Priority *uint16 `json:"priority,omitempty` + Priority *uint16 `json:"priority,omitempty"` TTL int `json:"ttl,omitempty"` Proxied *bool `json:"proxied,omitempty"` Comment string `json:"comment"` From 8fba73c947d9a3358aabfd1fccef26a50f3db841 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 23 May 2023 22:14:22 +0000 Subject: [PATCH 370/370] Update CHANGELOG.md for #1290 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 480c44098d..8f820bfd3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ENHANCEMENTS: BUG FIXES: +* dns: fix MX record priority not set by UpdateDNSRecord ([#1290](https://github.com/cloudflare/cloudflare-go/issues/1290)) * flarectl/dns: ensure MX priority value is dereferenced ([#1289](https://github.com/cloudflare/cloudflare-go/issues/1289)) * 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))