From cd993259180bae89442cd6f3c4822784f1379669 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Thu, 6 Apr 2023 21:32:44 -0400 Subject: [PATCH 001/130] Add support for pages deployment auto pagination --- .changelog/1264.txt | 3 +++ pages_deployment.go | 56 ++++++++++++++++++++++++++-------------- pages_deployment_test.go | 6 ++--- pages_project_test.go | 2 -- 4 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 .changelog/1264.txt diff --git a/.changelog/1264.txt b/.changelog/1264.txt new file mode 100644 index 00000000000..63f7b89eacc --- /dev/null +++ b/.changelog/1264.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +pages_deployment: add support for auto pagination +``` \ No newline at end of file diff --git a/pages_deployment.go b/pages_deployment.go index 4eb5c8f2ab1..df91dbbccec 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -62,12 +62,6 @@ type pagesDeploymentResponse struct { Result PagesProjectDeployment `json:"result"` } -type pagesDeploymentStageLogsResponse struct { - Response - Result PagesDeploymentStageLogs `json:"result"` - ResultInfo `json:"result_info"` -} - type pagesDeploymentLogsResponse struct { Response Result PagesDeploymentLogs `json:"result"` @@ -77,7 +71,7 @@ type pagesDeploymentLogsResponse struct { type ListPagesDeploymentsParams struct { ProjectName string - PaginationOptions + ResultInfo } type GetPagesDeploymentInfoParams struct { @@ -122,33 +116,55 @@ type RollbackPagesDeploymentParams struct { var ( ErrMissingProjectName = errors.New("required missing project name") ErrMissingDeploymentID = errors.New("required missing deployment ID") - ErrMissingStageName = errors.New("required missing stage name") ) // ListPagesDeployments returns all deployments for a Pages project. // // API reference: https://api.cloudflare.com/#pages-deployment-get-deployments -func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, params ListPagesDeploymentsParams) ([]PagesProjectDeployment, ResultInfo, error) { +func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, params ListPagesDeploymentsParams) ([]PagesProjectDeployment, *ResultInfo, error) { if rc.Identifier == "" { - return []PagesProjectDeployment{}, ResultInfo{}, ErrMissingAccountID + return []PagesProjectDeployment{}, &ResultInfo{}, ErrMissingAccountID } if params.ProjectName == "" { - return []PagesProjectDeployment{}, ResultInfo{}, ErrMissingProjectName + return []PagesProjectDeployment{}, &ResultInfo{}, ErrMissingProjectName } - uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName), params.PaginationOptions) + autoPaginate := true + if params.PerPage >= 1 || params.Page >= 1 { + autoPaginate = false + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []PagesProjectDeployment{}, ResultInfo{}, err + if params.PerPage < 1 { + params.PerPage = 50 } - var r pagesDeploymentListResponse - err = json.Unmarshal(res, &r) - if err != nil { - return []PagesProjectDeployment{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + + if params.Page < 1 { + params.Page = 1 } - return r.Result, r.ResultInfo, nil + + var deployments []PagesProjectDeployment + var r pagesDeploymentListResponse + + for { + r = pagesDeploymentListResponse{} + uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName), params) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []PagesProjectDeployment{}, &ResultInfo{}, err + } + err = json.Unmarshal(res, &r) + if err != nil { + return []PagesProjectDeployment{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + deployments = append(deployments, r.Result...) + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { + break + } + + } + return r.Result, &r.ResultInfo, nil } // GetPagesDeploymentInfo returns a deployment for a Pages project. diff --git a/pages_deployment_test.go b/pages_deployment_test.go index 282710a0cf8..23f118a1d1c 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -319,12 +319,12 @@ func TestListPagesDeployments(t *testing.T) { Total: 1, } actual, resultInfo, err := client.ListPagesDeployments(context.Background(), AccountIdentifier(testAccountID), ListPagesDeploymentsParams{ - ProjectName: "test", - PaginationOptions: PaginationOptions{}, + ProjectName: "test", + ResultInfo: ResultInfo{}, }) if assert.NoError(t, err) { assert.Equal(t, expectedPagesDeployments, actual) - assert.Equal(t, expectedResultInfo, resultInfo) + assert.Equal(t, &expectedResultInfo, resultInfo) } } diff --git a/pages_project_test.go b/pages_project_test.go index 91671a5d5ca..4adbd2a05e1 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -585,8 +585,6 @@ func TestUpdatePagesProject(t *testing.T) { _, err := client.UpdatePagesProject(context.Background(), testAccountID, "Test Pages Project", *updateAttributes) - t.Log(err) - assert.NoError(t, err) } From c066f41587efeb96e984e74de5567964dd824b1a Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 7 Apr 2023 19:58:22 -0400 Subject: [PATCH 002/130] Change DeletePagesDeploymentParams to be the URL parameters --- .changelog/1264.txt | 4 ++++ pages_deployment.go | 8 +++----- pages_deployment_test.go | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.changelog/1264.txt b/.changelog/1264.txt index 63f7b89eacc..04612e8804b 100644 --- a/.changelog/1264.txt +++ b/.changelog/1264.txt @@ -1,3 +1,7 @@ ```release-note:breaking-change pages_deployment: add support for auto pagination +``` + +```release-note:breaking-change +pages_deployment: change DeletePagesDeploymentParams to be URL parameters ``` \ No newline at end of file diff --git a/pages_deployment.go b/pages_deployment.go index df91dbbccec..54fa98e5560 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -95,8 +95,7 @@ type GetPagesDeploymentLogsParams struct { } type DeletePagesDeploymentParams struct { - ProjectName string - DeploymentID string + force bool `url:"force,omitempty"` } type CreatePagesDeploymentParams struct { @@ -162,7 +161,6 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, if params.ResultInfo.Done() || !autoPaginate { break } - } return r.Result, &r.ResultInfo, nil } @@ -233,7 +231,7 @@ func (api *API) GetPagesDeploymentLogs(ctx context.Context, rc *ResourceContaine // DeletePagesDeployment deletes a Pages deployment. // // API reference: https://api.cloudflare.com/#pages-deployment-delete-deployment -func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, projectName, deploymentID string) error { +func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, projectName, deploymentID string, params DeletePagesDeploymentParams) error { if rc.Identifier == "" { return ErrMissingAccountID } @@ -246,7 +244,7 @@ func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer return ErrMissingDeploymentID } - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, projectName, deploymentID) + uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, projectName, deploymentID), params) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/pages_deployment_test.go b/pages_deployment_test.go index 23f118a1d1c..e46fdce5e93 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -398,7 +398,7 @@ func TestDeletePagesDeployment(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe", handler) - err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), "test", "0012e50b-fa5d-44db-8cb5-1f372785dcbe") + err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), "test", "0012e50b-fa5d-44db-8cb5-1f372785dcbe", DeletePagesDeploymentParams{}) assert.NoError(t, err) } From c02bb44709eb209b11c1b7d87de57bfa8c07aeb3 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 9 Apr 2023 10:43:51 -0400 Subject: [PATCH 003/130] Fix linting --- pages_deployment.go | 4 ++-- pages_deployment_test.go | 38 -------------------------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/pages_deployment.go b/pages_deployment.go index 54fa98e5560..0d3c8de18f6 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -95,7 +95,7 @@ type GetPagesDeploymentLogsParams struct { } type DeletePagesDeploymentParams struct { - force bool `url:"force,omitempty"` + Force bool `url:"force,omitempty"` } type CreatePagesDeploymentParams struct { @@ -162,7 +162,7 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, break } } - return r.Result, &r.ResultInfo, nil + return deployments, &r.ResultInfo, nil } // GetPagesDeploymentInfo returns a deployment for a Pages project. diff --git a/pages_deployment_test.go b/pages_deployment_test.go index e46fdce5e93..c6c45eff090 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -207,44 +207,6 @@ var ( Status: "success", } - expectedPagesDeploymentStageLogEntries = []PagesDeploymentStageLogEntry{ - { - ID: 0, - Timestamp: &pagesDeploymentDummyTime, - Message: "Installing dependencies", - }, - { - ID: 1, - Timestamp: &pagesDeploymentDummyTime, - Message: "Verify run directory", - }, - { - ID: 2, - Timestamp: &pagesDeploymentDummyTime, - Message: "Executing user command: bash test.sh", - }, - { - ID: 3, - Timestamp: &pagesDeploymentDummyTime, - Message: "Finished", - }, - { - ID: 4, - Timestamp: &pagesDeploymentDummyTime, - Message: "Building functions...", - }, - { - ID: 5, - Timestamp: &pagesDeploymentDummyTime, - Message: "Validating asset output directory", - }, - { - ID: 6, - Timestamp: &pagesDeploymentDummyTime, - Message: "Parsed 2 valid header rules.", - }, - } - expectedPagesDeploymentLogs = &PagesDeploymentLogs{ Total: 6, IncludesContainerLogs: true, From 645aed884a0e87fead812c89122cb15e4d3359cf Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 9 Apr 2023 13:57:12 -0400 Subject: [PATCH 004/130] Pages support max of 25 for per_page --- pages_deployment.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pages_deployment.go b/pages_deployment.go index 0d3c8de18f6..422b164e8f0 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -69,7 +69,7 @@ type pagesDeploymentLogsResponse struct { } type ListPagesDeploymentsParams struct { - ProjectName string + ProjectName string `url:"-"` ResultInfo } @@ -135,7 +135,7 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, } if params.PerPage < 1 { - params.PerPage = 50 + params.PerPage = 25 } if params.Page < 1 { @@ -146,7 +146,6 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, var r pagesDeploymentListResponse for { - r = pagesDeploymentListResponse{} uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { From ce92b12ce4ce8766a3cc0048ed895fab0a3b0973 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Mon, 10 Apr 2023 20:36:03 -0400 Subject: [PATCH 005/130] PR comments --- .changelog/1264.txt | 14 +++++++++++++- pages_deployment.go | 12 +++++++----- pages_deployment_test.go | 6 ++++-- pages_project.go | 41 +++++++++++++++++++++++++++++----------- pages_project_test.go | 36 ++++++++++++++++++++++++++++++----- 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/.changelog/1264.txt b/.changelog/1264.txt index 04612e8804b..55ed0957708 100644 --- a/.changelog/1264.txt +++ b/.changelog/1264.txt @@ -2,6 +2,18 @@ pages_deployment: add support for auto pagination ``` +```release-note:enchancement +pages_deployment: add Force to DeletePagesDeploymentParams +``` + +```release-note:breaking-change +pages_deployment: change DeletePagesDeploymentParams to contain all parameters +``` + +```release-note:breaking-change +pages_project: rename PagesProject to GetPagesProject +``` + ```release-note:breaking-change -pages_deployment: change DeletePagesDeploymentParams to be URL parameters +pages_project: change to use ResourceContainer for account ID ``` \ No newline at end of file diff --git a/pages_deployment.go b/pages_deployment.go index 422b164e8f0..8367045829f 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -95,7 +95,9 @@ type GetPagesDeploymentLogsParams struct { } type DeletePagesDeploymentParams struct { - Force bool `url:"force,omitempty"` + ProjectName string `url:"-"` + DeploymentID string `url:"-"` + Force bool `url:"force,omitempty"` } type CreatePagesDeploymentParams struct { @@ -230,20 +232,20 @@ func (api *API) GetPagesDeploymentLogs(ctx context.Context, rc *ResourceContaine // DeletePagesDeployment deletes a Pages deployment. // // API reference: https://api.cloudflare.com/#pages-deployment-delete-deployment -func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, projectName, deploymentID string, params DeletePagesDeploymentParams) error { +func (api *API) DeletePagesDeployment(ctx context.Context, rc *ResourceContainer, params DeletePagesDeploymentParams) error { if rc.Identifier == "" { return ErrMissingAccountID } - if projectName == "" { + if params.ProjectName == "" { return ErrMissingProjectName } - if deploymentID == "" { + if params.DeploymentID == "" { return ErrMissingDeploymentID } - uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, projectName, deploymentID), params) + uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments/%s", rc.Identifier, params.ProjectName, params.DeploymentID), params) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/pages_deployment_test.go b/pages_deployment_test.go index c6c45eff090..b52179490d5 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -251,6 +251,8 @@ func TestListPagesDeployments(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, "25", r.URL.Query().Get("per_page")) + assert.Equal(t, "1", r.URL.Query().Get("page")) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, `{ @@ -348,7 +350,7 @@ func TestDeletePagesDeployment(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodDelete, r.Method, "Expected method 'DELETE', got %s", r.Method) - + assert.Equal(t, "true", r.URL.Query().Get("force")) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, `{ "success": true, @@ -360,7 +362,7 @@ func TestDeletePagesDeployment(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe", handler) - err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), "test", "0012e50b-fa5d-44db-8cb5-1f372785dcbe", DeletePagesDeploymentParams{}) + err := client.DeletePagesDeployment(context.Background(), AccountIdentifier(testAccountID), DeletePagesDeploymentParams{ProjectName: "test", DeploymentID: "0012e50b-fa5d-44db-8cb5-1f372785dcbe", Force: true}) assert.NoError(t, err) } diff --git a/pages_project.go b/pages_project.go index 3177a8e0f81..865f4ad4e64 100644 --- a/pages_project.go +++ b/pages_project.go @@ -3,6 +3,7 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" "time" @@ -191,8 +192,12 @@ const ( // ListPagesProjects returns all Pages projects for an account. // // API reference: https://api.cloudflare.com/#pages-project-get-projects -func (api *API) ListPagesProjects(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]PagesProject, ResultInfo, error) { - uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects", accountID), pageOpts) +func (api *API) ListPagesProjects(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]PagesProject, ResultInfo, error) { + if rc.Identifier == "" { + return []PagesProject{}, ResultInfo{}, errors.New(errMissingAccountID) + } + + uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects", rc.Identifier), pageOpts) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -206,11 +211,15 @@ func (api *API) ListPagesProjects(ctx context.Context, accountID string, pageOpt return r.Result, r.ResultInfo, nil } -// PagesProject returns a single Pages project by name. +// GetPagesProject returns a single Pages project by name. // // API reference: https://api.cloudflare.com/#pages-project-get-project -func (api *API) PagesProject(ctx context.Context, accountID, projectName string) (PagesProject, error) { - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", accountID, projectName) +func (api *API) GetPagesProject(ctx context.Context, rc *ResourceContainer, projectName string) (PagesProject, error) { + if rc.Identifier == "" { + return PagesProject{}, errors.New(errMissingAccountID) + } + + uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return PagesProject{}, err @@ -226,8 +235,11 @@ func (api *API) PagesProject(ctx context.Context, accountID, projectName string) // CreatePagesProject creates a new Pages project in an account. // // API reference: https://api.cloudflare.com/#pages-project-create-project -func (api *API) CreatePagesProject(ctx context.Context, accountID string, pagesProject PagesProject) (PagesProject, error) { - uri := fmt.Sprintf("/accounts/%s/pages/projects", accountID) +func (api *API) CreatePagesProject(ctx context.Context, rc *ResourceContainer, pagesProject PagesProject) (PagesProject, error) { + if rc.Identifier == "" { + return PagesProject{}, errors.New(errMissingAccountID) + } + uri := fmt.Sprintf("/accounts/%s/pages/projects", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, pagesProject) if err != nil { return PagesProject{}, err @@ -243,8 +255,12 @@ func (api *API) CreatePagesProject(ctx context.Context, accountID string, pagesP // UpdatePagesProject updates an existing Pages project. // // API reference: https://api.cloudflare.com/#pages-project-update-project -func (api *API) UpdatePagesProject(ctx context.Context, accountID, projectName string, pagesProject PagesProject) (PagesProject, error) { - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", accountID, projectName) +func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, projectName string, pagesProject PagesProject) (PagesProject, error) { + if rc.Identifier == "" { + return PagesProject{}, errors.New(errMissingAccountID) + } + + uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, pagesProject) if err != nil { return PagesProject{}, err @@ -260,8 +276,11 @@ func (api *API) UpdatePagesProject(ctx context.Context, accountID, projectName s // DeletePagesProject deletes a Pages project by name. // // API reference: https://api.cloudflare.com/#pages-project-delete-project -func (api *API) DeletePagesProject(ctx context.Context, accountID, projectName string) error { - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", accountID, projectName) +func (api *API) DeletePagesProject(ctx context.Context, rc *ResourceContainer, projectName string) error { + if rc.Identifier == "" { + return errors.New(errMissingAccountID) + } + uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err diff --git a/pages_project_test.go b/pages_project_test.go index 4adbd2a05e1..b1857714347 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -506,7 +506,13 @@ func TestListPagesProjects(t *testing.T) { Count: 1, Total: 1, } - actual, resultInfo, err := client.ListPagesProjects(context.Background(), testAccountID, PaginationOptions{}) + + _, _, err := client.ListPagesProjects(context.Background(), AccountIdentifier(""), PaginationOptions{}) + if assert.Error(t, err) { + assert.Equal(t, err.Error(), errMissingAccountID) + } + + actual, resultInfo, err := client.ListPagesProjects(context.Background(), AccountIdentifier(testAccountID), PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, expectedPagesProjects, actual) assert.Equal(t, expectedResultInfo, resultInfo) @@ -531,7 +537,12 @@ func TestPagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/Test Pages Project", handler) - actual, err := client.PagesProject(context.Background(), testAccountID, "Test Pages Project") + _, err := client.GetPagesProject(context.Background(), AccountIdentifier(""), "Test Pages Project") + if assert.Error(t, err) { + assert.Equal(t, err.Error(), errMissingAccountID) + } + + actual, err := client.GetPagesProject(context.Background(), AccountIdentifier(testAccountID), "Test Pages Project") if assert.NoError(t, err) { assert.Equal(t, *expectedPagesProject, actual) } @@ -555,7 +566,12 @@ func TestCreatePagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects", handler) - actual, err := client.CreatePagesProject(context.Background(), testAccountID, *expectedPagesProject) + _, err := client.CreatePagesProject(context.Background(), AccountIdentifier(""), *expectedPagesProject) + if assert.Error(t, err) { + assert.Equal(t, err.Error(), errMissingAccountID) + } + + actual, err := client.CreatePagesProject(context.Background(), AccountIdentifier(testAccountID), *expectedPagesProject) if assert.NoError(t, err) { assert.Equal(t, *expectedPagesProject, actual) } @@ -583,7 +599,12 @@ func TestUpdatePagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/Test Pages Project", handler) - _, err := client.UpdatePagesProject(context.Background(), testAccountID, "Test Pages Project", *updateAttributes) + _, err := client.UpdatePagesProject(context.Background(), AccountIdentifier(""), "Test Pages Project", *updateAttributes) + if assert.Error(t, err) { + assert.Equal(t, err.Error(), errMissingAccountID) + } + + _, err = client.UpdatePagesProject(context.Background(), AccountIdentifier(testAccountID), "Test Pages Project", *updateAttributes) assert.NoError(t, err) } @@ -606,6 +627,11 @@ func TestDeletePagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/Test Pages Project", handler) - err := client.DeletePagesProject(context.Background(), testAccountID, "Test Pages Project") + err := client.DeletePagesProject(context.Background(), AccountIdentifier(""), "Test Pages Project") + if assert.Error(t, err) { + assert.Equal(t, err.Error(), errMissingAccountID) + } + + err = client.DeletePagesProject(context.Background(), AccountIdentifier(testAccountID), "Test Pages Project") assert.NoError(t, err) } From dfc5234348e1c1784eb74fe51104988c65f1be7b Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 11 Apr 2023 15:09:16 +1000 Subject: [PATCH 006/130] update more method signatures to match conventions --- pages_project.go | 57 +++++++++++++++++++++++++++++++++---------- pages_project_test.go | 34 ++++++++++++++++++-------- 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/pages_project.go b/pages_project.go index 865f4ad4e64..eed8fde8334 100644 --- a/pages_project.go +++ b/pages_project.go @@ -3,7 +3,6 @@ package cloudflare import ( "context" "encoding/json" - "errors" "fmt" "net/http" "time" @@ -189,15 +188,43 @@ const ( Unbound UsageModel = "unbound" ) +type ListPagesProjectsParams struct { + PaginationOptions +} + +type CreatePagesProjectParams struct { + Name string `json:"name,omitempty"` + SubDomain string `json:"subdomain"` + Domains []string `json:"domains,omitempty"` + Source *PagesProjectSource `json:"source,omitempty"` + BuildConfig PagesProjectBuildConfig `json:"build_config"` + DeploymentConfigs PagesProjectDeploymentConfigs `json:"deployment_configs"` + LatestDeployment PagesProjectDeployment `json:"latest_deployment"` + CanonicalDeployment PagesProjectDeployment `json:"canonical_deployment"` + ProductionBranch string `json:"production_branch,omitempty"` +} + +type UpdatePagesProjectParams struct { + Name string `json:"name,omitempty"` + SubDomain string `json:"subdomain"` + Domains []string `json:"domains,omitempty"` + Source *PagesProjectSource `json:"source,omitempty"` + BuildConfig PagesProjectBuildConfig `json:"build_config"` + DeploymentConfigs PagesProjectDeploymentConfigs `json:"deployment_configs"` + LatestDeployment PagesProjectDeployment `json:"latest_deployment"` + CanonicalDeployment PagesProjectDeployment `json:"canonical_deployment"` + ProductionBranch string `json:"production_branch,omitempty"` +} + // ListPagesProjects returns all Pages projects for an account. // // API reference: https://api.cloudflare.com/#pages-project-get-projects -func (api *API) ListPagesProjects(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]PagesProject, ResultInfo, error) { +func (api *API) ListPagesProjects(ctx context.Context, rc *ResourceContainer, params ListPagesProjectsParams) ([]PagesProject, ResultInfo, error) { if rc.Identifier == "" { - return []PagesProject{}, ResultInfo{}, errors.New(errMissingAccountID) + return []PagesProject{}, ResultInfo{}, ErrMissingAccountID } - uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects", rc.Identifier), pageOpts) + uri := buildURI(fmt.Sprintf("/accounts/%s/pages/projects", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -216,7 +243,7 @@ func (api *API) ListPagesProjects(ctx context.Context, rc *ResourceContainer, pa // API reference: https://api.cloudflare.com/#pages-project-get-project func (api *API) GetPagesProject(ctx context.Context, rc *ResourceContainer, projectName string) (PagesProject, error) { if rc.Identifier == "" { - return PagesProject{}, errors.New(errMissingAccountID) + return PagesProject{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) @@ -235,12 +262,12 @@ func (api *API) GetPagesProject(ctx context.Context, rc *ResourceContainer, proj // CreatePagesProject creates a new Pages project in an account. // // API reference: https://api.cloudflare.com/#pages-project-create-project -func (api *API) CreatePagesProject(ctx context.Context, rc *ResourceContainer, pagesProject PagesProject) (PagesProject, error) { +func (api *API) CreatePagesProject(ctx context.Context, rc *ResourceContainer, params CreatePagesProjectParams) (PagesProject, error) { if rc.Identifier == "" { - return PagesProject{}, errors.New(errMissingAccountID) + return PagesProject{}, ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/pages/projects", rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, pagesProject) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return PagesProject{}, err } @@ -255,13 +282,17 @@ func (api *API) CreatePagesProject(ctx context.Context, rc *ResourceContainer, p // UpdatePagesProject updates an existing Pages project. // // API reference: https://api.cloudflare.com/#pages-project-update-project -func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, projectName string, pagesProject PagesProject) (PagesProject, error) { +func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, params UpdatePagesProjectParams) (PagesProject, error) { if rc.Identifier == "" { - return PagesProject{}, errors.New(errMissingAccountID) + return PagesProject{}, ErrMissingAccountID } - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, pagesProject) + if params.Name == "" { + return PagesProject{}, ErrMissingName + } + + uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, params.Name) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return PagesProject{}, err } @@ -278,7 +309,7 @@ func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, p // API reference: https://api.cloudflare.com/#pages-project-delete-project func (api *API) DeletePagesProject(ctx context.Context, rc *ResourceContainer, projectName string) error { if rc.Identifier == "" { - return errors.New(errMissingAccountID) + return ErrMissingAccountID } uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, projectName) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) diff --git a/pages_project_test.go b/pages_project_test.go index b1857714347..010a29eeb52 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -81,8 +81,8 @@ const ( } }, "d1_databases": { - "D1_BINDING": { - "id": "a94509c6-0757-43f3-b053-474b0ab10935" + "D1_BINDING": { + "id": "a94509c6-0757-43f3-b053-474b0ab10935" } }, "kv_namespaces": { @@ -507,12 +507,12 @@ func TestListPagesProjects(t *testing.T) { Total: 1, } - _, _, err := client.ListPagesProjects(context.Background(), AccountIdentifier(""), PaginationOptions{}) + _, _, err := client.ListPagesProjects(context.Background(), AccountIdentifier(""), ListPagesProjectsParams{}) if assert.Error(t, err) { assert.Equal(t, err.Error(), errMissingAccountID) } - actual, resultInfo, err := client.ListPagesProjects(context.Background(), AccountIdentifier(testAccountID), PaginationOptions{}) + actual, resultInfo, err := client.ListPagesProjects(context.Background(), AccountIdentifier(testAccountID), ListPagesProjectsParams{}) if assert.NoError(t, err) { assert.Equal(t, expectedPagesProjects, actual) assert.Equal(t, expectedResultInfo, resultInfo) @@ -566,14 +566,28 @@ func TestCreatePagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects", handler) - _, err := client.CreatePagesProject(context.Background(), AccountIdentifier(""), *expectedPagesProject) + params := &CreatePagesProjectParams{ + SubDomain: "test.pages.dev", + Name: "Test Pages Project", + Domains: []string{ + "testdomain.com", + "testdomain.org", + }, + CanonicalDeployment: *expectedPagesProjectDeployment, + BuildConfig: *expectedPagesProjectBuildConfig, + DeploymentConfigs: *expectedPagesProjectDeploymentConfigs, + Source: expectedPagesProjectSource, + LatestDeployment: *expectedPagesProjectDeployment, + ProductionBranch: "main", + } + _, err := client.CreatePagesProject(context.Background(), AccountIdentifier(""), *params) if assert.Error(t, err) { assert.Equal(t, err.Error(), errMissingAccountID) } - actual, err := client.CreatePagesProject(context.Background(), AccountIdentifier(testAccountID), *expectedPagesProject) + actual, err := client.CreatePagesProject(context.Background(), AccountIdentifier(testAccountID), *params) if assert.NoError(t, err) { - assert.Equal(t, *expectedPagesProject, actual) + assert.Equal(t, params, actual) } } @@ -581,7 +595,7 @@ func TestUpdatePagesProject(t *testing.T) { setup() defer teardown() - updateAttributes := &PagesProject{ + updateAttributes := &UpdatePagesProjectParams{ Name: "updated-project-name", } @@ -599,12 +613,12 @@ func TestUpdatePagesProject(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/Test Pages Project", handler) - _, err := client.UpdatePagesProject(context.Background(), AccountIdentifier(""), "Test Pages Project", *updateAttributes) + _, err := client.UpdatePagesProject(context.Background(), AccountIdentifier(""), *updateAttributes) if assert.Error(t, err) { assert.Equal(t, err.Error(), errMissingAccountID) } - _, err = client.UpdatePagesProject(context.Background(), AccountIdentifier(testAccountID), "Test Pages Project", *updateAttributes) + _, err = client.UpdatePagesProject(context.Background(), AccountIdentifier(testAccountID), *updateAttributes) assert.NoError(t, err) } From bced5443fd076d2ca4595423d1cb445018f4ff51 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 14 Apr 2023 23:14:09 -0400 Subject: [PATCH 007/130] Add support for providing branch name when creating a deployment --- pages_deployment.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pages_deployment.go b/pages_deployment.go index 8367045829f..1463c35fb44 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -101,7 +101,8 @@ type DeletePagesDeploymentParams struct { } type CreatePagesDeploymentParams struct { - ProjectName string + ProjectName string `json:"-"` + Branch string `json:"branch,omitempty"` } type RetryPagesDeploymentParams struct { @@ -268,7 +269,7 @@ func (api *API) CreatePagesDeployment(ctx context.Context, rc *ResourceContainer uri := fmt.Sprintf("/accounts/%s/pages/projects/%s/deployments", rc.Identifier, params.ProjectName) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return PagesProjectDeployment{}, err } From 1e74748ffb46c0c9dc142d915be2ca5e4c7b6d1b Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sat, 15 Apr 2023 17:59:55 -0400 Subject: [PATCH 008/130] Implement ResultInfo.DoneCount() for result_info that doesn't implement total_pages --- pages_deployment.go | 2 +- pages_deployment_test.go | 68 ++++++++++++++++++++++++++++++++++++---- pagination.go | 12 +++++++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/pages_deployment.go b/pages_deployment.go index 1463c35fb44..af8cc208a3f 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -160,7 +160,7 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, } deployments = append(deployments, r.Result...) params.ResultInfo = r.ResultInfo.Next() - if params.ResultInfo.Done() || !autoPaginate { + if params.DoneCount() || !autoPaginate { break } } diff --git a/pages_deployment_test.go b/pages_deployment_test.go index b52179490d5..2595fbd1c3d 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -11,7 +11,7 @@ import ( ) const ( - testPagesDeplyomentResponse = ` + testPagesDeploymentResponse = ` { "id": "0012e50b-fa5d-44db-8cb5-1f372785dcbe", "short_id": "0012e50b", @@ -268,7 +268,7 @@ func TestListPagesDeployments(t *testing.T) { "count": 1, "total_count": 1 } - }`, testPagesDeplyomentResponse) + }`, testPagesDeploymentResponse) } mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler) @@ -292,6 +292,62 @@ func TestListPagesDeployments(t *testing.T) { } } +func TestListPagesDeploymentsPagination(t *testing.T) { + 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") + switch page { + case "1": + page1Called = true + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + %s + ], + "result_info": { + "page": 1, + "per_page": 25, + "total_count": 26 + } + }`, testPagesDeploymentResponse) + case "2": + page2Called = true + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": [ + %s + ], + "result_info": { + "page": 2, + "per_page": 25, + "total_count": 26 + } + }`, testPagesDeploymentResponse) + default: + assert.Failf(t, "Unexpected page number", "Expected page 1 or 2, got %s", page) + return + } + } + mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler) + actual, resultInfo, err := client.ListPagesDeployments(context.Background(), AccountIdentifier(testAccountID), ListPagesDeploymentsParams{ + ProjectName: "test", + ResultInfo: ResultInfo{}, + }) + if assert.NoError(t, err) { + assert.True(t, page1Called) + assert.True(t, page2Called) + assert.Equal(t, 2, len(actual)) + assert.Equal(t, 26, resultInfo.Total) + } +} + func TestGetPagesDeploymentInfo(t *testing.T) { setup() defer teardown() @@ -305,7 +361,7 @@ func TestGetPagesDeploymentInfo(t *testing.T) { "errors": [], "messages": [], "result": %s - }`, testPagesDeplyomentResponse) + }`, testPagesDeploymentResponse) } mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe", handler) @@ -379,7 +435,7 @@ func TestCreatePagesDeployment(t *testing.T) { "errors": [], "messages": [], "result": %s - }`, testPagesDeplyomentResponse) + }`, testPagesDeploymentResponse) } mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments", handler) @@ -406,7 +462,7 @@ func TestRetryPagesDeployment(t *testing.T) { "errors": [], "messages": [], "result": %s - }`, testPagesDeplyomentResponse) + }`, testPagesDeploymentResponse) } mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe/retry", handler) @@ -430,7 +486,7 @@ func TestRollbackPagesDeployment(t *testing.T) { "errors": [], "messages": [], "result": %s - }`, testPagesDeplyomentResponse) + }`, testPagesDeploymentResponse) } mux.HandleFunc("/accounts/"+testAccountID+"/pages/projects/test/deployments/0012e50b-fa5d-44db-8cb5-1f372785dcbe/rollback", handler) diff --git a/pagination.go b/pagination.go index 07d75ede84a..057c9c82c71 100644 --- a/pagination.go +++ b/pagination.go @@ -1,5 +1,9 @@ package cloudflare +import ( + "math" +) + // Done returns true for the last page and false otherwise. func (p ResultInfo) Done() bool { return p.Page > 1 && p.Page > p.TotalPages @@ -17,3 +21,11 @@ func (p ResultInfo) Next() ResultInfo { func (p ResultInfo) HasMorePages() bool { return p.Page > 1 && p.Page < p.TotalPages } + +// DoneCount returns true for the last page and false otherwise. +// This function uses the Total and PerPage fields to generate TotalPages +// then calls Done() +func (p ResultInfo) DoneCount() bool { + p.TotalPages = int(math.Ceil(float64(p.Total) / float64(p.PerPage))) + return p.Done() +} From 3bef7f275c64c1c08eefd7135ea37bb5811bce28 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Tue, 25 Apr 2023 20:42:08 -0400 Subject: [PATCH 009/130] Update pages_deployment to use the correct way to pagination. --- pages_deployment.go | 2 +- pages_deployment_test.go | 6 ++++-- pagination.go | 12 ------------ 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/pages_deployment.go b/pages_deployment.go index af8cc208a3f..899e89100e0 100644 --- a/pages_deployment.go +++ b/pages_deployment.go @@ -160,7 +160,7 @@ func (api *API) ListPagesDeployments(ctx context.Context, rc *ResourceContainer, } deployments = append(deployments, r.Result...) params.ResultInfo = r.ResultInfo.Next() - if params.DoneCount() || !autoPaginate { + if params.Done() || !autoPaginate { break } } diff --git a/pages_deployment_test.go b/pages_deployment_test.go index 2595fbd1c3d..48ec89abb6d 100644 --- a/pages_deployment_test.go +++ b/pages_deployment_test.go @@ -312,7 +312,8 @@ func TestListPagesDeploymentsPagination(t *testing.T) { "result_info": { "page": 1, "per_page": 25, - "total_count": 26 + "total_count": 26, + "total_pages": 2 } }`, testPagesDeploymentResponse) case "2": @@ -327,7 +328,8 @@ func TestListPagesDeploymentsPagination(t *testing.T) { "result_info": { "page": 2, "per_page": 25, - "total_count": 26 + "total_count": 26, + "total_pages": 2 } }`, testPagesDeploymentResponse) default: diff --git a/pagination.go b/pagination.go index 057c9c82c71..07d75ede84a 100644 --- a/pagination.go +++ b/pagination.go @@ -1,9 +1,5 @@ package cloudflare -import ( - "math" -) - // Done returns true for the last page and false otherwise. func (p ResultInfo) Done() bool { return p.Page > 1 && p.Page > p.TotalPages @@ -21,11 +17,3 @@ func (p ResultInfo) Next() ResultInfo { func (p ResultInfo) HasMorePages() bool { return p.Page > 1 && p.Page < p.TotalPages } - -// DoneCount returns true for the last page and false otherwise. -// This function uses the Total and PerPage fields to generate TotalPages -// then calls Done() -func (p ResultInfo) DoneCount() bool { - p.TotalPages = int(math.Ceil(float64(p.Total) / float64(p.PerPage))) - return p.Done() -} From 2aff559019fb5cee3c6678853d97a9dd83d7a824 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 8 Jun 2023 13:44:36 +1000 Subject: [PATCH 010/130] tunnel: introduce custom `Duration` for time fields All Tunnel timeout values are based on seconds however, there isn't a great way to do this in a flexible way with Go due to `time.Duration` not having marshal/unmarshal support in Go 1[1]. Instead, we introduce a custom `TunnelDuration` value here and ensure it always converts durations into seconds without impacting other users of `time.Duration`. [1]: https://github.com/golang/go/issues/10275 --- .changelog/1303.txt | 3 +++ tunnel.go | 33 +++++++++++++++++++++++++++++---- tunnel_test.go | 8 +++++--- 3 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 .changelog/1303.txt diff --git a/.changelog/1303.txt b/.changelog/1303.txt new file mode 100644 index 00000000000..50a9b97a30b --- /dev/null +++ b/.changelog/1303.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +tunnel: swap `ConnectTimeout`, `TLSTimeout`, `TCPKeepAlive` and `KeepAliveTimeout` to `TunnelDuration` instead of `time.Duration` +``` diff --git a/tunnel.go b/tunnel.go index 30fa97896cb..92e91b991ff 100644 --- a/tunnel.go +++ b/tunnel.go @@ -6,9 +6,34 @@ import ( "errors" "fmt" "net/http" + "strconv" "time" ) +// A TunnelDuration is a Duration that has custom serialization for JSON. +// JSON in Javascript assumes that int fields are 32 bits and Duration fields +// are deserialized assuming that numbers are in nanoseconds, which in 32bit +// integers limits to just 2 seconds. This type assumes that when +// serializing/deserializing from JSON, that the number is in seconds, while it +// maintains the YAML serde assumptions. +type TunnelDuration struct { + time.Duration +} + +func (s TunnelDuration) MarshalJSON() ([]byte, error) { + return json.Marshal(s.Duration.Seconds()) +} + +func (s *TunnelDuration) UnmarshalJSON(data []byte) error { + seconds, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return err + } + + s.Duration = time.Duration(seconds * int64(time.Second)) + return nil +} + // ErrMissingTunnelID is for when a required tunnel ID is missing from the // parameters. var ErrMissingTunnelID = errors.New("required missing tunnel ID") @@ -118,17 +143,17 @@ type UnvalidatedIngressRule struct { // config. type OriginRequestConfig struct { // HTTP proxy timeout for establishing a new connection - ConnectTimeout *time.Duration `json:"connectTimeout,omitempty"` + ConnectTimeout *TunnelDuration `json:"connectTimeout,omitempty"` // HTTP proxy timeout for completing a TLS handshake - TLSTimeout *time.Duration `json:"tlsTimeout,omitempty"` + TLSTimeout *TunnelDuration `json:"tlsTimeout,omitempty"` // HTTP proxy TCP keepalive duration - TCPKeepAlive *time.Duration `json:"tcpKeepAlive,omitempty"` + TCPKeepAlive *TunnelDuration `json:"tcpKeepAlive,omitempty"` // HTTP proxy should disable "happy eyeballs" for IPv4/v6 fallback NoHappyEyeballs *bool `json:"noHappyEyeballs,omitempty"` // HTTP proxy maximum keepalive connection pool size KeepAliveConnections *int `json:"keepAliveConnections,omitempty"` // HTTP proxy timeout for closing an idle connection - KeepAliveTimeout *time.Duration `json:"keepAliveTimeout,omitempty"` + KeepAliveTimeout *TunnelDuration `json:"keepAliveTimeout,omitempty"` // Sets the HTTP Host header for the local webserver. HTTPHostHeader *string `json:"httpHostHeader,omitempty"` // Hostname on the origin server certificate. diff --git a/tunnel_test.go b/tunnel_test.go index cacc12fb608..da912ccf4be 100644 --- a/tunnel_test.go +++ b/tunnel_test.go @@ -189,6 +189,7 @@ func TestUpdateTunnelConfiguration(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "configuration")) } + timeout, _ := time.ParseDuration("10s") mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/configurations", testAccountID, testTunnelID), handler) want := TunnelConfigurationResult{ TunnelID: testTunnelID, @@ -210,7 +211,7 @@ func TestUpdateTunnelConfiguration(t *testing.T) { Enabled: true, }, OriginRequest: OriginRequestConfig{ - ConnectTimeout: DurationPtr(10), + ConnectTimeout: &TunnelDuration{timeout}, }, }} @@ -233,7 +234,7 @@ func TestUpdateTunnelConfiguration(t *testing.T) { Enabled: true, }, OriginRequest: OriginRequestConfig{ - ConnectTimeout: DurationPtr(10 * time.Second), + ConnectTimeout: &TunnelDuration{10}, }, }, }) @@ -254,6 +255,7 @@ func TestGetTunnelConfiguration(t *testing.T) { fmt.Fprint(w, loadFixture("tunnel", "configuration")) } + timeout, _ := time.ParseDuration("10s") mux.HandleFunc(fmt.Sprintf("/accounts/%s/cfd_tunnel/%s/configurations", testAccountID, testTunnelID), handler) want := TunnelConfigurationResult{ TunnelID: testTunnelID, @@ -275,7 +277,7 @@ func TestGetTunnelConfiguration(t *testing.T) { Enabled: true, }, OriginRequest: OriginRequestConfig{ - ConnectTimeout: DurationPtr(10), + ConnectTimeout: &TunnelDuration{timeout}, }, }} From f47947b77a3b2bbb5d3955735fb8b27c72f87895 Mon Sep 17 00:00:00 2001 From: Ryan Whelan <4249368+rwhelan@users.noreply.github.com> Date: Thu, 8 Jun 2023 14:56:29 -0400 Subject: [PATCH 011/130] feat: add account level custom nameservers --- account_level_custom_nameservers.go | 162 ++++++++++++++++ account_level_custom_nameservers_test.go | 223 +++++++++++++++++++++++ 2 files changed, 385 insertions(+) create mode 100644 account_level_custom_nameservers.go create mode 100644 account_level_custom_nameservers_test.go diff --git a/account_level_custom_nameservers.go b/account_level_custom_nameservers.go new file mode 100644 index 00000000000..185d63771f3 --- /dev/null +++ b/account_level_custom_nameservers.go @@ -0,0 +1,162 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" +) + +type CustomNameserverRecord struct { + Type string `json:"type"` + Value string `json:"value"` +} + +type CustomNameserver struct { + NSName string `json:"ns_name"` + NSSet int `json:"ns_set"` +} + +type CustomNameserverResult struct { + DNSRecords []CustomNameserverRecord `json:"dns_records"` + NSName string `json:"ns_name"` + NSSet int `json:"ns_set"` + Status string `json:"status"` + ZoneTag string `json:"zone_tag"` +} + +type CustomNameserverZoneMetadata struct { + Type string `json:"type"` + NSSet string `json:"ns_set"` + Enabled bool `json:"enabled"` +} + +type customNameserverListResponse struct { + Response + Result []CustomNameserverResult `json:"result"` +} + +type customNameserverCreateResponse struct { + Response + Result CustomNameserverResult `json:"result"` +} + +type customNameserverZoneMetadata struct { + Response + Result CustomNameserverZoneMetadata +} + +// GetAccountCustomNameservers lists an account's custom nameservers. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-list-account-custom-nameservers +func (api *API) GetAccountCustomNameservers(ctx context.Context, rc *ResourceContainer) ([]CustomNameserverResult, error) { + uri := fmt.Sprintf("/accounts/%s/custom_ns", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, err + } + + response := &customNameserverListResponse{} + err = json.Unmarshal(res, &response) + if err != nil { + return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// CreateAccountCustomNameserver adds an account custom nameserver. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-add-account-custom-nameserver +func (api *API) CreateAccountCustomNameserver(ctx context.Context, rc *ResourceContainer, param CustomNameserver) (CustomNameserverResult, error) { + uri := fmt.Sprintf("/accounts/%s/custom_ns", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, param) + if err != nil { + return CustomNameserverResult{}, err + } + + response := &customNameserverCreateResponse{} + err = json.Unmarshal(res, &response) + if err != nil { + return CustomNameserverResult{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// DeleteAccountCustomNameserver removes an account custom nameserver. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-delete-account-custom-nameserver +func (api *API) DeleteAccountCustomNameserver(ctx context.Context, rc *ResourceContainer, nsName string) error { + uri := fmt.Sprintf("/accounts/%s/custom_ns/%s", rc.Identifier, nsName) + + _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) + if err != nil { + return err + } + + return nil +} + +// GetEligibleZonesAccountCustomNameservers lists zones eligible for account custom nameservers. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-get-eligible-zones-for-account-custom-nameservers +func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc *ResourceContainer) ([]string, error) { + uri := fmt.Sprintf("/accounts/%s/custom_ns/availability", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, err + } + + response := struct { + Result []string `json:"result"` + }{} + + err = json.Unmarshal(res, &response) + if err != nil { + return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// GetAccountCustomNameserverZoneMetadata get metadata for account-level custom nameservers on a zone. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-get-account-custom-nameserver-related-zone-metadata +func (api *API) GetAccountCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer) (CustomNameserverZoneMetadata, error) { + uri := fmt.Sprintf("/zones/%s/custom_ns", rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return CustomNameserverZoneMetadata{}, err + } + + response := &customNameserverZoneMetadata{} + + err = json.Unmarshal(res, &response) + if err != nil { + return CustomNameserverZoneMetadata{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} + +// UpdateAccountCustomNameserverZoneMetadata set metadata for account-level custom nameservers on a zone. +// +// API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-set-account-custom-nameserver-related-zone-metadata +func (api *API) UpdateAccountCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, param CustomNameserverZoneMetadata) error { + uri := fmt.Sprintf("/zones/%s/custom_ns", rc.Identifier) + + param.Type = "" + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, param) + if err != nil { + return nil + } + + fmt.Println(string(res)) + + return nil +} diff --git a/account_level_custom_nameservers_test.go b/account_level_custom_nameservers_test.go new file mode 100644 index 00000000000..41647c714f6 --- /dev/null +++ b/account_level_custom_nameservers_test.go @@ -0,0 +1,223 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAccountCustomNameserver_Get(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": [ + { + "ns_name": "ns1.example.com", + "ns_set": 1, + "dns_records": [ + { + "type": "A", + "value": "192.0.2.1" + }, + { + "type": "AAAA", + "value": "2400:cb00:2049:1::ffff:ffee" + } + ] + }, + { + "ns_name": "ns2.example.com", + "ns_set": 1, + "dns_records": [ + { + "type": "A", + "value": "192.0.2.2" + }, + { + "type": "AAAA", + "value": "2400:cb00:2049:1::ffff:fffe" + } + ] + } + ] + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns", handler) + want := []CustomNameserverResult{ + { + DNSRecords: []CustomNameserverRecord{ + { + Type: "A", + Value: "192.0.2.1", + }, + { + Type: "AAAA", + Value: "2400:cb00:2049:1::ffff:ffee", + }, + }, + NSName: "ns1.example.com", + NSSet: 1, + }, + { + DNSRecords: []CustomNameserverRecord{ + { + Type: "A", + Value: "192.0.2.2", + }, + { + Type: "AAAA", + Value: "2400:cb00:2049:1::ffff:fffe", + }, + }, + NSName: "ns2.example.com", + NSSet: 1, + }, + } + + actual, err := client.GetAccountCustomNameservers(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823")) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestAccountCustomNameserver_Create(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "ns_name": "ns1.example.com", + "ns_set": 1, + "dns_records": [ + { + "type": "A", + "value": "192.0.2.1" + }, + { + "type": "AAAA", + "value": "2400:cb00:2049:1::ffff:ffee" + } + ] + } + }`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns", handler) + want := CustomNameserverResult{ + DNSRecords: []CustomNameserverRecord{ + { + Type: "A", + Value: "192.0.2.1", + }, + { + Type: "AAAA", + Value: "2400:cb00:2049:1::ffff:ffee", + }, + }, + NSName: "ns1.example.com", + NSSet: 1, + } + + actual, err := client.CreateAccountCustomNameserver( + context.Background(), + AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), + CustomNameserver{ + NSName: "ns1.example.com", + NSSet: 1, + }, + ) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestAccountCustomNameserver_GetEligibleZones(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": [ + "example.com", + "example2.com", + "example3.com" + ], + "success": true, + "errors": [], + "messages": [] +}`) + } + + mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns/availability", handler) + want := []string{ + "example.com", + "example2.com", + "example3.com", + } + + actual, err := client.GetEligibleZonesAccountCustomNameservers( + context.Background(), + AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), + ) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestAccountCustomNameserver_GetAccountCustomNameserverZoneMetadata(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": { + "type": "account", + "ns_set": "1", + "enabled": true + }, + "success": true, + "errors": [], + "messages": [] + }`) + } + + mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/custom_ns", handler) + want := CustomNameserverZoneMetadata{ + Type: "account", + NSSet: "1", + Enabled: true, + } + + actual, err := client.GetAccountCustomNameserverZoneMetadata( + context.Background(), + ZoneIdentifier("023e105f4ecef8ad9ca31a8372d0c353"), + ) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From 68b50a2ed020a8c46bcf4b2f05a97534346b6d72 Mon Sep 17 00:00:00 2001 From: Ryan Whelan <4249368+rwhelan@users.noreply.github.com> Date: Thu, 8 Jun 2023 15:05:37 -0400 Subject: [PATCH 012/130] chore: add changelog --- .changelog/1304.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1304.txt diff --git a/.changelog/1304.txt b/.changelog/1304.txt new file mode 100644 index 00000000000..e20e7817959 --- /dev/null +++ b/.changelog/1304.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +account_level_custom_hostnames: add support for the account level custom hostname api +``` From 914af569ead7780cb7295ffea871efd7b3749759 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:56:48 +0000 Subject: [PATCH 013/130] build(deps): bump github.com/urfave/cli/v2 from 2.25.5 to 2.25.6 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.5 to 2.25.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.25.5...v2.25.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 95ab6b1d62f..8966dcce0f0 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.25.5 + github.com/urfave/cli/v2 v2.25.6 golang.org/x/net v0.10.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index 1cc438c83da..f7513449f23 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= -github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.25.6 h1:yuSkgDSZfH3L1CjF2/5fNNg2KbM47pY2EvjBq4ESQnU= +github.com/urfave/cli/v2 v2.25.6/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= From ee59776a25cb837f8a1a687a11b56b2ee47e4f2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:57:04 +0000 Subject: [PATCH 014/130] build(deps): bump goreleaser/goreleaser-action from 4.2.0 to 4.3.0 Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v4.2.0...v4.3.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 d93438671af..542ceda8811 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.2.0 + uses: goreleaser/goreleaser-action@v4.3.0 with: version: latest args: release --rm-dist From f4bf3bae9c86fe6b80552c14a7d93be94d6e4691 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 12 Jun 2023 16:57:08 +0000 Subject: [PATCH 015/130] add CHANGELOG for #1305 --- .changelog/1305.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1305.txt diff --git a/.changelog/1305.txt b/.changelog/1305.txt new file mode 100644 index 00000000000..1919a14e3fb --- /dev/null +++ b/.changelog/1305.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.25.5 to 2.25.6 +``` From 857ae4a1ee2df9ee5dd49505949fc08230b46873 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 12 Jun 2023 16:57:21 +0000 Subject: [PATCH 016/130] add CHANGELOG for #1306 --- .changelog/1306.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1306.txt diff --git a/.changelog/1306.txt b/.changelog/1306.txt new file mode 100644 index 00000000000..a655ab47bd9 --- /dev/null +++ b/.changelog/1306.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps goreleaser/goreleaser-action from 4.2.0 to 4.3.0 +``` From a36f00f7d65b11688e38c4e304cf676b0bb827d9 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 12 Jun 2023 20:26:41 +0000 Subject: [PATCH 017/130] Update CHANGELOG.md for #1306 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b18cfae7e4f..0302e89a746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ ENHANCEMENTS: DEPENDENCIES: * deps: bumps github.com/hashicorp/go-retryablehttp from 0.7.3 to 0.7.4 ([#1301](https://github.com/cloudflare/cloudflare-go/issues/1301)) +* deps: bumps github.com/urfave/cli/v2 from 2.25.5 to 2.25.6 ([#1305](https://github.com/cloudflare/cloudflare-go/issues/1305)) +* deps: bumps goreleaser/goreleaser-action from 4.2.0 to 4.3.0 ([#1306](https://github.com/cloudflare/cloudflare-go/issues/1306)) ## 0.69.0 (June 7th, 2023) From 0d9c8d59292d9a55bbfa49cc267fd231e067023f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 16:56:41 +0000 Subject: [PATCH 018/130] build(deps): bump golang.org/x/net from 0.10.0 to 0.11.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.11.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.11.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 8966dcce0f0..4039b9fe6c3 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.4 github.com/urfave/cli/v2 v2.25.6 - golang.org/x/net v0.10.0 + golang.org/x/net v0.11.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.9.0 // indirect + golang.org/x/text v0.10.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f7513449f23..df5503443a3 100644 --- a/go.sum +++ b/go.sum @@ -57,17 +57,17 @@ github.com/urfave/cli/v2 v2.25.6 h1:yuSkgDSZfH3L1CjF2/5fNNg2KbM47pY2EvjBq4ESQnU= github.com/urfave/cli/v2 v2.25.6/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= 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.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/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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 64c041504aef6e357a9f7889010cd4963efaf637 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 13 Jun 2023 16:56:57 +0000 Subject: [PATCH 019/130] add CHANGELOG for #1307 --- .changelog/1307.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1307.txt diff --git a/.changelog/1307.txt b/.changelog/1307.txt new file mode 100644 index 00000000000..ce939ea0c57 --- /dev/null +++ b/.changelog/1307.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.10.0 to 0.11.0 +``` From 713a1af00a17e92d24bb46103a811e0e57470fa1 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 13 Jun 2023 20:36:41 +0000 Subject: [PATCH 020/130] Update CHANGELOG.md for #1307 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0302e89a746..b0b42dd98ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ DEPENDENCIES: * deps: bumps github.com/hashicorp/go-retryablehttp from 0.7.3 to 0.7.4 ([#1301](https://github.com/cloudflare/cloudflare-go/issues/1301)) * deps: bumps github.com/urfave/cli/v2 from 2.25.5 to 2.25.6 ([#1305](https://github.com/cloudflare/cloudflare-go/issues/1305)) +* deps: bumps golang.org/x/net from 0.10.0 to 0.11.0 ([#1307](https://github.com/cloudflare/cloudflare-go/issues/1307)) * deps: bumps goreleaser/goreleaser-action from 4.2.0 to 4.3.0 ([#1306](https://github.com/cloudflare/cloudflare-go/issues/1306)) ## 0.69.0 (June 7th, 2023) From fce8f787bf4d9c351497749b75e89c41cb800712 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 13:27:56 +1000 Subject: [PATCH 021/130] account_level_custom_nameservers => custom_nameservers --- account_level_custom_nameservers.go => custom_nameservers.go | 0 ...level_custom_nameservers_test.go => custom_nameservers_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename account_level_custom_nameservers.go => custom_nameservers.go (100%) rename account_level_custom_nameservers_test.go => custom_nameservers_test.go (100%) diff --git a/account_level_custom_nameservers.go b/custom_nameservers.go similarity index 100% rename from account_level_custom_nameservers.go rename to custom_nameservers.go diff --git a/account_level_custom_nameservers_test.go b/custom_nameservers_test.go similarity index 100% rename from account_level_custom_nameservers_test.go rename to custom_nameservers_test.go From c8b7f697daef180173dd83c8d12b42234a440cd3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 15:01:35 +1000 Subject: [PATCH 022/130] drop "account" from method names Instead, rely on `ResourceContainer` to build the endpoints. --- custom_nameservers.go | 103 +++++++++++++++++++++++++++---------- custom_nameservers_test.go | 8 +-- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/custom_nameservers.go b/custom_nameservers.go index 185d63771f3..ce8a47cabbc 100644 --- a/custom_nameservers.go +++ b/custom_nameservers.go @@ -3,6 +3,7 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" ) @@ -41,16 +42,44 @@ type customNameserverCreateResponse struct { Result CustomNameserverResult `json:"result"` } +type getEligibleZonesAccountCustomNameserversResponse struct { + Result []string `json:"result"` +} + type customNameserverZoneMetadata struct { Response Result CustomNameserverZoneMetadata } -// GetAccountCustomNameservers lists an account's custom nameservers. +type GetCustomNameserversParams struct{} + +type CreateCustomNameserversParams struct { + NSName string `json:"ns_name"` + NSSet int `json:"ns_set"` +} + +type DeleteCustomNameserversParams struct { + NSName string +} + +type GetEligibleZonesAccountCustomNameserversParams struct{} + +type GetCustomNameserverZoneMetadataParams struct{} + +type UpdateCustomNameserverZoneMetadataParams struct { + Type string `json:"type"` + NSSet string `json:"ns_set"` + Enabled bool `json:"enabled"` +} + +// GetCustomNameservers lists an account's custom nameservers. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-list-account-custom-nameservers -func (api *API) GetAccountCustomNameservers(ctx context.Context, rc *ResourceContainer) ([]CustomNameserverResult, error) { - uri := fmt.Sprintf("/accounts/%s/custom_ns", rc.Identifier) +func (api *API) GetCustomNameservers(ctx context.Context, rc *ResourceContainer, params GetCustomNameserversParams) ([]CustomNameserverResult, error) { + if rc.Level != AccountRouteLevel { + return []CustomNameserverResult{}, ErrRequiredAccountLevelResourceContainer + } + uri := fmt.Sprintf("/%s/%s/custom_ns", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -66,13 +95,17 @@ func (api *API) GetAccountCustomNameservers(ctx context.Context, rc *ResourceCon return response.Result, nil } -// CreateAccountCustomNameserver adds an account custom nameserver. +// CreateCustomNameservers adds a custom nameserver. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-add-account-custom-nameserver -func (api *API) CreateAccountCustomNameserver(ctx context.Context, rc *ResourceContainer, param CustomNameserver) (CustomNameserverResult, error) { - uri := fmt.Sprintf("/accounts/%s/custom_ns", rc.Identifier) +func (api *API) CreateCustomNameservers(ctx context.Context, rc *ResourceContainer, params CreateCustomNameserversParams) (CustomNameserverResult, error) { + if rc.Level != AccountRouteLevel { + return CustomNameserverResult{}, ErrRequiredAccountLevelResourceContainer + } - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, param) + uri := fmt.Sprintf("/%s/%s/custom_ns", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return CustomNameserverResult{}, err } @@ -86,11 +119,19 @@ func (api *API) CreateAccountCustomNameserver(ctx context.Context, rc *ResourceC return response.Result, nil } -// DeleteAccountCustomNameserver removes an account custom nameserver. +// DeleteCustomNameservers removes a custom nameserver. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-delete-account-custom-nameserver -func (api *API) DeleteAccountCustomNameserver(ctx context.Context, rc *ResourceContainer, nsName string) error { - uri := fmt.Sprintf("/accounts/%s/custom_ns/%s", rc.Identifier, nsName) +func (api *API) DeleteCustomNameservers(ctx context.Context, rc *ResourceContainer, params DeleteCustomNameserversParams) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + if params.NSName == "" { + return errors.New("missing required NSName parameter") + } + + uri := fmt.Sprintf("/%s/%s/custom_ns/%s", rc.Level, rc.Identifier, params.NSName) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -103,18 +144,19 @@ func (api *API) DeleteAccountCustomNameserver(ctx context.Context, rc *ResourceC // GetEligibleZonesAccountCustomNameservers lists zones eligible for account custom nameservers. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-get-eligible-zones-for-account-custom-nameservers -func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc *ResourceContainer) ([]string, error) { - uri := fmt.Sprintf("/accounts/%s/custom_ns/availability", rc.Identifier) +func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc *ResourceContainer, params GetEligibleZonesAccountCustomNameserversParams) ([]string, error) { + if rc.Level != AccountRouteLevel { + return []string{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/custom_ns/availability", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err } - response := struct { - Result []string `json:"result"` - }{} - + var response getEligibleZonesAccountCustomNameserversResponse err = json.Unmarshal(res, &response) if err != nil { return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -123,19 +165,22 @@ func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc return response.Result, nil } -// GetAccountCustomNameserverZoneMetadata get metadata for account-level custom nameservers on a zone. +// GetCustomNameserverZoneMetadata get metadata for account-level custom nameservers on a zone. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-get-account-custom-nameserver-related-zone-metadata -func (api *API) GetAccountCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer) (CustomNameserverZoneMetadata, error) { - uri := fmt.Sprintf("/zones/%s/custom_ns", rc.Identifier) +func (api *API) GetCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, params GetCustomNameserverZoneMetadataParams) (CustomNameserverZoneMetadata, error) { + if rc.Level != ZoneRouteLevel { + return CustomNameserverZoneMetadata{}, ErrRequiredZoneLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/custom_ns", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return CustomNameserverZoneMetadata{}, err } - response := &customNameserverZoneMetadata{} - + var response customNameserverZoneMetadata err = json.Unmarshal(res, &response) if err != nil { return CustomNameserverZoneMetadata{}, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -144,19 +189,21 @@ func (api *API) GetAccountCustomNameserverZoneMetadata(ctx context.Context, rc * return response.Result, nil } -// UpdateAccountCustomNameserverZoneMetadata set metadata for account-level custom nameservers on a zone. +// UpdateCustomNameserverZoneMetadata set metadata for account-level custom nameservers on a zone. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-set-account-custom-nameserver-related-zone-metadata -func (api *API) UpdateAccountCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, param CustomNameserverZoneMetadata) error { - uri := fmt.Sprintf("/zones/%s/custom_ns", rc.Identifier) +func (api *API) UpdateCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, params UpdateCustomNameserverZoneMetadataParams) error { + if rc.Level != ZoneRouteLevel { + return ErrRequiredZoneLevelResourceContainer + } - param.Type = "" - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, param) + uri := fmt.Sprintf("/%s/%s/custom_ns", rc.Level, rc.Identifier) + + params.Type = "" + _, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return nil } - fmt.Println(string(res)) - return nil } diff --git a/custom_nameservers_test.go b/custom_nameservers_test.go index 41647c714f6..2014508fabd 100644 --- a/custom_nameservers_test.go +++ b/custom_nameservers_test.go @@ -85,7 +85,7 @@ func TestAccountCustomNameserver_Get(t *testing.T) { }, } - actual, err := client.GetAccountCustomNameservers(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823")) + actual, err := client.GetCustomNameservers(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), GetCustomNameserversParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -136,10 +136,10 @@ func TestAccountCustomNameserver_Create(t *testing.T) { NSSet: 1, } - actual, err := client.CreateAccountCustomNameserver( + actual, err := client.CreateCustomNameservers( context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), - CustomNameserver{ + CreateCustomNameserversParams{ NSName: "ns1.example.com", NSSet: 1, }, @@ -212,7 +212,7 @@ func TestAccountCustomNameserver_GetAccountCustomNameserverZoneMetadata(t *testi Enabled: true, } - actual, err := client.GetAccountCustomNameserverZoneMetadata( + actual, err := client.GetCustomNameserverZoneMetadata( context.Background(), ZoneIdentifier("023e105f4ecef8ad9ca31a8372d0c353"), ) From 4c6c1188a16934f5bd6c1ac44b7eaea35ecd3ff4 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 15:02:47 +1000 Subject: [PATCH 023/130] reword changelog entry --- .changelog/1304.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1304.txt b/.changelog/1304.txt index e20e7817959..f3e8693e2ad 100644 --- a/.changelog/1304.txt +++ b/.changelog/1304.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -account_level_custom_hostnames: add support for the account level custom hostname api +custom_nameservers: add support for managing custom nameservers ``` From 824053f28ffb180d8a797170cd2ed5fff3e2b6a5 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 15:05:31 +1000 Subject: [PATCH 024/130] clean up comments --- custom_nameservers.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_nameservers.go b/custom_nameservers.go index ce8a47cabbc..17836c883cd 100644 --- a/custom_nameservers.go +++ b/custom_nameservers.go @@ -72,7 +72,7 @@ type UpdateCustomNameserverZoneMetadataParams struct { Enabled bool `json:"enabled"` } -// GetCustomNameservers lists an account's custom nameservers. +// GetCustomNameservers lists custom nameservers. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-list-account-custom-nameservers func (api *API) GetCustomNameservers(ctx context.Context, rc *ResourceContainer, params GetCustomNameserversParams) ([]CustomNameserverResult, error) { @@ -86,7 +86,7 @@ func (api *API) GetCustomNameservers(ctx context.Context, rc *ResourceContainer, return nil, err } - response := &customNameserverListResponse{} + var response customNameserverListResponse err = json.Unmarshal(res, &response) if err != nil { return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -141,7 +141,7 @@ func (api *API) DeleteCustomNameservers(ctx context.Context, rc *ResourceContain return nil } -// GetEligibleZonesAccountCustomNameservers lists zones eligible for account custom nameservers. +// GetEligibleZonesAccountCustomNameservers lists zones eligible for custom nameservers. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-get-eligible-zones-for-account-custom-nameservers func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc *ResourceContainer, params GetEligibleZonesAccountCustomNameserversParams) ([]string, error) { @@ -165,7 +165,7 @@ func (api *API) GetEligibleZonesAccountCustomNameservers(ctx context.Context, rc return response.Result, nil } -// GetCustomNameserverZoneMetadata get metadata for account-level custom nameservers on a zone. +// GetCustomNameserverZoneMetadata get metadata for custom nameservers on a zone. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-get-account-custom-nameserver-related-zone-metadata func (api *API) GetCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, params GetCustomNameserverZoneMetadataParams) (CustomNameserverZoneMetadata, error) { @@ -189,7 +189,7 @@ func (api *API) GetCustomNameserverZoneMetadata(ctx context.Context, rc *Resourc return response.Result, nil } -// UpdateCustomNameserverZoneMetadata set metadata for account-level custom nameservers on a zone. +// UpdateCustomNameserverZoneMetadata set metadata for custom nameservers on a zone. // // API documentation: https://developers.cloudflare.com/api/operations/account-level-custom-nameservers-usage-for-a-zone-set-account-custom-nameserver-related-zone-metadata func (api *API) UpdateCustomNameserverZoneMetadata(ctx context.Context, rc *ResourceContainer, params UpdateCustomNameserverZoneMetadataParams) error { From 51918be45c12f2529d2320ff082d6d94a687bbd6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 15:07:27 +1000 Subject: [PATCH 025/130] reuse consts in tests --- custom_nameservers_test.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/custom_nameservers_test.go b/custom_nameservers_test.go index 2014508fabd..e1b51fa161e 100644 --- a/custom_nameservers_test.go +++ b/custom_nameservers_test.go @@ -53,7 +53,7 @@ func TestAccountCustomNameserver_Get(t *testing.T) { }`) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/custom_ns", handler) want := []CustomNameserverResult{ { DNSRecords: []CustomNameserverRecord{ @@ -85,7 +85,7 @@ func TestAccountCustomNameserver_Get(t *testing.T) { }, } - actual, err := client.GetCustomNameservers(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), GetCustomNameserversParams{}) + actual, err := client.GetCustomNameservers(context.Background(), AccountIdentifier(testAccountID), GetCustomNameserversParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -120,7 +120,7 @@ func TestAccountCustomNameserver_Create(t *testing.T) { }`) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/custom_ns", handler) want := CustomNameserverResult{ DNSRecords: []CustomNameserverRecord{ { @@ -138,7 +138,7 @@ func TestAccountCustomNameserver_Create(t *testing.T) { actual, err := client.CreateCustomNameservers( context.Background(), - AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), + AccountIdentifier(testAccountID), CreateCustomNameserversParams{ NSName: "ns1.example.com", NSSet: 1, @@ -169,7 +169,7 @@ func TestAccountCustomNameserver_GetEligibleZones(t *testing.T) { }`) } - mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/custom_ns/availability", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/custom_ns/availability", handler) want := []string{ "example.com", "example2.com", @@ -178,7 +178,8 @@ func TestAccountCustomNameserver_GetEligibleZones(t *testing.T) { actual, err := client.GetEligibleZonesAccountCustomNameservers( context.Background(), - AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), + AccountIdentifier(testAccountID), + GetEligibleZonesAccountCustomNameserversParams{}, ) if assert.NoError(t, err) { @@ -205,7 +206,7 @@ func TestAccountCustomNameserver_GetAccountCustomNameserverZoneMetadata(t *testi }`) } - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/custom_ns", handler) + mux.HandleFunc("/zones/"+testZoneID+"/custom_ns", handler) want := CustomNameserverZoneMetadata{ Type: "account", NSSet: "1", @@ -214,7 +215,8 @@ func TestAccountCustomNameserver_GetAccountCustomNameserverZoneMetadata(t *testi actual, err := client.GetCustomNameserverZoneMetadata( context.Background(), - ZoneIdentifier("023e105f4ecef8ad9ca31a8372d0c353"), + ZoneIdentifier(testZoneID), + GetCustomNameserverZoneMetadataParams{}, ) if assert.NoError(t, err) { From 9f347f30b84aec2ca687d370f910a6745d077068 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 14 Jun 2023 15:11:17 +1000 Subject: [PATCH 026/130] return err, not `nil` --- custom_nameservers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_nameservers.go b/custom_nameservers.go index 17836c883cd..45150a2111d 100644 --- a/custom_nameservers.go +++ b/custom_nameservers.go @@ -202,7 +202,7 @@ func (api *API) UpdateCustomNameserverZoneMetadata(ctx context.Context, rc *Reso params.Type = "" _, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { - return nil + return err } return nil From 5237e486f2a39aa4432b185af29e860fa30704f9 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 14 Jun 2023 05:15:58 +0000 Subject: [PATCH 027/130] Update CHANGELOG.md for #1304 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0b42dd98ec..c5e550770c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ENHANCEMENTS: +* custom_nameservers: add support for managing custom nameservers ([#1304](https://github.com/cloudflare/cloudflare-go/issues/1304)) * load_balancing: extend documentation for least_outstanding_requests steering policy ([#1293](https://github.com/cloudflare/cloudflare-go/issues/1293)) DEPENDENCIES: From 6a394db76e2dab571369df3ef70ac48559fec5a9 Mon Sep 17 00:00:00 2001 From: Yawar Jamal Date: Mon, 24 Apr 2023 15:00:17 -0500 Subject: [PATCH 028/130] Add cookie_suffix and additional_routes to WR object --- waiting_room.go | 46 ++++++++++++++++++++++++++------------------ waiting_room_test.go | 6 +++++- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/waiting_room.go b/waiting_room.go index 737e49dc494..fe0ed76f117 100644 --- a/waiting_room.go +++ b/waiting_room.go @@ -16,25 +16,27 @@ var ( // WaitingRoom describes a WaitingRoom object. type WaitingRoom struct { - CreatedOn time.Time `json:"created_on,omitempty"` - ModifiedOn time.Time `json:"modified_on,omitempty"` - Path string `json:"path"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - QueueingMethod string `json:"queueing_method,omitempty"` - CustomPageHTML string `json:"custom_page_html,omitempty"` - DefaultTemplateLanguage string `json:"default_template_language,omitempty"` - Host string `json:"host"` - ID string `json:"id,omitempty"` - NewUsersPerMinute int `json:"new_users_per_minute"` - TotalActiveUsers int `json:"total_active_users"` - SessionDuration int `json:"session_duration"` - QueueAll bool `json:"queue_all"` - DisableSessionRenewal bool `json:"disable_session_renewal"` - Suspended bool `json:"suspended"` - JsonResponseEnabled bool `json:"json_response_enabled"` - NextEventPrequeueStartTime *time.Time `json:"next_event_prequeue_start_time,omitempty"` - NextEventStartTime *time.Time `json:"next_event_start_time,omitempty"` + CreatedOn time.Time `json:"created_on,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Path string `json:"path"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + QueueingMethod string `json:"queueing_method,omitempty"` + CustomPageHTML string `json:"custom_page_html,omitempty"` + DefaultTemplateLanguage string `json:"default_template_language,omitempty"` + Host string `json:"host"` + ID string `json:"id,omitempty"` + NewUsersPerMinute int `json:"new_users_per_minute"` + TotalActiveUsers int `json:"total_active_users"` + SessionDuration int `json:"session_duration"` + QueueAll bool `json:"queue_all"` + DisableSessionRenewal bool `json:"disable_session_renewal"` + Suspended bool `json:"suspended"` + JsonResponseEnabled bool `json:"json_response_enabled"` + NextEventPrequeueStartTime *time.Time `json:"next_event_prequeue_start_time,omitempty"` + NextEventStartTime *time.Time `json:"next_event_start_time,omitempty"` + CookieSuffix string `json:"cookie_suffix"` + AdditionalRoutes []*WaitingRoomRoute `json:"additional_routes,omitempty"` } // WaitingRoomStatus describes the status of a waiting room. @@ -92,6 +94,12 @@ type WaitingRoomPagePreviewCustomHTML struct { CustomHTML string `json:"custom_html"` } +// WaitingRoomRoute describes a WaitingRoomRoute object. +type WaitingRoomRoute struct { + Host string `json:"host"` + Path string `json:"path"` +} + // WaitingRoomDetailResponse is the API response, containing a single WaitingRoom. type WaitingRoomDetailResponse struct { Response diff --git a/waiting_room_test.go b/waiting_room_test.go index 057789906bf..df7e0da6bde 100644 --- a/waiting_room_test.go +++ b/waiting_room_test.go @@ -39,7 +39,9 @@ var waitingRoomJSON = fmt.Sprintf(` "custom_page_html": "{{#waitTimeKnown}} {{waitTime}} mins {{/waitTimeKnown}} {{^waitTimeKnown}} Queue all enabled {{/waitTimeKnown}}", "default_template_language": "en-US", "next_event_prequeue_start_time": null, - "next_event_start_time": "%s" + "next_event_start_time": "%s", + "cookie_suffix": "example_shop", + "additional_routes": [{"host": "shop2.example.com", "path": "/shop/checkout"}] } `, waitingRoomID, testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoom.Format(time.RFC3339Nano), testTimestampWaitingRoomEventStart.Format(time.RFC3339Nano)) @@ -123,6 +125,8 @@ var waitingRoom = WaitingRoom{ DefaultTemplateLanguage: "en-US", NextEventStartTime: &testTimestampWaitingRoomEventStart, NextEventPrequeueStartTime: nil, + CookieSuffix: "example_shop", + AdditionalRoutes: []*WaitingRoomRoute{{Host: "shop2.example.com", Path: "/shop/checkout"}}, } var waitingRoomEvent = WaitingRoomEvent{ From 9b624a06e7698644fece2a519abb32e5b051a47b Mon Sep 17 00:00:00 2001 From: Yawar Jamal Date: Thu, 15 Jun 2023 09:33:20 -0500 Subject: [PATCH 029/130] add changelog message --- .changelog/1311.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1311.txt diff --git a/.changelog/1311.txt b/.changelog/1311.txt new file mode 100644 index 00000000000..a10742670b1 --- /dev/null +++ b/.changelog/1311.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +waiting_room: add support for two new fields, namely, `additional_routes` and `cookie_suffix` +``` From 74e0b34cc19a48b158d6996d94fa21b0612854aa Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 16 Jun 2023 15:20:38 +1000 Subject: [PATCH 030/130] update changelog --- .changelog/1311.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/1311.txt b/.changelog/1311.txt index a10742670b1..46639f877c1 100644 --- a/.changelog/1311.txt +++ b/.changelog/1311.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -waiting_room: add support for two new fields, namely, `additional_routes` and `cookie_suffix` +waiting_room: add support for `additional_routes` and `cookie_suffix` ``` From 1dc4830b798b195b8cb31ce16ac132995600a92d Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 16 Jun 2023 05:23:00 +0000 Subject: [PATCH 031/130] Update CHANGELOG.md for #1311 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e550770c3..396cb563359 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ENHANCEMENTS: * custom_nameservers: add support for managing custom nameservers ([#1304](https://github.com/cloudflare/cloudflare-go/issues/1304)) * load_balancing: extend documentation for least_outstanding_requests steering policy ([#1293](https://github.com/cloudflare/cloudflare-go/issues/1293)) +* waiting_room: add support for `additional_routes` and `cookie_suffix` ([#1311](https://github.com/cloudflare/cloudflare-go/issues/1311)) DEPENDENCIES: From 61ef8fe5c609fa38b120e3bf716a6abd42600f7d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 16 Jun 2023 16:01:03 +1000 Subject: [PATCH 032/130] Create conventions.md --- docs/conventions.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/conventions.md diff --git a/docs/conventions.md b/docs/conventions.md new file mode 100644 index 00000000000..7cd0189499e --- /dev/null +++ b/docs/conventions.md @@ -0,0 +1,40 @@ +# Conventions + +This document aims to cover the conventions and guidance to consider when +making changes the Go SDK. + +## Methods + +- All methods should take a maxium of 3 parameter. See examples in [experimental](./experimental.md) +- The first parameter is always `context.Context`. +- The second is a `*ResourceContainer`. +- The final is a struct of available parameters for the method. + - The parameter naming convention should be `Params`. Example: + method name of `GetDNSRecords` has a struct parameter name of + `GetDNSRecordsParams`. + - Do not share parameter structs between methods. Each should have a dedicated + one. + - Even if you don't intend to have parameter configurations, you should add + the third parameter to your method signature for future flexibility. + +## Types + +### Booleans + +- Should always be represented as pointers in structs with an `omitempty` + marshaling tag (most commonly as JSON). This ensures you can determine unset, + false and truthy values. + +### `time.Time` + +- Should always be represented as pointers in structs. + +### Ports (0-65535) + +- Should use `uint16` unless you have a reason to restrict the port range in + which case, you should also provide a validator on the type. + +## Marshaling/unmarshaling + +- Avoid custom marshal/unmarshal handlers unless absolutely necessary. They can + be difficult to debug in a larger codebase. From 99661e0edb35293e2dd93276c860d1714ae374ae Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Jun 2023 14:55:09 +1000 Subject: [PATCH 033/130] railgun: remove from SDK Cloudflare has announced Railgun[1] is being deprecated. To support this deprecation, we are removing the endpoints going forward in the SDK. [1]: https://blog.cloudflare.com/deprecating-railgun/ --- .changelog/1312.txt | 3 + railgun.go | 298 --------------------- railgun_test.go | 622 -------------------------------------------- 3 files changed, 3 insertions(+), 920 deletions(-) create mode 100644 .changelog/1312.txt delete mode 100644 railgun.go delete mode 100644 railgun_test.go diff --git a/.changelog/1312.txt b/.changelog/1312.txt new file mode 100644 index 00000000000..9d3d216d119 --- /dev/null +++ b/.changelog/1312.txt @@ -0,0 +1,3 @@ +```release-note:breaking-change +railgun: remove support for railgun +``` diff --git a/railgun.go b/railgun.go deleted file mode 100644 index e189124131b..00000000000 --- a/railgun.go +++ /dev/null @@ -1,298 +0,0 @@ -package cloudflare - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/url" - "time" -) - -// Railgun represents a Railgun's properties. -type Railgun struct { - ID string `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Enabled bool `json:"enabled"` - ZonesConnected int `json:"zones_connected"` - Build string `json:"build"` - Version string `json:"version"` - Revision string `json:"revision"` - ActivationKey string `json:"activation_key"` - ActivatedOn time.Time `json:"activated_on"` - CreatedOn time.Time `json:"created_on"` - ModifiedOn time.Time `json:"modified_on"` - UpgradeInfo struct { - LatestVersion string `json:"latest_version"` - DownloadLink string `json:"download_link"` - } `json:"upgrade_info"` -} - -// RailgunListOptions represents the parameters used to list railguns. -type RailgunListOptions struct { - Direction string -} - -// railgunResponse represents the response from the Create Railgun and the Railgun Details endpoints. -type railgunResponse struct { - Response - Result Railgun `json:"result"` -} - -// railgunsResponse represents the response from the List Railguns endpoint. -type railgunsResponse struct { - Response - Result []Railgun `json:"result"` -} - -// CreateRailgun creates a new Railgun. -// -// API reference: https://api.cloudflare.com/#railgun-create-railgun -func (api *API) CreateRailgun(ctx context.Context, name string) (Railgun, error) { - uri := fmt.Sprintf("%s/railguns", api.userBaseURL("")) - params := struct { - Name string `json:"name"` - }{ - Name: name, - } - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) - if err != nil { - return Railgun{}, err - } - var r railgunResponse - if err := json.Unmarshal(res, &r); err != nil { - return Railgun{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// ListRailguns lists Railguns connected to an account. -// -// API reference: https://api.cloudflare.com/#railgun-list-railguns -func (api *API) ListRailguns(ctx context.Context, options RailgunListOptions) ([]Railgun, error) { - v := url.Values{} - if options.Direction != "" { - v.Set("direction", options.Direction) - } - uri := fmt.Sprintf("%s/railguns?%s", api.userBaseURL(""), v.Encode()) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return nil, err - } - var r railgunsResponse - if err := json.Unmarshal(res, &r); err != nil { - return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// RailgunDetails returns the details for a Railgun. -// -// API reference: https://api.cloudflare.com/#railgun-railgun-details -func (api *API) RailgunDetails(ctx context.Context, railgunID string) (Railgun, error) { - uri := fmt.Sprintf("%s/railguns/%s", api.userBaseURL(""), railgunID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return Railgun{}, err - } - var r railgunResponse - if err := json.Unmarshal(res, &r); err != nil { - return Railgun{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// RailgunZones returns the zones that are currently using a Railgun. -// -// API reference: https://api.cloudflare.com/#railgun-get-zones-connected-to-a-railgun -func (api *API) RailgunZones(ctx context.Context, railgunID string) ([]Zone, error) { - uri := fmt.Sprintf("%s/railguns/%s/zones", api.userBaseURL(""), railgunID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return nil, err - } - var r ZonesResponse - if err := json.Unmarshal(res, &r); err != nil { - return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// enableRailgun enables (true) or disables (false) a Railgun for all zones connected to it. -// -// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun -func (api *API) enableRailgun(ctx context.Context, railgunID string, enable bool) (Railgun, error) { - uri := fmt.Sprintf("%s/railguns/%s", api.userBaseURL(""), railgunID) - params := struct { - Enabled bool `json:"enabled"` - }{ - Enabled: enable, - } - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) - if err != nil { - return Railgun{}, err - } - var r railgunResponse - if err := json.Unmarshal(res, &r); err != nil { - return Railgun{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// EnableRailgun enables a Railgun for all zones connected to it. -// -// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun -func (api *API) EnableRailgun(ctx context.Context, railgunID string) (Railgun, error) { - return api.enableRailgun(ctx, railgunID, true) -} - -// DisableRailgun enables a Railgun for all zones connected to it. -// -// API reference: https://api.cloudflare.com/#railgun-enable-or-disable-a-railgun -func (api *API) DisableRailgun(ctx context.Context, railgunID string) (Railgun, error) { - return api.enableRailgun(ctx, railgunID, false) -} - -// DeleteRailgun disables and deletes a Railgun. -// -// API reference: https://api.cloudflare.com/#railgun-delete-railgun -func (api *API) DeleteRailgun(ctx context.Context, railgunID string) error { - uri := fmt.Sprintf("%s/railguns/%s", api.userBaseURL(""), railgunID) - if _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil); err != nil { - return err - } - return nil -} - -// ZoneRailgun represents the status of a Railgun on a zone. -type ZoneRailgun struct { - ID string `json:"id"` - Name string `json:"name"` - Enabled bool `json:"enabled"` - Connected bool `json:"connected"` -} - -// zoneRailgunResponse represents the response from the Zone Railgun Details endpoint. -type zoneRailgunResponse struct { - Response - Result ZoneRailgun `json:"result"` -} - -// zoneRailgunsResponse represents the response from the Zone Railgun endpoint. -type zoneRailgunsResponse struct { - Response - Result []ZoneRailgun `json:"result"` -} - -// RailgunDiagnosis represents the test results from testing railgun connections -// to a zone. -type RailgunDiagnosis struct { - Method string `json:"method"` - HostName string `json:"host_name"` - HTTPStatus int `json:"http_status"` - Railgun string `json:"railgun"` - URL string `json:"url"` - ResponseStatus string `json:"response_status"` - Protocol string `json:"protocol"` - ElapsedTime string `json:"elapsed_time"` - BodySize string `json:"body_size"` - BodyHash string `json:"body_hash"` - MissingHeaders string `json:"missing_headers"` - ConnectionClose bool `json:"connection_close"` - Cloudflare string `json:"cloudflare"` - CFRay string `json:"cf-ray"` - // NOTE: Cloudflare's online API documentation does not yet have definitions - // for the following fields. See: https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection/ - CFWANError string `json:"cf-wan-error"` - CFCacheStatus string `json:"cf-cache-status"` -} - -// railgunDiagnosisResponse represents the response from the Test Railgun Connection endpoint. -type railgunDiagnosisResponse struct { - Response - Result RailgunDiagnosis `json:"result"` -} - -// ZoneRailguns returns the available Railguns for a zone. -// -// API reference: https://api.cloudflare.com/#railguns-for-a-zone-get-available-railguns -func (api *API) ZoneRailguns(ctx context.Context, zoneID string) ([]ZoneRailgun, error) { - uri := fmt.Sprintf("/zones/%s/railguns", zoneID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return nil, err - } - var r zoneRailgunsResponse - if err := json.Unmarshal(res, &r); err != nil { - return nil, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// ZoneRailgunDetails returns the configuration for a given Railgun. -// -// API reference: https://api.cloudflare.com/#railguns-for-a-zone-get-railgun-details -func (api *API) ZoneRailgunDetails(ctx context.Context, zoneID, railgunID string) (ZoneRailgun, error) { - uri := fmt.Sprintf("/zones/%s/railguns/%s", zoneID, railgunID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return ZoneRailgun{}, err - } - var r zoneRailgunResponse - if err := json.Unmarshal(res, &r); err != nil { - return ZoneRailgun{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// TestRailgunConnection tests a Railgun connection for a given zone. -// -// API reference: https://api.cloudflare.com/#railgun-connections-for-a-zone-test-railgun-connection -func (api *API) TestRailgunConnection(ctx context.Context, zoneID, railgunID string) (RailgunDiagnosis, error) { - uri := fmt.Sprintf("/zones/%s/railguns/%s/diagnose", zoneID, railgunID) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return RailgunDiagnosis{}, err - } - var r railgunDiagnosisResponse - if err := json.Unmarshal(res, &r); err != nil { - return RailgunDiagnosis{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// connectZoneRailgun connects (true) or disconnects (false) a Railgun for a given zone. -// -// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun -func (api *API) connectZoneRailgun(ctx context.Context, zoneID, railgunID string, connect bool) (ZoneRailgun, error) { - uri := fmt.Sprintf("/zones/%s/railguns/%s", zoneID, railgunID) - params := struct { - Connected bool `json:"connected"` - }{ - Connected: connect, - } - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) - if err != nil { - return ZoneRailgun{}, err - } - var r zoneRailgunResponse - if err := json.Unmarshal(res, &r); err != nil { - return ZoneRailgun{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return r.Result, nil -} - -// ConnectZoneRailgun connects a Railgun for a given zone. -// -// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun -func (api *API) ConnectZoneRailgun(ctx context.Context, zoneID, railgunID string) (ZoneRailgun, error) { - return api.connectZoneRailgun(ctx, zoneID, railgunID, true) -} - -// DisconnectZoneRailgun disconnects a Railgun for a given zone. -// -// API reference: https://api.cloudflare.com/#railguns-for-a-zone-connect-or-disconnect-a-railgun -func (api *API) DisconnectZoneRailgun(ctx context.Context, zoneID, railgunID string) (ZoneRailgun, error) { - return api.connectZoneRailgun(ctx, zoneID, railgunID, false) -} diff --git a/railgun_test.go b/railgun_test.go deleted file mode 100644 index e80c146c853..00000000000 --- a/railgun_test.go +++ /dev/null @@ -1,622 +0,0 @@ -package cloudflare - -import ( - "context" - "fmt" - "io" - "net/http" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestCreateRailgun(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") - b, err := io.ReadAll(r.Body) - defer r.Body.Close() - if assert.NoError(t, err) { - assert.JSONEq(t, `{"name":"My Railgun"}`, string(b)) - } - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "status": "active", - "enabled": true, - "zones_connected": 2, - "build": "b1234", - "version": "2.1", - "revision": "123", - "activation_key": "e4edc00281cb56ebac22c81be9bac8f3", - "activated_on": "2014-01-02T02:20:00Z", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z" - } - }`) - } - - mux.HandleFunc("/railguns", handler) - activatedOn, _ := time.Parse(time.RFC3339, "2014-01-02T02:20:00Z") - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := Railgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Status: "active", - Enabled: true, - ZonesConnected: 2, - Build: "b1234", - Version: "2.1", - Revision: "123", - ActivationKey: "e4edc00281cb56ebac22c81be9bac8f3", - ActivatedOn: activatedOn, - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - } - - actual, err := client.CreateRailgun(context.Background(), "My Railgun") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } -} - -func TestListRailguns(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": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "status": "active", - "enabled": true, - "zones_connected": 2, - "build": "b1234", - "version": "2.1", - "revision": "123", - "activation_key": "e4edc00281cb56ebac22c81be9bac8f3", - "activated_on": "2014-01-02T02:20:00Z", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z" - } - ], - "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 2000 - } - }`) - } - - mux.HandleFunc("/railguns", handler) - activatedOn, _ := time.Parse(time.RFC3339, "2014-01-02T02:20:00Z") - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := []Railgun{ - { - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Status: "active", - Enabled: true, - ZonesConnected: 2, - Build: "b1234", - Version: "2.1", - Revision: "123", - ActivationKey: "e4edc00281cb56ebac22c81be9bac8f3", - ActivatedOn: activatedOn, - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - }, - } - - actual, err := client.ListRailguns(context.Background(), RailgunListOptions{Direction: "desc"}) - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } -} - -func TestRailgunDetails(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": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "status": "active", - "enabled": true, - "zones_connected": 2, - "build": "b1234", - "version": "2.1", - "revision": "123", - "activation_key": "e4edc00281cb56ebac22c81be9bac8f3", - "activated_on": "2014-01-02T02:20:00Z", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z" - } - }`) - } - - mux.HandleFunc("/railguns/e928d310693a83094309acf9ead50448", handler) - activatedOn, _ := time.Parse(time.RFC3339, "2014-01-02T02:20:00Z") - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := Railgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Status: "active", - Enabled: true, - ZonesConnected: 2, - Build: "b1234", - Version: "2.1", - Revision: "123", - ActivationKey: "e4edc00281cb56ebac22c81be9bac8f3", - ActivatedOn: activatedOn, - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - } - - actual, err := client.RailgunDetails(context.Background(), "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.RailgunDetails(context.Background(), "bar") - assert.Error(t, err) -} - -func TestRailgunZones(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": "023e105f4ecef8ad9ca31a8372d0c353", - "name": "example.com", - "development_mode": 7200, - "original_name_servers": [ - "ns1.originaldnshost.com", - "ns2.originaldnshost.com" - ], - "original_registrar": "GoDaddy", - "original_dnshost": "NameCheap", - "created_on": "2014-01-01T05:20:00.12345Z", - "modified_on": "2014-01-01T05:20:00.12345Z" - } - ], - "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 2000 - } - }`) - } - - mux.HandleFunc("/railguns/e928d310693a83094309acf9ead50448/zones", handler) - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - want := []Zone{ - { - ID: "023e105f4ecef8ad9ca31a8372d0c353", - Name: "example.com", - DevMode: 7200, - OriginalNS: []string{"ns1.originaldnshost.com", "ns2.originaldnshost.com"}, - OriginalRegistrar: "GoDaddy", - OriginalDNSHost: "NameCheap", - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - }, - } - - actual, err := client.RailgunZones(context.Background(), "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.RailgunZones(context.Background(), "bar") - assert.Error(t, err) -} - -func TestEnableRailgun(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) - b, err := io.ReadAll(r.Body) - defer r.Body.Close() - if assert.NoError(t, err) { - assert.JSONEq(t, `{"enabled":true}`, string(b)) - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "status": "active", - "enabled": true, - "zones_connected": 2, - "build": "b1234", - "version": "2.1", - "revision": "123", - "activation_key": "e4edc00281cb56ebac22c81be9bac8f3", - "activated_on": "2014-01-02T02:20:00Z", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z" - } - }`) - } - - mux.HandleFunc("/railguns/e928d310693a83094309acf9ead50448", handler) - activatedOn, _ := time.Parse(time.RFC3339, "2014-01-02T02:20:00Z") - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := Railgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Status: "active", - Enabled: true, - ZonesConnected: 2, - Build: "b1234", - Version: "2.1", - Revision: "123", - ActivationKey: "e4edc00281cb56ebac22c81be9bac8f3", - ActivatedOn: activatedOn, - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - } - - actual, err := client.EnableRailgun(context.Background(), "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.EnableRailgun(context.Background(), "bar") - assert.Error(t, err) -} - -func TestDisableRailgun(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) - b, err := io.ReadAll(r.Body) - defer r.Body.Close() - if assert.NoError(t, err) { - assert.JSONEq(t, `{"enabled":false}`, string(b)) - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "status": "active", - "enabled": false, - "zones_connected": 2, - "build": "b1234", - "version": "2.1", - "revision": "123", - "activation_key": "e4edc00281cb56ebac22c81be9bac8f3", - "activated_on": "2014-01-02T02:20:00Z", - "created_on": "2014-01-01T05:20:00Z", - "modified_on": "2014-01-01T05:20:00Z" - } - }`) - } - - mux.HandleFunc("/railguns/e928d310693a83094309acf9ead50448", handler) - activatedOn, _ := time.Parse(time.RFC3339, "2014-01-02T02:20:00Z") - createdOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - modifiedOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00Z") - want := Railgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Status: "active", - Enabled: false, - ZonesConnected: 2, - Build: "b1234", - Version: "2.1", - Revision: "123", - ActivationKey: "e4edc00281cb56ebac22c81be9bac8f3", - ActivatedOn: activatedOn, - CreatedOn: createdOn, - ModifiedOn: modifiedOn, - } - - actual, err := client.DisableRailgun(context.Background(), "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.DisableRailgun(context.Background(), "bar") - assert.Error(t, err) -} - -func TestDeleteRailgun(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": "e928d310693a83094309acf9ead50448" - } - }`) - } - - mux.HandleFunc("/railguns/e928d310693a83094309acf9ead50448", handler) - assert.NoError(t, client.DeleteRailgun(context.Background(), "e928d310693a83094309acf9ead50448")) - assert.Error(t, client.DeleteRailgun(context.Background(), "bar")) -} - -func TestZoneRailguns(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": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "enabled": true, - "connected": true - } - ], - "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 2000 - } - }`) - } - - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/railguns", handler) - want := []ZoneRailgun{ - { - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Enabled: true, - Connected: true, - }, - } - - actual, err := client.ZoneRailguns(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.ZoneRailguns(context.Background(), "bar") - assert.Error(t, err) -} - -func TestZoneRailgunDetails(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": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "enabled": true, - "connected": true - } - }`) - } - - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/railguns/e928d310693a83094309acf9ead50448", handler) - want := ZoneRailgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Enabled: true, - Connected: true, - } - - actual, err := client.ZoneRailgunDetails(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.ZoneRailgunDetails(context.Background(), "bar", "baz") - assert.Error(t, err) -} - -func TestTestRailgunConnection(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": { - "method": "GET", - "host_name": "www.example.com", - "http_status": 200, - "railgun": "on", - "url": "https://www.cloudflare.com", - "response_status": "200 OK", - "protocol": "HTTP/1.1", - "elapsed_time": "0.239013s", - "body_size": "63910 bytes", - "body_hash": "be27f2429421e12f200cab1da43ba301bdc70e1d", - "missing_headers": "No Content-Length or Transfer-Encoding", - "connection_close": false, - "cloudflare": "on", - "cf-ray": "1ddd7570575207d9-LAX", - "cf-wan-error": null, - "cf-cache-status": null - } - }`) - } - - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/railguns/e928d310693a83094309acf9ead50448/diagnose", handler) - want := RailgunDiagnosis{ - Method: http.MethodGet, - HostName: "www.example.com", - HTTPStatus: 200, - Railgun: "on", - URL: "https://www.cloudflare.com", - ResponseStatus: "200 OK", - Protocol: "HTTP/1.1", - ElapsedTime: "0.239013s", - BodySize: "63910 bytes", - BodyHash: "be27f2429421e12f200cab1da43ba301bdc70e1d", - MissingHeaders: "No Content-Length or Transfer-Encoding", - ConnectionClose: false, - Cloudflare: "on", - CFRay: "1ddd7570575207d9-LAX", - CFWANError: "", - CFCacheStatus: "", - } - - actual, err := client.TestRailgunConnection(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.TestRailgunConnection(context.Background(), "bar", "baz") - assert.Error(t, err) -} - -func TestConnectRailgun(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) - b, err := io.ReadAll(r.Body) - defer r.Body.Close() - if assert.NoError(t, err) { - assert.JSONEq(t, `{"connected":true}`, string(b)) - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "enabled": true, - "connected": true - } - }`) - } - - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/railguns/e928d310693a83094309acf9ead50448", handler) - want := ZoneRailgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Enabled: true, - Connected: true, - } - - actual, err := client.ConnectZoneRailgun(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.ConnectZoneRailgun(context.Background(), "bar", "baz") - assert.Error(t, err) -} - -func TestDisconnectRailgun(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) - b, err := io.ReadAll(r.Body) - defer r.Body.Close() - if assert.NoError(t, err) { - assert.JSONEq(t, `{"connected":false}`, string(b)) - } - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "success": true, - "errors": [], - "messages": [], - "result": { - "id": "e928d310693a83094309acf9ead50448", - "name": "My Railgun", - "enabled": true, - "connected": false - } - }`) - } - - mux.HandleFunc("/zones/023e105f4ecef8ad9ca31a8372d0c353/railguns/e928d310693a83094309acf9ead50448", handler) - want := ZoneRailgun{ - ID: "e928d310693a83094309acf9ead50448", - Name: "My Railgun", - Enabled: true, - Connected: false, - } - - actual, err := client.DisconnectZoneRailgun(context.Background(), "023e105f4ecef8ad9ca31a8372d0c353", "e928d310693a83094309acf9ead50448") - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } - - _, err = client.DisconnectZoneRailgun(context.Background(), "bar", "baz") - assert.Error(t, err) -} From 360920110bbdc97fa165d42cd8aa22278ffe29f1 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Jun 2023 15:46:30 +1000 Subject: [PATCH 034/130] virtualdns: remove support from SDK This was an alias for the newer DNS firewall. Since we are revampign the DNS firewall file, we should remove this now to avoid introducing breaking changes to these older methods. --- virtualdns.go | 165 --------------------------------------------- virtualdns_test.go | 78 --------------------- 2 files changed, 243 deletions(-) delete mode 100644 virtualdns.go delete mode 100644 virtualdns_test.go diff --git a/virtualdns.go b/virtualdns.go deleted file mode 100644 index d4bc91bd96b..00000000000 --- a/virtualdns.go +++ /dev/null @@ -1,165 +0,0 @@ -package cloudflare - -import ( - "context" - "fmt" -) - -// NOTE: Everything in this file is deprecated. See `dns_firewall.go` instead. - -// VirtualDNS represents a Virtual DNS configuration. -// -// Deprecated: Use DNSFirewallCluster instead. -type VirtualDNS struct { - ID string `json:"id"` - Name string `json:"name"` - OriginIPs []string `json:"origin_ips"` - VirtualDNSIPs []string `json:"virtual_dns_ips"` - MinimumCacheTTL uint `json:"minimum_cache_ttl"` - MaximumCacheTTL uint `json:"maximum_cache_ttl"` - DeprecateAnyRequests bool `json:"deprecate_any_requests"` - ModifiedOn string `json:"modified_on"` -} - -// VirtualDNSAnalyticsMetrics represents a group of aggregated Virtual DNS metrics. -// -// Deprecated: Use DNSFirewallAnalyticsMetrics instead. -type VirtualDNSAnalyticsMetrics DNSFirewallAnalyticsMetrics - -// VirtualDNSAnalytics represents a set of aggregated Virtual DNS metrics. -// -// Deprecated: Use DNSFirewallAnalytics instead. -type VirtualDNSAnalytics struct { - Totals VirtualDNSAnalyticsMetrics `json:"totals"` - Min VirtualDNSAnalyticsMetrics `json:"min"` - Max VirtualDNSAnalyticsMetrics `json:"max"` -} - -// VirtualDNSUserAnalyticsOptions represents range and dimension selection on analytics endpoint -// -// Deprecated: Use DNSFirewallUserAnalyticsOptions instead. -type VirtualDNSUserAnalyticsOptions DNSFirewallUserAnalyticsOptions - -// VirtualDNSResponse represents a Virtual DNS response. -// -// Deprecated: This internal type will be removed in the future. -type VirtualDNSResponse struct { - Response - Result *VirtualDNS `json:"result"` -} - -// VirtualDNSListResponse represents an array of Virtual DNS responses. -// -// Deprecated: This internal type will be removed in the future. -type VirtualDNSListResponse struct { - Response - Result []*VirtualDNS `json:"result"` -} - -// VirtualDNSAnalyticsResponse represents a Virtual DNS analytics response. -// -// Deprecated: This internal type will be removed in the future. -type VirtualDNSAnalyticsResponse struct { - Response - Result VirtualDNSAnalytics `json:"result"` -} - -// CreateVirtualDNS creates a new Virtual DNS cluster. -// -// Deprecated: Use CreateDNSFirewallCluster instead. -func (api *API) CreateVirtualDNS(ctx context.Context, v *VirtualDNS) (*VirtualDNS, error) { - if v == nil { - return nil, fmt.Errorf("cluster must not be nil") - } - - res, err := api.CreateDNSFirewallCluster(ctx, v.vdnsUpgrade()) - return res.vdnsDowngrade(), err -} - -// VirtualDNS fetches a single virtual DNS cluster. -// -// Deprecated: Use DNSFirewallCluster instead. -func (api *API) VirtualDNS(ctx context.Context, virtualDNSID string) (*VirtualDNS, error) { - res, err := api.DNSFirewallCluster(ctx, virtualDNSID) - return res.vdnsDowngrade(), err -} - -// ListVirtualDNS lists the virtual DNS clusters associated with an account. -// -// Deprecated: Use ListDNSFirewallClusters instead. -func (api *API) ListVirtualDNS(ctx context.Context) ([]*VirtualDNS, error) { - res, err := api.ListDNSFirewallClusters(ctx) - if res == nil { - return nil, err - } - - clusters := make([]*VirtualDNS, 0, len(res)) - for _, cluster := range res { - clusters = append(clusters, cluster.vdnsDowngrade()) - } - - return clusters, err -} - -// UpdateVirtualDNS updates a Virtual DNS cluster. -// -// Deprecated: Use UpdateDNSFirewallCluster instead. -func (api *API) UpdateVirtualDNS(ctx context.Context, virtualDNSID string, vv VirtualDNS) error { - return api.UpdateDNSFirewallCluster(ctx, virtualDNSID, vv.vdnsUpgrade()) -} - -// DeleteVirtualDNS deletes a Virtual DNS cluster. Note that this cannot be -// undone, and will stop all traffic to that cluster. -// -// Deprecated: Use DeleteDNSFirewallCluster instead. -func (api *API) DeleteVirtualDNS(ctx context.Context, virtualDNSID string) error { - return api.DeleteDNSFirewallCluster(ctx, virtualDNSID) -} - -// VirtualDNSUserAnalytics retrieves analytics report for a specified dimension and time range -// -// Deprecated: Use DNSFirewallUserAnalytics instead. -func (api *API) VirtualDNSUserAnalytics(ctx context.Context, virtualDNSID string, o VirtualDNSUserAnalyticsOptions) (VirtualDNSAnalytics, error) { - res, err := api.DNSFirewallUserAnalytics(ctx, virtualDNSID, DNSFirewallUserAnalyticsOptions(o)) - return res.vdnsDowngrade(), err -} - -// --- Compatibility helper functions --- - -func (v VirtualDNS) vdnsUpgrade() DNSFirewallCluster { - return DNSFirewallCluster{ - ID: v.ID, - Name: v.Name, - UpstreamIPs: v.OriginIPs, - DNSFirewallIPs: v.VirtualDNSIPs, - MinimumCacheTTL: v.MinimumCacheTTL, - MaximumCacheTTL: v.MaximumCacheTTL, - DeprecateAnyRequests: v.DeprecateAnyRequests, - ModifiedOn: v.ModifiedOn, - } -} - -func (v *DNSFirewallCluster) vdnsDowngrade() *VirtualDNS { - if v == nil { - return nil - } - - return &VirtualDNS{ - ID: v.ID, - Name: v.Name, - OriginIPs: v.UpstreamIPs, - VirtualDNSIPs: v.DNSFirewallIPs, - MinimumCacheTTL: v.MinimumCacheTTL, - MaximumCacheTTL: v.MaximumCacheTTL, - DeprecateAnyRequests: v.DeprecateAnyRequests, - ModifiedOn: v.ModifiedOn, - } -} - -func (v DNSFirewallAnalytics) vdnsDowngrade() VirtualDNSAnalytics { - return VirtualDNSAnalytics{ - Totals: VirtualDNSAnalyticsMetrics(v.Totals), - Min: VirtualDNSAnalyticsMetrics(v.Min), - Max: VirtualDNSAnalyticsMetrics(v.Max), - } -} diff --git a/virtualdns_test.go b/virtualdns_test.go deleted file mode 100644 index 9adcce6d904..00000000000 --- a/virtualdns_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package cloudflare - -import ( - "context" - "fmt" - "net/http" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestVirtualDNSUserAnalytics(t *testing.T) { - setup() - defer teardown() - - now := time.Now().UTC() - since := now.Add(-1 * time.Hour) - until := now - - handler := func(w http.ResponseWriter, r *http.Request) { - expectedMetrics := "queryCount,uncachedCount,staleCount,responseTimeAvg,responseTimeMedia,responseTime90th,responseTime99th" - - assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET'") - assert.Equal(t, expectedMetrics, r.URL.Query().Get("metrics"), "Expected many metrics in URL parameter") - assert.Equal(t, since.Format(time.RFC3339), r.URL.Query().Get("since"), "Expected since parameter in URL") - assert.Equal(t, until.Format(time.RFC3339), r.URL.Query().Get("until"), "Expected until parameter in URL") - - w.Header().Set("content-type", "application/json") - fmt.Fprint(w, `{ - "result": { - "totals":{ - "queryCount": 5, - "uncachedCount":6, - "staleCount":7, - "responseTimeAvg":1.0, - "responseTimeMedian":2.0, - "responseTime90th":3.0, - "responseTime99th":4.0 - } - }, - "success": true, - "errors": null, - "messages": null - }`) - } - - mux.HandleFunc("/user/dns_firewall/12345/dns_analytics/report", handler) - want := VirtualDNSAnalytics{ - Totals: VirtualDNSAnalyticsMetrics{ - QueryCount: int64Ptr(5), - UncachedCount: int64Ptr(6), - StaleCount: int64Ptr(7), - ResponseTimeAvg: float64Ptr(1.0), - ResponseTimeMedian: float64Ptr(2.0), - ResponseTime90th: float64Ptr(3.0), - ResponseTime99th: float64Ptr(4.0), - }, - } - - params := VirtualDNSUserAnalyticsOptions{ - Metrics: []string{ - "queryCount", - "uncachedCount", - "staleCount", - "responseTimeAvg", - "responseTimeMedia", - "responseTime90th", - "responseTime99th", - }, - Since: &since, - Until: &until, - } - actual, err := client.VirtualDNSUserAnalytics(context.Background(), "12345", params) - if assert.NoError(t, err) { - assert.Equal(t, want, actual) - } -} From 453ca7f6493fdf738f58176baeae1ebf9928ed6f Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Jun 2023 15:47:35 +1000 Subject: [PATCH 035/130] internal: add support for deprecated `/user` routes This shouldn't be used anywhere however, we can add support here until it's fully quashed as a concept in the services. --- resource.go | 5 +++++ resource_test.go | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/resource.go b/resource.go index 2113e5eba7d..481eae25ac7 100644 --- a/resource.go +++ b/resource.go @@ -27,6 +27,11 @@ func (rc *ResourceContainer) URLFragment() string { if rc.Level == "" { return rc.Identifier } + + if rc.Level == UserRouteLevel { + return "user" + } + return fmt.Sprintf("%s/%s", rc.Level, rc.Identifier) } diff --git a/resource_test.go b/resource_test.go index ef0c96d3122..0a9e82caa08 100644 --- a/resource_test.go +++ b/resource_test.go @@ -11,8 +11,11 @@ func TestResourcURLFragment(t *testing.T) { container *ResourceContainer want string }{ - "account resource": {container: AccountIdentifier("foo"), want: "accounts/foo"}, - "zone resource": {container: ZoneIdentifier("foo"), want: "zones/foo"}, + "account resource": {container: AccountIdentifier("foo"), want: "accounts/foo"}, + "zone resource": {container: ZoneIdentifier("foo"), want: "zones/foo"}, + // this is pretty well deprecated in favour of `AccountIdentifier` but + // here for completeness. + "user level resource": {container: UserIdentifier("foo"), want: "user"}, "missing level resource": {container: &ResourceContainer{Level: "", Identifier: "foo"}, want: "foo"}, } From 05c773d771ab4873da7def2b65602763abf10677 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Jun 2023 15:48:51 +1000 Subject: [PATCH 036/130] dns_firewall: modernise method conventions Updates the method conventions[1] to match the experimental client[2] bringing in more modern support and usage. [1]: https://github.com/cloudflare/cloudflare-go/blob/master/docs/conventions.md [2]: https://github.com/cloudflare/cloudflare-go/blob/master/docs/experimental.md --- dns_firewall.go | 96 +++++++++++++++++++++++++++----------------- dns_firewall_test.go | 93 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 53 deletions(-) diff --git a/dns_firewall.go b/dns_firewall.go index a6282aea209..064da15c749 100644 --- a/dns_firewall.go +++ b/dns_firewall.go @@ -3,13 +3,14 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" - "net/url" - "strings" "time" ) +var ErrMissingClusterID = errors.New("missing required cluster ID") + // DNSFirewallCluster represents a DNS Firewall configuration. type DNSFirewallCluster struct { ID string `json:"id,omitempty"` @@ -43,9 +44,9 @@ type DNSFirewallAnalytics struct { // DNSFirewallUserAnalyticsOptions represents range and dimension selection on analytics endpoint. type DNSFirewallUserAnalyticsOptions struct { - Metrics []string - Since *time.Time - Until *time.Time + Metrics []string `url:"metrics,omitempty" del:","` + Since *time.Time `url:"since,omitempty"` + Until *time.Time `url:"until,omitempty"` } // dnsFirewallResponse represents a DNS Firewall response. @@ -66,12 +67,42 @@ type dnsFirewallAnalyticsResponse struct { Result DNSFirewallAnalytics `json:"result"` } +type CreateDNSFirewallClusterParams struct { + Name string `json:"name"` + 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"` + DeprecateAnyRequests bool `json:"deprecate_any_requests"` +} + +type GetDNSFirewallClusterParams struct { + ClusterID string `json:"-"` +} + +type UpdateDNSFirewallClusterParams struct { + ClusterID string `json:"-"` + Name string `json:"name"` + 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"` + DeprecateAnyRequests bool `json:"deprecate_any_requests"` +} + +type ListDNSFirewallClustersParams struct{} + +type GetDNSFirewallUserAnalyticsParams struct { + ClusterID string `json:"-"` + DNSFirewallUserAnalyticsOptions +} + // CreateDNSFirewallCluster creates a new DNS Firewall cluster. // // API reference: https://api.cloudflare.com/#dns-firewall-create-dns-firewall-cluster -func (api *API) CreateDNSFirewallCluster(ctx context.Context, v DNSFirewallCluster) (*DNSFirewallCluster, error) { - uri := fmt.Sprintf("%s/dns_firewall", api.userBaseURL("/user")) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, v) +func (api *API) CreateDNSFirewallCluster(ctx context.Context, rc *ResourceContainer, params CreateDNSFirewallClusterParams) (*DNSFirewallCluster, error) { + uri := fmt.Sprintf("/%s/dns_firewall", rc.URLFragment()) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return nil, err } @@ -85,11 +116,15 @@ func (api *API) CreateDNSFirewallCluster(ctx context.Context, v DNSFirewallClust return response.Result, nil } -// DNSFirewallCluster fetches a single DNS Firewall cluster. +// GetDNSFirewallCluster fetches a single DNS Firewall cluster. // // API reference: https://api.cloudflare.com/#dns-firewall-dns-firewall-cluster-details -func (api *API) DNSFirewallCluster(ctx context.Context, clusterID string) (*DNSFirewallCluster, error) { - uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) +func (api *API) GetDNSFirewallCluster(ctx context.Context, rc *ResourceContainer, params GetDNSFirewallClusterParams) (*DNSFirewallCluster, error) { + if params.ClusterID == "" { + return &DNSFirewallCluster{}, ErrMissingClusterID + } + + uri := fmt.Sprintf("/%s/dns_firewall/%s", rc.URLFragment(), params.ClusterID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err @@ -107,8 +142,8 @@ func (api *API) DNSFirewallCluster(ctx context.Context, clusterID string) (*DNSF // ListDNSFirewallClusters lists the DNS Firewall clusters associated with an account. // // API reference: https://api.cloudflare.com/#dns-firewall-list-dns-firewall-clusters -func (api *API) ListDNSFirewallClusters(ctx context.Context) ([]*DNSFirewallCluster, error) { - uri := fmt.Sprintf("%s/dns_firewall", api.userBaseURL("/user")) +func (api *API) ListDNSFirewallClusters(ctx context.Context, rc *ResourceContainer, params ListDNSFirewallClustersParams) ([]*DNSFirewallCluster, error) { + uri := fmt.Sprintf("/%s/dns_firewall", rc.URLFragment()) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, err @@ -126,9 +161,13 @@ func (api *API) ListDNSFirewallClusters(ctx context.Context) ([]*DNSFirewallClus // UpdateDNSFirewallCluster updates a DNS Firewall cluster. // // API reference: https://api.cloudflare.com/#dns-firewall-update-dns-firewall-cluster -func (api *API) UpdateDNSFirewallCluster(ctx context.Context, clusterID string, vv DNSFirewallCluster) error { - uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, vv) +func (api *API) UpdateDNSFirewallCluster(ctx context.Context, rc *ResourceContainer, params UpdateDNSFirewallClusterParams) error { + if params.ClusterID == "" { + return ErrMissingClusterID + } + + uri := fmt.Sprintf("/%s/dns_firewall/%s", rc.URLFragment(), params.ClusterID) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return err } @@ -146,8 +185,8 @@ func (api *API) UpdateDNSFirewallCluster(ctx context.Context, clusterID string, // undone, and will stop all traffic to that cluster. // // API reference: https://api.cloudflare.com/#dns-firewall-delete-dns-firewall-cluster -func (api *API) DeleteDNSFirewallCluster(ctx context.Context, clusterID string) error { - uri := fmt.Sprintf("%s/dns_firewall/%s", api.userBaseURL("/user"), clusterID) +func (api *API) DeleteDNSFirewallCluster(ctx context.Context, rc *ResourceContainer, clusterID string) error { + uri := fmt.Sprintf("/%s/dns_firewall/%s", rc.URLFragment(), clusterID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err @@ -162,24 +201,9 @@ func (api *API) DeleteDNSFirewallCluster(ctx context.Context, clusterID string) return nil } -// encode encodes non-nil fields into URL encoded form. -func (o DNSFirewallUserAnalyticsOptions) encode() string { - v := url.Values{} - if o.Since != nil { - v.Set("since", o.Since.UTC().Format(time.RFC3339)) - } - if o.Until != nil { - v.Set("until", o.Until.UTC().Format(time.RFC3339)) - } - if o.Metrics != nil { - v.Set("metrics", strings.Join(o.Metrics, ",")) - } - return v.Encode() -} - -// DNSFirewallUserAnalytics retrieves analytics report for a specified dimension and time range. -func (api *API) DNSFirewallUserAnalytics(ctx context.Context, clusterID string, o DNSFirewallUserAnalyticsOptions) (DNSFirewallAnalytics, error) { - uri := fmt.Sprintf("%s/dns_firewall/%s/dns_analytics/report?%s", api.userBaseURL("/user"), clusterID, o.encode()) +// GetDNSFirewallUserAnalytics retrieves analytics report for a specified dimension and time range. +func (api *API) GetDNSFirewallUserAnalytics(ctx context.Context, rc *ResourceContainer, params GetDNSFirewallUserAnalyticsParams) (DNSFirewallAnalytics, error) { + uri := buildURI(fmt.Sprintf("/%s/dns_firewall/%s/dns_analytics/report", rc.URLFragment(), params.ClusterID), params.DNSFirewallUserAnalyticsOptions) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return DNSFirewallAnalytics{}, err diff --git a/dns_firewall_test.go b/dns_firewall_test.go index 1002b8d9d7c..5c85320cb3b 100644 --- a/dns_firewall_test.go +++ b/dns_firewall_test.go @@ -10,15 +10,74 @@ import ( "github.com/stretchr/testify/assert" ) -func float64Ptr(v float64) *float64 { - return &v -} +func TestDNSFirewallUserAnalytics_UserLevel(t *testing.T) { + setup() + defer teardown() + + now := time.Now().UTC() + since := now.Add(-1 * time.Hour) + until := now + + handler := func(w http.ResponseWriter, r *http.Request) { + expectedMetrics := "queryCount,uncachedCount,staleCount,responseTimeAvg,responseTimeMedia,responseTime90th,responseTime99th" + + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET'") + assert.Equal(t, expectedMetrics, r.URL.Query().Get("metrics"), "Expected many metrics in URL parameter") + assert.Equal(t, since.Format(time.RFC3339), r.URL.Query().Get("since"), "Expected since parameter in URL") + assert.Equal(t, until.Format(time.RFC3339), r.URL.Query().Get("until"), "Expected until parameter in URL") + + w.Header().Set("content-type", "application/json") + fmt.Fprint(w, `{ + "result": { + "totals":{ + "queryCount": 5, + "uncachedCount":6, + "staleCount":7, + "responseTimeAvg":1.0, + "responseTimeMedian":2.0, + "responseTime90th":3.0, + "responseTime99th":4.0 + } + }, + "success": true, + "errors": null, + "messages": null + }`) + } -func int64Ptr(v int64) *int64 { - return &v + mux.HandleFunc("/user/dns_firewall/12345/dns_analytics/report", handler) + want := DNSFirewallAnalytics{ + Totals: DNSFirewallAnalyticsMetrics{ + QueryCount: Int64Ptr(5), + UncachedCount: Int64Ptr(6), + StaleCount: Int64Ptr(7), + ResponseTimeAvg: Float64Ptr(1.0), + ResponseTimeMedian: Float64Ptr(2.0), + ResponseTime90th: Float64Ptr(3.0), + ResponseTime99th: Float64Ptr(4.0), + }, + } + + actual, err := client.GetDNSFirewallUserAnalytics(context.Background(), UserIdentifier("foo"), GetDNSFirewallUserAnalyticsParams{ClusterID: "12345", DNSFirewallUserAnalyticsOptions: DNSFirewallUserAnalyticsOptions{ + Metrics: []string{ + "queryCount", + "uncachedCount", + "staleCount", + "responseTimeAvg", + "responseTimeMedia", + "responseTime90th", + "responseTime99th", + }, + Since: &since, + Until: &until, + }}) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } } -func TestDNSFirewallUserAnalytics(t *testing.T) { +func TestDNSFirewallUserAnalytics_AccountLevel(t *testing.T) { setup() defer teardown() @@ -53,20 +112,20 @@ func TestDNSFirewallUserAnalytics(t *testing.T) { }`) } - mux.HandleFunc("/user/dns_firewall/12345/dns_analytics/report", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/dns_firewall/12345/dns_analytics/report", handler) want := DNSFirewallAnalytics{ Totals: DNSFirewallAnalyticsMetrics{ - QueryCount: int64Ptr(5), - UncachedCount: int64Ptr(6), - StaleCount: int64Ptr(7), - ResponseTimeAvg: float64Ptr(1.0), - ResponseTimeMedian: float64Ptr(2.0), - ResponseTime90th: float64Ptr(3.0), - ResponseTime99th: float64Ptr(4.0), + QueryCount: Int64Ptr(5), + UncachedCount: Int64Ptr(6), + StaleCount: Int64Ptr(7), + ResponseTimeAvg: Float64Ptr(1.0), + ResponseTimeMedian: Float64Ptr(2.0), + ResponseTime90th: Float64Ptr(3.0), + ResponseTime99th: Float64Ptr(4.0), }, } - params := DNSFirewallUserAnalyticsOptions{ + actual, err := client.GetDNSFirewallUserAnalytics(context.Background(), AccountIdentifier(testAccountID), GetDNSFirewallUserAnalyticsParams{ClusterID: "12345", DNSFirewallUserAnalyticsOptions: DNSFirewallUserAnalyticsOptions{ Metrics: []string{ "queryCount", "uncachedCount", @@ -78,8 +137,8 @@ func TestDNSFirewallUserAnalytics(t *testing.T) { }, Since: &since, Until: &until, - } - actual, err := client.DNSFirewallUserAnalytics(context.Background(), "12345", params) + }}) + if assert.NoError(t, err) { assert.Equal(t, want, actual) } From 37b9d253e27dbbf39f32fa4cb8239f7fc31d9458 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 19 Jun 2023 15:51:33 +1000 Subject: [PATCH 037/130] add changelog entry --- .changelog/1313.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/1313.txt diff --git a/.changelog/1313.txt b/.changelog/1313.txt new file mode 100644 index 00000000000..ace0376ab4c --- /dev/null +++ b/.changelog/1313.txt @@ -0,0 +1,7 @@ +```release-note:breaking-change +virtualdns: remove support in favour of newer DNS firewall methods +``` + +```release-note:breaking-change +dns_firewall: modernise method signatures and conventions to align with the experimental client +``` From 94404ee06ecd044d2d783c004a5bf36f9b3a090a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:56:44 +0000 Subject: [PATCH 038/130] build(deps): bump github.com/urfave/cli/v2 from 2.25.6 to 2.25.7 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.6 to 2.25.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.25.6...v2.25.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 4039b9fe6c3..856fd9cb6c7 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 github.com/olekukonko/tablewriter v0.0.5 github.com/stretchr/testify v1.8.4 - github.com/urfave/cli/v2 v2.25.6 + github.com/urfave/cli/v2 v2.25.7 golang.org/x/net v0.11.0 golang.org/x/time v0.3.0 ) diff --git a/go.sum b/go.sum index df5503443a3..a528bd1062b 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/urfave/cli/v2 v2.25.6 h1:yuSkgDSZfH3L1CjF2/5fNNg2KbM47pY2EvjBq4ESQnU= -github.com/urfave/cli/v2 v2.25.6/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 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.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= From b0f8e9480e507cf4a404c1f98037a664645234bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 19 Jun 2023 16:57:01 +0000 Subject: [PATCH 039/130] add CHANGELOG for #1314 --- .changelog/1314.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1314.txt diff --git a/.changelog/1314.txt b/.changelog/1314.txt new file mode 100644 index 00000000000..4eb0d0acb65 --- /dev/null +++ b/.changelog/1314.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps github.com/urfave/cli/v2 from 2.25.6 to 2.25.7 +``` From 754659847a0df689038a1ff307c6257c683bf401 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 19 Jun 2023 19:59:21 +0000 Subject: [PATCH 040/130] Update CHANGELOG.md for #1314 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 396cb563359..aadbb9fc9ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ DEPENDENCIES: * deps: bumps github.com/hashicorp/go-retryablehttp from 0.7.3 to 0.7.4 ([#1301](https://github.com/cloudflare/cloudflare-go/issues/1301)) * deps: bumps github.com/urfave/cli/v2 from 2.25.5 to 2.25.6 ([#1305](https://github.com/cloudflare/cloudflare-go/issues/1305)) +* deps: bumps github.com/urfave/cli/v2 from 2.25.6 to 2.25.7 ([#1314](https://github.com/cloudflare/cloudflare-go/issues/1314)) * deps: bumps golang.org/x/net from 0.10.0 to 0.11.0 ([#1307](https://github.com/cloudflare/cloudflare-go/issues/1307)) * deps: bumps goreleaser/goreleaser-action from 4.2.0 to 4.3.0 ([#1306](https://github.com/cloudflare/cloudflare-go/issues/1306)) From 505473bb6303a31b77d574b43c2f8711b8f7aace Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 19 Jun 2023 22:36:27 +0000 Subject: [PATCH 041/130] Update CHANGELOG.md for #1313 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aadbb9fc9ce..95389ebf097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## 0.70.0 (Unreleased) +BREAKING CHANGES: + +* dns_firewall: modernise method signatures and conventions to align with the experimental client ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) +* railgun: remove support for railgun ([#1312](https://github.com/cloudflare/cloudflare-go/issues/1312)) +* virtualdns: remove support in favour of newer DNS firewall methods ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) + ENHANCEMENTS: * custom_nameservers: add support for managing custom nameservers ([#1304](https://github.com/cloudflare/cloudflare-go/issues/1304)) From 385fc64122fe2d8af5a5f3b4b6a08aa87c5dcca8 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 20 Jun 2023 09:10:05 +1000 Subject: [PATCH 042/130] cloudflare: remove all references to api.AccountID Now that all references to `api.AccountID` are removed, we can pull out the helpers that were setting it along with any other method references. --- cloudflare.go | 16 +--------------- cloudflare_test.go | 2 +- cmd/flarectl/misc.go | 4 ---- options.go | 11 ----------- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/cloudflare.go b/cloudflare.go index 8e5afe369eb..2231bd79f20 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -45,7 +45,6 @@ type API struct { APIUserServiceKey string APIToken string BaseURL string - AccountID string UserAgent string headers http.Header httpClient *http.Client @@ -147,7 +146,7 @@ func (api *API) SetAuthType(authType int) { // ZoneIDByName retrieves a zone's ID from the name. func (api *API) ZoneIDByName(zoneName string) (string, error) { zoneName = normalizeZoneName(zoneName) - res, err := api.ListZonesContext(context.Background(), WithZoneFilters(zoneName, api.AccountID, "")) + res, err := api.ListZonesContext(context.Background(), WithZoneFilters(zoneName, "", "")) if err != nil { return "", fmt.Errorf("ListZonesContext command failed: %w", err) } @@ -416,19 +415,6 @@ func (api *API) request(ctx context.Context, method, uri string, reqBody io.Read return resp, nil } -// Returns the base URL to use for API endpoints that exist for accounts. -// If an account option was used when creating the API instance, returns -// the account URL. -// -// accountBase is the base URL for endpoints referring to the current user. -// It exists as a parameter because it is not consistent across APIs. -func (api *API) userBaseURL(accountBase string) string { - if api.AccountID != "" { - return "/accounts/" + api.AccountID - } - return accountBase -} - // copyHeader copies all headers for `source` and sets them on `target`. // based on https://godoc.org/github.com/golang/gddo/httputil/header#Copy func copyHeader(target, source http.Header) { diff --git a/cloudflare_test.go b/cloudflare_test.go index 831b1464d97..c841144219e 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -352,7 +352,7 @@ func TestZoneIDByNameWithNonUniqueZonesWithoutOrgID(t *testing.T) { } func TestZoneIDByNameWithIDN(t *testing.T) { - setup(UsingAccount("01a7362d577a6c3019a474fd6f485823")) + setup() defer teardown() handler := func(w http.ResponseWriter, r *http.Request) { diff --git a/cmd/flarectl/misc.go b/cmd/flarectl/misc.go index ddfeeb6cfb7..4f8372c3d9f 100644 --- a/cmd/flarectl/misc.go +++ b/cmd/flarectl/misc.go @@ -44,10 +44,6 @@ func initializeAPI(c *cli.Context) error { return err } - if c.IsSet("account-id") { - cloudflare.UsingAccount(c.String("account-id"))(api) // nolint - } - return nil } diff --git a/options.go b/options.go index 1ed8919228c..7754badbe39 100644 --- a/options.go +++ b/options.go @@ -28,17 +28,6 @@ func Headers(headers http.Header) Option { } } -// UsingAccount allows you to apply account-level changes (Load Balancing, -// Railguns) to an account instead. -// -// Deprecated: Resources should define the `AccountID` parameter explicitly. -func UsingAccount(accountID string) Option { - return func(api *API) error { - api.AccountID = accountID - return nil - } -} - // UsingRateLimit applies a non-default rate limit to client API requests // If not specified the default of 4rps will be applied. func UsingRateLimit(rps float64) Option { From 3dc24cea71c4f4af1accd79c34493cf50a60caa9 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 20 Jun 2023 09:15:45 +1000 Subject: [PATCH 043/130] add changelog entry --- .changelog/1315.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/1315.txt diff --git a/.changelog/1315.txt b/.changelog/1315.txt new file mode 100644 index 00000000000..c5dedfd9a4f --- /dev/null +++ b/.changelog/1315.txt @@ -0,0 +1,7 @@ +```release-note:breaking-change +cloudflare: remove `api.AccountID` from client struct +``` + +```release-note:breaking-change +cloudflare: remove `UsingAccount` in favour of resource specific attributes +``` From 2cad7d5cdf029bc5cd2a39a22fb1a1e37761de0a Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 19 Jun 2023 23:32:22 +0000 Subject: [PATCH 044/130] Update CHANGELOG.md for #1315 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95389ebf097..08c936b95d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ BREAKING CHANGES: +* cloudflare: remove `UsingAccount` in favour of resource specific attributes ([#1315](https://github.com/cloudflare/cloudflare-go/issues/1315)) +* cloudflare: remove `api.AccountID` from client struct ([#1315](https://github.com/cloudflare/cloudflare-go/issues/1315)) * dns_firewall: modernise method signatures and conventions to align with the experimental client ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) * railgun: remove support for railgun ([#1312](https://github.com/cloudflare/cloudflare-go/issues/1312)) * virtualdns: remove support in favour of newer DNS firewall methods ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) From b90ad48946f73fc49a87675c44e49932a8261e9c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 19 Jun 2023 23:33:03 +0000 Subject: [PATCH 045/130] Update CHANGELOG.md for #1303 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08c936b95d2..00445b9a244 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ BREAKING CHANGES: * cloudflare: remove `api.AccountID` from client struct ([#1315](https://github.com/cloudflare/cloudflare-go/issues/1315)) * dns_firewall: modernise method signatures and conventions to align with the experimental client ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) * railgun: remove support for railgun ([#1312](https://github.com/cloudflare/cloudflare-go/issues/1312)) +* tunnel: swap `ConnectTimeout`, `TLSTimeout`, `TCPKeepAlive` and `KeepAliveTimeout` to `TunnelDuration` instead of `time.Duration` ([#1303](https://github.com/cloudflare/cloudflare-go/issues/1303)) * virtualdns: remove support in favour of newer DNS firewall methods ([#1313](https://github.com/cloudflare/cloudflare-go/issues/1313)) ENHANCEMENTS: From a8a0d7470a874143ae00b3b23e597225a78a2272 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 21 Jun 2023 11:07:21 +1000 Subject: [PATCH 046/130] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00445b9a244..66e277472cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.70.0 (Unreleased) +## 0.71.0 (Unreleased) + +## 0.70.0 (June 21st, 2023) BREAKING CHANGES: From fce9d2c070e7344bc9db1fab1a43ded6dedcc0da Mon Sep 17 00:00:00 2001 From: Suhrit Rimal Date: Thu, 22 Jun 2023 10:34:33 -0400 Subject: [PATCH 047/130] support os_version_extra for posture rule creation --- .changelog/1316.txt | 3 +++ device_posture_rule.go | 1 + teams_devices.go | 1 + teams_devices_test.go | 2 ++ 4 files changed, 7 insertions(+) create mode 100644 .changelog/1316.txt diff --git a/.changelog/1316.txt b/.changelog/1316.txt new file mode 100644 index 00000000000..d2588ba25bf --- /dev/null +++ b/.changelog/1316.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +device_posture_rule: support os_version_extra +``` diff --git a/device_posture_rule.go b/device_posture_rule.go index 5d04e270b56..4b2986ccb68 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -178,6 +178,7 @@ type DevicePostureRuleInput struct { Os string `json:"os,omitempty"` OsDistroName string `json:"os_distro_name,omitempty"` OsDistroRevision string `json:"os_distro_revision,omitempty"` + OSVersionExtra string `json:"os_version_extra,omitempty` Operator string `json:"operator,omitempty"` Domain string `json:"domain,omitempty"` ComplianceStatus string `json:"compliance_status,omitempty"` diff --git a/teams_devices.go b/teams_devices.go index 8836cbe51ce..941a376704f 100644 --- a/teams_devices.go +++ b/teams_devices.go @@ -31,6 +31,7 @@ type TeamsDeviceListItem struct { OSVersion string `json:"os_version,omitempty"` OSDistroName string `json:"os_distro_name,omitempty"` OsDistroRevision string `json:"os_distro_revision,omitempty"` + OSVersionExtra string `json:"os_version_extra,omitempty"` MacAddress string `json:"mac_address,omitempty"` IP string `json:"ip,omitempty"` Created string `json:"created,omitempty"` diff --git a/teams_devices_test.go b/teams_devices_test.go index b639c164c09..6b4a28f7999 100644 --- a/teams_devices_test.go +++ b/teams_devices_test.go @@ -41,6 +41,7 @@ func TestTeamsDevicesList(t *testing.T) { "os_version": "10.0.0", "os_distro_name": "ubuntu", "os_distro_revision": "1.0.0", + "os_version_extra": "(a), "mac_address": "00-00-5E-00-53-00", "ip": "192.0.2.1", "created": "2017-06-14T00:00:00Z", @@ -71,6 +72,7 @@ func TestTeamsDevicesList(t *testing.T) { OSVersion: "10.0.0", OSDistroName: "ubuntu", OsDistroRevision: "1.0.0", + OSVersionExtra: "(a)", MacAddress: "00-00-5E-00-53-00", IP: "192.0.2.1", Created: "2017-06-14T00:00:00Z", From dd5f22e02bb3a48ab6aa80ead8df564686d744c4 Mon Sep 17 00:00:00 2001 From: Nathan Disidore Date: Thu, 22 Jun 2023 13:09:24 -0500 Subject: [PATCH 048/130] chore(workers): move Workers test script response to varadic builder --- utils.go | 4 + workers.go | 5 + workers_test.go | 245 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 175 insertions(+), 79 deletions(-) diff --git a/utils.go b/utils.go index bc2dc563384..621a5eab1c4 100644 --- a/utils.go +++ b/utils.go @@ -9,6 +9,10 @@ import ( "github.com/google/go-querystring/query" ) +func ptr[T any](val T) *T { + return &val +} + // buildURI assembles the base path and queries. func buildURI(path string, options interface{}) string { v, _ := query.Values(options) diff --git a/workers.go b/workers.go index b934218e693..403c890ede4 100644 --- a/workers.go +++ b/workers.go @@ -90,6 +90,11 @@ type WorkerScript struct { UsageModel string `json:"usage_model,omitempty"` } +type WorkersTailConsumer struct { + Service string `json:"service"` + Environment *string `json:"environment,omitempty"` +} + // WorkerMetaData contains worker script information such as size, creation & modification dates. type WorkerMetaData struct { ID string `json:"id,omitempty"` diff --git a/workers_test.go b/workers_test.go index 8492cdee06d..420c67e4382 100644 --- a/workers_test.go +++ b/workers_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -21,29 +22,7 @@ const ( "errors": [], "messages": [] }` - uploadWorkerResponseData = `{ - "result": { - "script": "addEventListener('fetch', event => {\n event.passThroughOnException()\n event.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n return fetch(request)\n}", - "etag": "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - "size": 191, - "modified_on": "2018-06-09T15:17:01.989141Z" - }, - "success": true, - "errors": [], - "messages": [] -}` - uploadWorkerModuleResponseData = `{ - "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" - }, - "success": true, - "errors": [], - "messages": [] -}` updateWorkerRouteResponse = `{ "result": { "id": "e7a57d8746e74ae49c25994dadb421b1", @@ -211,18 +190,6 @@ 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 ( @@ -242,6 +209,107 @@ var ( }`, testZoneID) ) +type ( + WorkersTestScriptResponse struct { + Script string `json:"script"` + UsageModel string `json:"usage_model,omitempty"` + Handlers []string `json:"handlers"` + ID string `json:"id,omitempty"` + ETAG string `json:"etag,omitempty"` + Size uint `json:"size,omitempty"` + CreatedOn string `json:"created_on,omitempty"` + ModifiedOn string `json:"modified_on,omitempty"` + LastDeployedFrom *string `json:"last_deployed_from,omitempty"` + DeploymentId *string `json:"deployment_id,omitempty"` + CompatibilityDate *string `json:"compatibility_date,omitempty"` + Logpush *bool `json:"logpush,omitempty"` + PlacementMode *string `json:"placement_mode,omitempty"` + } + workersTestResponseOpt func(r *WorkersTestScriptResponse) +) + +var ( + expectedWorkersServiceWorkerScript = "addEventListener('fetch', event => {\n event.passThroughOnException()\n event.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n return fetch(request)\n}" + expectedWorkersModuleWorkerScript = "export default {\n async fetch(request, env, event) {\n event.passThroughOnException()\n return fetch(request)\n }\n}" + WorkersDefaultTestResponse = WorkersTestScriptResponse{ + Script: expectedWorkersServiceWorkerScript, + Handlers: []string{"fetch"}, + UsageModel: "unbound", + ID: "e7a57d8746e74ae49c25994dadb421b1", + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + LastDeployedFrom: ptr("dash"), + Logpush: ptr(false), + CompatibilityDate: ptr("2022-07-12"), + } +) + +func withWorkerScript(content string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.Script = content } +} + +func withWorkerUsageModel(um string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.UsageModel = um } +} + +func withWorkerHandlers(h []string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.Handlers = h } +} + +func withWorkerID(id string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.ID = id } +} + +func withWorkerEtag(etag string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.ETAG = etag } +} + +func withWorkerSize(size uint) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.Size = size } +} + +func withWorkerCreatedOn(co time.Time) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.CreatedOn = co.Format(time.RFC3339Nano) } +} + +func withWorkerModifiedOn(mo time.Time) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.ModifiedOn = mo.Format(time.RFC3339Nano) } +} + +func withWorkerLogpush(logpush *bool) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.Logpush = logpush } +} + +func withWorkerPlacementMode(mode *string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.PlacementMode = mode } +} + +func withWorkerLastDeployedFrom(from *string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.LastDeployedFrom = from } +} + +func withWorkerDeploymentId(dID *string) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.DeploymentId = dID } +} + +func workersScriptResponse(t testing.TB, opts ...workersTestResponseOpt) string { + var responseConfig = WorkersDefaultTestResponse + for _, opt := range opts { + opt(&responseConfig) + } + + bytes, err := json.Marshal(struct { + Response + Result WorkersTestScriptResponse `json:"result"` + }{ + Response: Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}, + Result: responseConfig, + }) + require.NoError(t, err) + + return string(bytes) +} + func getFormValue(r *http.Request, key string) ([]byte, error) { err := r.ParseMultipartForm(1024 * 1024) if err != nil { @@ -439,24 +507,28 @@ func TestUploadWorker_Basic(t *testing.T) { setup() defer teardown() + formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") 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.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t, withWorkerModifiedOn(formattedTime))) }) 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, false, WorkerScript{ - Script: workerScript, + Script: workerScript, + UsageModel: "unbound", WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, + ID: "e7a57d8746e74ae49c25994dadb421b1", + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + ModifiedOn: formattedTime, + Logpush: ptr(false), + LastDeployedFrom: ptr("dash"), }, }} if assert.NoError(t, err) { @@ -468,6 +540,7 @@ func TestUploadWorker_Module(t *testing.T) { setup() defer teardown() + formattedCreatedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", func(w http.ResponseWriter, r *http.Request) { mpUpload, err := parseMultipartUpload(r) assert.NoError(t, err) @@ -483,19 +556,22 @@ 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.Fprint(w, uploadWorkerModuleResponseData) + fmt.Fprint(w, workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), withWorkerCreatedOn(formattedCreatedTime))) }) 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, - false, - WorkerScript{ - Script: workerModuleScript, + Response: successResponse, + Module: false, + WorkerScript: WorkerScript{ + Script: workerModuleScript, + UsageModel: "unbound", WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, + ID: "e7a57d8746e74ae49c25994dadb421b1", + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + CreatedOn: formattedCreatedTime, + Logpush: ptr(false), + LastDeployedFrom: ptr("dash"), }, }} if assert.NoError(t, err) { @@ -525,7 +601,7 @@ func TestUploadWorker_WithDurableObjectBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -548,6 +624,7 @@ func TestUploadWorker_WithInheritBinding(t *testing.T) { setup() defer teardown() + formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") // Setup route handler for both single-script and multi-script handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) @@ -570,20 +647,23 @@ func TestUploadWorker_WithInheritBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t, withWorkerModifiedOn(formattedTime))) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) - formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") want := WorkerScriptResponse{ - successResponse, - false, - WorkerScript{ - Script: workerScript, + Response: successResponse, + Module: false, + WorkerScript: WorkerScript{ + Script: workerScript, + UsageModel: "unbound", WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, + ID: "e7a57d8746e74ae49c25994dadb421b1", + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + ModifiedOn: formattedTime, + Logpush: ptr(false), + LastDeployedFrom: ptr("dash"), }, }} @@ -622,7 +702,7 @@ func TestUploadWorker_WithKVBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -663,7 +743,7 @@ func TestUploadWorker_WithWasmBinding(t *testing.T) { assert.Equal(t, []byte("fake-wasm"), wasmContent) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -701,7 +781,7 @@ func TestUploadWorker_WithPlainTextBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -747,7 +827,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.Fprint(w, uploadWorkerModuleResponseData) + fmt.Fprint(w, workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript))) }) _, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ @@ -785,7 +865,7 @@ func TestUploadWorker_WithSecretTextBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -828,7 +908,7 @@ func TestUploadWorker_WithServiceBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -852,6 +932,10 @@ func TestUploadWorker_WithLogpush(t *testing.T) { setup() defer teardown() + var ( + formattedTime, _ = time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") + logpush = ptr(true) + ) 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) @@ -861,19 +945,22 @@ func TestUploadWorker_WithLogpush(t *testing.T) { assert.Equal(t, &expected, mpUpload.Logpush) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t, withWorkerLogpush(logpush), withWorkerModifiedOn(formattedTime))) }) - 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") + res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript, Logpush: logpush}) want := WorkerScriptResponse{ - successResponse, - false, - WorkerScript{ - Script: workerScript, + Response: successResponse, + Module: false, + WorkerScript: WorkerScript{ + Script: expectedWorkersModuleWorkerScript, + UsageModel: "unbound", WorkerMetaData: WorkerMetaData{ - ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", - Size: 191, - ModifiedOn: formattedTime, + ID: "e7a57d8746e74ae49c25994dadb421b1", + ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", + Size: 191, + ModifiedOn: formattedTime, + Logpush: logpush, + LastDeployedFrom: ptr("dash"), }, }} if assert.NoError(t, err) { @@ -899,7 +986,7 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) { assert.Equal(t, compatibilityFlags, mpUpload.CompatibilityFlags) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -933,7 +1020,7 @@ func TestUploadWorker_WithQueueBinding(t *testing.T) { assert.Equal(t, expectedBindings, mpUpload.BindingMeta) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, uploadWorkerResponseData) + fmt.Fprint(w, workersScriptResponse(t)) } mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler) @@ -954,7 +1041,7 @@ func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) { defer teardown() placementMode := PlacementModeSmart - response := uploadModuleWorkerSmartPlacement + response := workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), withWorkerPlacementMode(ptr("smart"))) handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) @@ -983,7 +1070,7 @@ func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) { t.Run("Test disabling placement", func(t *testing.T) { placementMode = PlacementModeOff - response = uploadWorkerModuleResponseData + response = workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript)) worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ ScriptName: "bar", From b037105aa30f4d30caf150ba440440d09e3ae0eb Mon Sep 17 00:00:00 2001 From: Nathan Disidore Date: Thu, 22 Jun 2023 13:11:31 -0500 Subject: [PATCH 049/130] feat(workers): allow tail consumers to be set on script upload --- workers.go | 41 +++++++++++++++++------------ workers_test.go | 70 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/workers.go b/workers.go index 403c890ede4..3bfcc354d70 100644 --- a/workers.go +++ b/workers.go @@ -32,6 +32,10 @@ type CreateWorkerParams struct { // https://developers.cloudflare.com/workers/platform/logpush/ Logpush *bool + // TailConsumers specifices a list of Workers that will consume the logs of the attached Worker. + // https://developers.cloudflare.com/workers/platform/tail-workers/ + TailConsumers *[]WorkersTailConsumer + // Bindings should be a map where the keys are the binding name, and the // values are the binding content Bindings map[string]WorkerBinding @@ -97,15 +101,16 @@ type WorkersTailConsumer 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"` - Logpush *bool `json:"logpush,omitempty"` - LastDeployedFrom *string `json:"last_deployed_from,omitempty"` - DeploymentId *string `json:"deployment_id,omitempty"` - PlacementMode *PlacementMode `json:"placement_mode,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"` + TailConsumers *[]WorkersTailConsumer `json:"tail_consumers,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. @@ -256,7 +261,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params err error ) - if params.Module || params.Logpush != nil || params.Placement != 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 || params.TailConsumers != nil { contentType, body, err = formatMultipartBody(params) if err != nil { return WorkerScriptResponse{}, err @@ -290,16 +295,18 @@ 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"` - CompatibilityDate string `json:"compatibility_date,omitempty"` - CompatibilityFlags []string `json:"compatibility_flags,omitempty"` - Placement *Placement `json:"placement,omitempty"` + BodyPart string `json:"body_part,omitempty"` + MainModule string `json:"main_module,omitempty"` + Bindings []workerBindingMeta `json:"bindings"` + Logpush *bool `json:"logpush,omitempty"` + TailConsumers *[]WorkersTailConsumer `json:"tail_consumers,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, + TailConsumers: params.TailConsumers, CompatibilityDate: params.CompatibilityDate, CompatibilityFlags: params.CompatibilityFlags, Placement: params.Placement, diff --git a/workers_test.go b/workers_test.go index 420c67e4382..9d6b8a17463 100644 --- a/workers_test.go +++ b/workers_test.go @@ -211,19 +211,20 @@ var ( type ( WorkersTestScriptResponse struct { - Script string `json:"script"` - UsageModel string `json:"usage_model,omitempty"` - Handlers []string `json:"handlers"` - ID string `json:"id,omitempty"` - ETAG string `json:"etag,omitempty"` - Size uint `json:"size,omitempty"` - CreatedOn string `json:"created_on,omitempty"` - ModifiedOn string `json:"modified_on,omitempty"` - LastDeployedFrom *string `json:"last_deployed_from,omitempty"` - DeploymentId *string `json:"deployment_id,omitempty"` - CompatibilityDate *string `json:"compatibility_date,omitempty"` - Logpush *bool `json:"logpush,omitempty"` - PlacementMode *string `json:"placement_mode,omitempty"` + Script string `json:"script"` + UsageModel string `json:"usage_model,omitempty"` + Handlers []string `json:"handlers"` + ID string `json:"id,omitempty"` + ETAG string `json:"etag,omitempty"` + Size uint `json:"size,omitempty"` + CreatedOn string `json:"created_on,omitempty"` + ModifiedOn string `json:"modified_on,omitempty"` + LastDeployedFrom *string `json:"last_deployed_from,omitempty"` + DeploymentId *string `json:"deployment_id,omitempty"` + CompatibilityDate *string `json:"compatibility_date,omitempty"` + Logpush *bool `json:"logpush,omitempty"` + TailConsumers *[]WorkersTailConsumer `json:"tail_consumers,omitempty"` + PlacementMode *string `json:"placement_mode,omitempty"` } workersTestResponseOpt func(r *WorkersTestScriptResponse) ) @@ -284,6 +285,10 @@ func withWorkerPlacementMode(mode *string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.PlacementMode = mode } } +func withWorkerTailConsumers(consumers ...WorkersTailConsumer) workersTestResponseOpt { + return func(r *WorkersTestScriptResponse) { r.TailConsumers = &consumers } +} + func withWorkerLastDeployedFrom(from *string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.LastDeployedFrom = from } } @@ -1083,3 +1088,42 @@ func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) { assert.Nil(t, worker.PlacementMode) }) } + +func TestUploadWorker_WithTailConsumers(t *testing.T) { + setup() + defer teardown() + + response := workersScriptResponse(t, + withWorkerScript(expectedWorkersModuleWorkerScript)) + 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("adds tail consumers", func(t *testing.T) { + tailConsumers := []WorkersTailConsumer{ + {Service: "my-service-a"}, + {Service: "my-service-b", Environment: ptr("production")}, + } + response = workersScriptResponse(t, + withWorkerScript(expectedWorkersModuleWorkerScript), + withWorkerTailConsumers(tailConsumers...)) + + worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ + ScriptName: "bar", + Script: workerScript, + TailConsumers: ptr(tailConsumers), + }) + assert.NoError(t, err) + require.NotNil(t, worker.TailConsumers) + assert.Len(t, *worker.TailConsumers, 2) + }) +} From a98408951abe12c8c2d0b44ddcd54a159ce9fe4c Mon Sep 17 00:00:00 2001 From: Nathan Disidore Date: Thu, 22 Jun 2023 13:38:09 -0500 Subject: [PATCH 050/130] chore(workers): nolint:unused the workers test response helpers --- workers_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/workers_test.go b/workers_test.go index 9d6b8a17463..4db7b1078d6 100644 --- a/workers_test.go +++ b/workers_test.go @@ -245,54 +245,67 @@ var ( } ) +//nolint:unused func withWorkerScript(content string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.Script = content } } +//nolint:unused func withWorkerUsageModel(um string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.UsageModel = um } } +//nolint:unused func withWorkerHandlers(h []string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.Handlers = h } } +//nolint:unused func withWorkerID(id string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.ID = id } } +//nolint:unused func withWorkerEtag(etag string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.ETAG = etag } } +//nolint:unused func withWorkerSize(size uint) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.Size = size } } +//nolint:unused func withWorkerCreatedOn(co time.Time) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.CreatedOn = co.Format(time.RFC3339Nano) } } +//nolint:unused func withWorkerModifiedOn(mo time.Time) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.ModifiedOn = mo.Format(time.RFC3339Nano) } } +//nolint:unused func withWorkerLogpush(logpush *bool) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.Logpush = logpush } } +//nolint:unused func withWorkerPlacementMode(mode *string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.PlacementMode = mode } } +//nolint:unused func withWorkerTailConsumers(consumers ...WorkersTailConsumer) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.TailConsumers = &consumers } } +//nolint:unused func withWorkerLastDeployedFrom(from *string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.LastDeployedFrom = from } } +//nolint:unused func withWorkerDeploymentId(dID *string) workersTestResponseOpt { return func(r *WorkersTestScriptResponse) { r.DeploymentId = dID } } From d8b25de4394f8395bda5f221a3c1024f84462402 Mon Sep 17 00:00:00 2001 From: Nathan Disidore Date: Thu, 22 Jun 2023 13:40:42 -0500 Subject: [PATCH 051/130] chore(workers): add release note --- .changelog/1317.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1317.txt diff --git a/.changelog/1317.txt b/.changelog/1317.txt new file mode 100644 index 00000000000..722e04c20df --- /dev/null +++ b/.changelog/1317.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +workers: Add ability to specify tail Workers in script metadata +``` \ No newline at end of file From 4e2bb5c4e17a2b6a881d68fbfda3eddb61f98136 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Jun 2023 06:01:59 +1000 Subject: [PATCH 052/130] Update device_posture_rule.go --- device_posture_rule.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device_posture_rule.go b/device_posture_rule.go index 4b2986ccb68..56d143e8e3b 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -178,7 +178,7 @@ type DevicePostureRuleInput struct { Os string `json:"os,omitempty"` OsDistroName string `json:"os_distro_name,omitempty"` OsDistroRevision string `json:"os_distro_revision,omitempty"` - OSVersionExtra string `json:"os_version_extra,omitempty` + OSVersionExtra string `json:"os_version_extra,omitempty"` Operator string `json:"operator,omitempty"` Domain string `json:"domain,omitempty"` ComplianceStatus string `json:"compliance_status,omitempty"` From 465a4a2ae018f0f2aba3f8446369df006c123ef6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Jun 2023 06:02:05 +1000 Subject: [PATCH 053/130] Update teams_devices_test.go --- teams_devices_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/teams_devices_test.go b/teams_devices_test.go index 6b4a28f7999..3c78bb38d65 100644 --- a/teams_devices_test.go +++ b/teams_devices_test.go @@ -41,7 +41,7 @@ func TestTeamsDevicesList(t *testing.T) { "os_version": "10.0.0", "os_distro_name": "ubuntu", "os_distro_revision": "1.0.0", - "os_version_extra": "(a), + "os_version_extra": "(a)", "mac_address": "00-00-5E-00-53-00", "ip": "192.0.2.1", "created": "2017-06-14T00:00:00Z", From e159d2cbe70560741e08d4881ed8c6f45b27eb6c Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 22 Jun 2023 20:36:13 +0000 Subject: [PATCH 054/130] Update CHANGELOG.md for #1316 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66e277472cc..5a37b0a35e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.71.0 (Unreleased) +ENHANCEMENTS: + +* device_posture_rule: support os_version_extra ([#1316](https://github.com/cloudflare/cloudflare-go/issues/1316)) + ## 0.70.0 (June 21st, 2023) BREAKING CHANGES: From c85776d7da17b6fbbbc948ba7dabdb7590f4a737 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Jun 2023 14:18:10 +1000 Subject: [PATCH 055/130] swap ptr util to specific helpers --- utils.go | 4 ---- workers.go | 11 +++++++---- workers_test.go | 28 ++++++++++++++-------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/utils.go b/utils.go index 621a5eab1c4..bc2dc563384 100644 --- a/utils.go +++ b/utils.go @@ -9,10 +9,6 @@ import ( "github.com/google/go-querystring/query" ) -func ptr[T any](val T) *T { - return &val -} - // buildURI assembles the base path and queries. func buildURI(path string, options interface{}) string { v, _ := query.Values(options) diff --git a/workers.go b/workers.go index 3bfcc354d70..53711f9068f 100644 --- a/workers.go +++ b/workers.go @@ -28,12 +28,15 @@ 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 opts the worker into Workers Logpush logging. A nil value leaves + // the current setting unchanged. + // + // Documentation: https://developers.cloudflare.com/workers/platform/logpush/ Logpush *bool - // TailConsumers specifices a list of Workers that will consume the logs of the attached Worker. - // https://developers.cloudflare.com/workers/platform/tail-workers/ + // TailConsumers specifies a list of Workers that will consume the logs of + // the attached Worker. + // Documentation: https://developers.cloudflare.com/workers/platform/tail-workers/ TailConsumers *[]WorkersTailConsumer // Bindings should be a map where the keys are the binding name, and the diff --git a/workers_test.go b/workers_test.go index 4db7b1078d6..820c72bd575 100644 --- a/workers_test.go +++ b/workers_test.go @@ -239,9 +239,9 @@ var ( ID: "e7a57d8746e74ae49c25994dadb421b1", ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", Size: 191, - LastDeployedFrom: ptr("dash"), - Logpush: ptr(false), - CompatibilityDate: ptr("2022-07-12"), + LastDeployedFrom: StringPtr("dash"), + Logpush: BoolPtr(false), + CompatibilityDate: StringPtr("2022-07-12"), } ) @@ -545,8 +545,8 @@ func TestUploadWorker_Basic(t *testing.T) { ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", Size: 191, ModifiedOn: formattedTime, - Logpush: ptr(false), - LastDeployedFrom: ptr("dash"), + Logpush: BoolPtr(false), + LastDeployedFrom: StringPtr("dash"), }, }} if assert.NoError(t, err) { @@ -588,8 +588,8 @@ func TestUploadWorker_Module(t *testing.T) { ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", Size: 191, CreatedOn: formattedCreatedTime, - Logpush: ptr(false), - LastDeployedFrom: ptr("dash"), + Logpush: BoolPtr(false), + LastDeployedFrom: StringPtr("dash"), }, }} if assert.NoError(t, err) { @@ -680,8 +680,8 @@ func TestUploadWorker_WithInheritBinding(t *testing.T) { ETAG: "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a", Size: 191, ModifiedOn: formattedTime, - Logpush: ptr(false), - LastDeployedFrom: ptr("dash"), + Logpush: BoolPtr(false), + LastDeployedFrom: StringPtr("dash"), }, }} @@ -952,7 +952,7 @@ func TestUploadWorker_WithLogpush(t *testing.T) { var ( formattedTime, _ = time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z") - logpush = ptr(true) + logpush = BoolPtr(true) ) 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) @@ -978,7 +978,7 @@ func TestUploadWorker_WithLogpush(t *testing.T) { Size: 191, ModifiedOn: formattedTime, Logpush: logpush, - LastDeployedFrom: ptr("dash"), + LastDeployedFrom: StringPtr("dash"), }, }} if assert.NoError(t, err) { @@ -1059,7 +1059,7 @@ func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) { defer teardown() placementMode := PlacementModeSmart - response := workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), withWorkerPlacementMode(ptr("smart"))) + response := workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), withWorkerPlacementMode(StringPtr("smart"))) handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method) @@ -1124,7 +1124,7 @@ func TestUploadWorker_WithTailConsumers(t *testing.T) { t.Run("adds tail consumers", func(t *testing.T) { tailConsumers := []WorkersTailConsumer{ {Service: "my-service-a"}, - {Service: "my-service-b", Environment: ptr("production")}, + {Service: "my-service-b", Environment: StringPtr("production")}, } response = workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), @@ -1133,7 +1133,7 @@ func TestUploadWorker_WithTailConsumers(t *testing.T) { worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ ScriptName: "bar", Script: workerScript, - TailConsumers: ptr(tailConsumers), + TailConsumers: &tailConsumers, }) assert.NoError(t, err) require.NotNil(t, worker.TailConsumers) From 899550c42a472b1c380027b143d8d48bbe22f187 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 23 Jun 2023 14:23:00 +1000 Subject: [PATCH 056/130] fix test assertion for correct payload --- workers_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers_test.go b/workers_test.go index 820c72bd575..1a48bf4b047 100644 --- a/workers_test.go +++ b/workers_test.go @@ -963,7 +963,7 @@ func TestUploadWorker_WithLogpush(t *testing.T) { assert.Equal(t, &expected, mpUpload.Logpush) w.Header().Set("content-type", "application/json") - fmt.Fprint(w, workersScriptResponse(t, withWorkerLogpush(logpush), withWorkerModifiedOn(formattedTime))) + fmt.Fprint(w, workersScriptResponse(t, withWorkerScript(expectedWorkersModuleWorkerScript), withWorkerLogpush(logpush), withWorkerModifiedOn(formattedTime))) }) res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript, Logpush: logpush}) want := WorkerScriptResponse{ From 4defa6d211c55ef7f1109778ab1058e9eb147d91 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 23 Jun 2023 04:28:42 +0000 Subject: [PATCH 057/130] Update CHANGELOG.md for #1317 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a37b0a35e4..0e1d2b7b4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ENHANCEMENTS: * device_posture_rule: support os_version_extra ([#1316](https://github.com/cloudflare/cloudflare-go/issues/1316)) +* workers: Add ability to specify tail Workers in script metadata ([#1317](https://github.com/cloudflare/cloudflare-go/issues/1317)) ## 0.70.0 (June 21st, 2023) From 57a0cb683d2bf59c62f728618e36e21c816cc67c Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 23 Jun 2023 20:15:31 -0400 Subject: [PATCH 058/130] Convert access application --- .changelog/1391.txt | 6 ++ access_application.go | 163 +++++++++++++++---------------------- access_application_test.go | 38 ++++----- cloudflare_test.go | 2 +- 4 files changed, 90 insertions(+), 119 deletions(-) create mode 100644 .changelog/1391.txt diff --git a/.changelog/1391.txt b/.changelog/1391.txt new file mode 100644 index 00000000000..f4c5868ad09 --- /dev/null +++ b/.changelog/1391.txt @@ -0,0 +1,6 @@ +```release-note:breaking-change +access_application: add support for auto pagination +``` +```release-note:breaking-change +access_application: Merge all methods to use ResourceContainer +``` \ No newline at end of file diff --git a/access_application.go b/access_application.go index bd49cf2c301..41481097dd6 100644 --- a/access_application.go +++ b/access_application.go @@ -112,58 +112,64 @@ type SaasApplication struct { CustomAttributes []SAMLAttributeConfig `json:"custom_attributes,omitempty"` } -// AccessApplications returns all applications within an account. +// ListAccessApplications returns all applications within an account or zone. // -// API reference: https://api.cloudflare.com/#access-applications-list-access-applications -func (api *API) AccessApplications(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]AccessApplication, ResultInfo, error) { - return api.accessApplications(ctx, accountID, pageOpts, AccountRouteRoot) -} - -// ZoneLevelAccessApplications returns all applications within a zone. -// -// API reference: https://api.cloudflare.com/#zone-level-access-applications-list-access-applications -func (api *API) ZoneLevelAccessApplications(ctx context.Context, zoneID string, pageOpts PaginationOptions) ([]AccessApplication, ResultInfo, error) { - return api.accessApplications(ctx, zoneID, pageOpts, ZoneRouteRoot) -} +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-list-access-applications +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-list-access-applications +func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessApplication, *ResultInfo, error) { + baseURL := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) + + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false + } -func (api *API) accessApplications(ctx context.Context, id string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessApplication, ResultInfo, error) { - uri := buildURI(fmt.Sprintf("/%s/%s/access/apps", routeRoot, id), pageOpts) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessApplication{}, ResultInfo{}, err + if pageOpts.Page < 1 { + pageOpts.Page = 1 } - var accessApplicationListResponse AccessApplicationListResponse - err = json.Unmarshal(res, &accessApplicationListResponse) - if err != nil { - return []AccessApplication{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, } - return accessApplicationListResponse.Result, accessApplicationListResponse.ResultInfo, nil -} + var applications []AccessApplication + var r AccessApplicationListResponse + for { + uri := buildURI(baseURL, resultInfo) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessApplication{}, &ResultInfo{}, err + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + applications = append(applications, r.Result...) + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } -// AccessApplication returns a single application based on the -// application ID. -// -// API reference: https://api.cloudflare.com/#access-applications-access-applications-details -func (api *API) AccessApplication(ctx context.Context, accountID, applicationID string) (AccessApplication, error) { - return api.accessApplication(ctx, accountID, applicationID, AccountRouteRoot) + return applications, &r.ResultInfo, nil } -// ZoneLevelAccessApplication returns a single zone level application based on the -// application ID. +// GetAccessApplication returns a single application based on the application ID for either account or zone. // -// API reference: https://api.cloudflare.com/#zone-level-access-applications-access-applications-details -func (api *API) ZoneLevelAccessApplication(ctx context.Context, zoneID, applicationID string) (AccessApplication, error) { - return api.accessApplication(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) accessApplication(ctx context.Context, id, applicationID string, routeRoot RouteRoot) (AccessApplication, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-get-an-access-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-get-an-access-application +func (api *API) GetAccessApplication(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessApplication, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) @@ -183,20 +189,10 @@ func (api *API) accessApplication(ctx context.Context, id, applicationID string, // CreateAccessApplication creates a new access application. // -// API reference: https://api.cloudflare.com/#access-applications-create-access-application -func (api *API) CreateAccessApplication(ctx context.Context, accountID string, accessApplication AccessApplication) (AccessApplication, error) { - return api.createAccessApplication(ctx, accountID, accessApplication, AccountRouteRoot) -} - -// CreateZoneLevelAccessApplication creates a new zone level access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-applications-create-access-application -func (api *API) CreateZoneLevelAccessApplication(ctx context.Context, zoneID string, accessApplication AccessApplication) (AccessApplication, error) { - return api.createAccessApplication(ctx, zoneID, accessApplication, ZoneRouteRoot) -} - -func (api *API) createAccessApplication(ctx context.Context, id string, accessApplication AccessApplication, routeRoot RouteRoot) (AccessApplication, error) { - uri := fmt.Sprintf("/%s/%s/access/apps", routeRoot, id) +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application +func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContainer, accessApplication AccessApplication) (AccessApplication, error) { + uri := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessApplication) if err != nil { @@ -214,27 +210,17 @@ func (api *API) createAccessApplication(ctx context.Context, id string, accessAp // UpdateAccessApplication updates an existing access application. // -// API reference: https://api.cloudflare.com/#access-applications-update-access-application -func (api *API) UpdateAccessApplication(ctx context.Context, accountID string, accessApplication AccessApplication) (AccessApplication, error) { - return api.updateAccessApplication(ctx, accountID, accessApplication, AccountRouteRoot) -} - -// UpdateZoneLevelAccessApplication updates an existing zone level access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-applications-update-access-application -func (api *API) UpdateZoneLevelAccessApplication(ctx context.Context, zoneID string, accessApplication AccessApplication) (AccessApplication, error) { - return api.updateAccessApplication(ctx, zoneID, accessApplication, ZoneRouteRoot) -} - -func (api *API) updateAccessApplication(ctx context.Context, id string, accessApplication AccessApplication, routeRoot RouteRoot) (AccessApplication, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-update-a-bookmark-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-update-a-bookmark-application +func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContainer, accessApplication AccessApplication) (AccessApplication, error) { if accessApplication.ID == "" { return AccessApplication{}, fmt.Errorf("access application ID cannot be empty") } uri := fmt.Sprintf( "/%s/%s/access/apps/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, accessApplication.ID, ) @@ -254,23 +240,13 @@ func (api *API) updateAccessApplication(ctx context.Context, id string, accessAp // DeleteAccessApplication deletes an access application. // -// API reference: https://api.cloudflare.com/#access-applications-delete-access-application -func (api *API) DeleteAccessApplication(ctx context.Context, accountID, applicationID string) error { - return api.deleteAccessApplication(ctx, accountID, applicationID, AccountRouteRoot) -} - -// DeleteZoneLevelAccessApplication deletes a zone level access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-applications-delete-access-application -func (api *API) DeleteZoneLevelAccessApplication(ctx context.Context, zoneID, applicationID string) error { - return api.deleteAccessApplication(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) deleteAccessApplication(ctx context.Context, id, applicationID string, routeRoot RouteRoot) error { +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-delete-an-access-application +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-delete-an-access-application +func (api *API) DeleteAccessApplication(ctx context.Context, rc *ResourceContainer, applicationID string) error { uri := fmt.Sprintf( "/%s/%s/access/apps/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) @@ -285,24 +261,13 @@ func (api *API) deleteAccessApplication(ctx context.Context, id, applicationID s // RevokeAccessApplicationTokens revokes tokens associated with an // access application. // -// API reference: https://api.cloudflare.com/#access-applications-revoke-access-tokens -func (api *API) RevokeAccessApplicationTokens(ctx context.Context, accountID, applicationID string) error { - return api.revokeAccessApplicationTokens(ctx, accountID, applicationID, AccountRouteRoot) -} - -// RevokeZoneLevelAccessApplicationTokens revokes tokens associated with a zone level -// access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-applications-revoke-access-tokens -func (api *API) RevokeZoneLevelAccessApplicationTokens(ctx context.Context, zoneID, applicationID string) error { - return api.revokeAccessApplicationTokens(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) revokeAccessApplicationTokens(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) error { +// Account API reference: https://developers.cloudflare.com/api/operations/access-applications-revoke-service-tokens +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-revoke-service-tokens +func (api *API) RevokeAccessApplicationTokens(ctx context.Context, rc *ResourceContainer, applicationID string) error { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/revoke-tokens", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) diff --git a/access_application_test.go b/access_application_test.go index 4275f452508..778e8926cc7 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -83,7 +83,7 @@ func TestAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, _, err := client.AccessApplications(context.Background(), testAccountID, PaginationOptions{}) + actual, _, err := client.ListAccessApplications(context.Background(), AccountIdentifier(testAccountID), PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -91,7 +91,7 @@ func TestAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, _, err = client.ZoneLevelAccessApplications(context.Background(), testZoneID, PaginationOptions{}) + actual, _, err = client.ListAccessApplications(context.Background(), ZoneIdentifier(testZoneID), PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -163,7 +163,7 @@ func TestAccessApplication(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.AccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + actual, err := client.GetAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -171,7 +171,7 @@ func TestAccessApplication(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err = client.ZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + actual, err = client.GetAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -238,7 +238,7 @@ func TestCreateAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", @@ -250,7 +250,7 @@ func TestCreateAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, err = client.CreateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{ + actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), AccessApplication{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", @@ -321,7 +321,7 @@ func TestUpdateAccessApplication(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.UpdateAccessApplication(context.Background(), testAccountID, fullAccessApplication) + actual, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), fullAccessApplication) if assert.NoError(t, err) { assert.Equal(t, fullAccessApplication, actual) @@ -329,7 +329,7 @@ func TestUpdateAccessApplication(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err = client.UpdateZoneLevelAccessApplication(context.Background(), testZoneID, fullAccessApplication) + actual, err = client.UpdateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), fullAccessApplication) if assert.NoError(t, err) { assert.Equal(t, fullAccessApplication, actual) @@ -340,10 +340,10 @@ func TestUpdateAccessApplicationWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessApplication(context.Background(), testZoneID, AccessApplication{}) + _, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{}) assert.EqualError(t, err, "access application ID cannot be empty") - _, err = client.UpdateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{}) + _, err = client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{}) assert.EqualError(t, err, "access application ID cannot be empty") } @@ -366,12 +366,12 @@ func TestDeleteAccessApplication(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - err := client.DeleteAccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + err := client.DeleteAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - err = client.DeleteZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + err = client.DeleteAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") assert.NoError(t, err) } @@ -392,12 +392,12 @@ func TestRevokeAccessApplicationTokens(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db/revoke-tokens", handler) - err := client.RevokeAccessApplicationTokens(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + err := client.RevokeAccessApplicationTokens(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db/revoke-tokens", handler) - err = client.RevokeZoneLevelAccessApplicationTokens(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + err = client.RevokeAccessApplicationTokens(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") assert.NoError(t, err) } @@ -461,7 +461,7 @@ func TestAccessApplicationWithCORS(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.AccessApplication(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + actual, err := client.GetAccessApplication(context.Background(), AccountIdentifier(testAccountID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -469,7 +469,7 @@ func TestAccessApplicationWithCORS(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err = client.ZoneLevelAccessApplication(context.Background(), testZoneID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + actual, err = client.GetAccessApplication(context.Background(), ZoneIdentifier(testZoneID), "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -542,7 +542,7 @@ func TestCreatePrivateAccessApplication(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ Name: "Admin Site", PrivateAddress: "198.51.100.0", SessionDuration: "24h", @@ -668,7 +668,7 @@ func TestCreateSaasAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), testAccountID, AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ Name: "Admin Saas Site", SaasApplication: &SaasApplication{ ConsumerServiceUrl: "https://examplesaas.com", @@ -684,7 +684,7 @@ func TestCreateSaasAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, err = client.CreateZoneLevelAccessApplication(context.Background(), testZoneID, AccessApplication{ + actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), AccessApplication{ Name: "Admin Saas Site", SaasApplication: &SaasApplication{ ConsumerServiceUrl: "https://saas.example.com", diff --git a/cloudflare_test.go b/cloudflare_test.go index c841144219e..5b7b1262ab2 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -475,7 +475,7 @@ func TestErrorFromResponseWithUnmarshalingError(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/access/apps", handler) - _, err := client.CreateAccessApplication(context.Background(), "01a7362d577a6c3019a474fd6f485823", AccessApplication{ + _, err := client.CreateAccessApplication(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), AccessApplication{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", From f9e202539b77c26e3c5328f9cd013abdfc101ddb Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Fri, 23 Jun 2023 20:21:48 -0400 Subject: [PATCH 059/130] Fix changelog --- .changelog/{1391.txt => 1319.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1391.txt => 1319.txt} (100%) diff --git a/.changelog/1391.txt b/.changelog/1319.txt similarity index 100% rename from .changelog/1391.txt rename to .changelog/1319.txt From 79fedcdc441e365b8918b99da5401df4eab05bdb Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sat, 24 Jun 2023 12:36:51 -0400 Subject: [PATCH 060/130] Merge Access CA Certificates --- access_application.go | 12 ++-- access_application_test.go | 4 ++ access_ca_certificate.go | 132 +++++++++++++++------------------- access_ca_certificate_test.go | 28 ++++---- cloudflare_test.go | 6 ++ 5 files changed, 88 insertions(+), 94 deletions(-) diff --git a/access_application.go b/access_application.go index 41481097dd6..65421f2e267 100644 --- a/access_application.go +++ b/access_application.go @@ -144,7 +144,7 @@ func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContaine res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []AccessApplication{}, &ResultInfo{}, err + return []AccessApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } err = json.Unmarshal(res, &r) @@ -175,7 +175,7 @@ func (api *API) GetAccessApplication(ctx context.Context, rc *ResourceContainer, res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return AccessApplication{}, err + return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessApplicationDetailResponse AccessApplicationDetailResponse @@ -196,7 +196,7 @@ func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContain res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessApplication) if err != nil { - return AccessApplication{}, err + return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessApplicationDetailResponse AccessApplicationDetailResponse @@ -226,7 +226,7 @@ func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContain res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessApplication) if err != nil { - return AccessApplication{}, err + return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessApplicationDetailResponse AccessApplicationDetailResponse @@ -252,7 +252,7 @@ func (api *API) DeleteAccessApplication(ctx context.Context, rc *ResourceContain _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return err + return fmt.Errorf("%s: %w", errMakeRequestError, err) } return nil @@ -273,7 +273,7 @@ func (api *API) RevokeAccessApplicationTokens(ctx context.Context, rc *ResourceC _, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil) if err != nil { - return err + return fmt.Errorf("%s: %w", errMakeRequestError, err) } return nil diff --git a/access_application_test.go b/access_application_test.go index 778e8926cc7..8b605a36012 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -10,6 +10,10 @@ import ( "github.com/stretchr/testify/assert" ) +const ( + testAccessApplicationID = "480f4f69-1a28-4fdd-9240-1ed29f0ac1db" +) + func TestAccessApplications(t *testing.T) { setup() defer teardown() diff --git a/access_ca_certificate.go b/access_ca_certificate.go index 1845bdb332a..5ca92b4a994 100644 --- a/access_ca_certificate.go +++ b/access_ca_certificate.go @@ -8,7 +8,7 @@ import ( ) // AccessCACertificate is the structure of the CA certificate used for -// short lived certificates. +// short-lived certificates. type AccessCACertificate struct { ID string `json:"id"` Aud string `json:"aud"` @@ -20,6 +20,7 @@ type AccessCACertificate struct { type AccessCACertificateListResponse struct { Response Result []AccessCACertificate `json:"result"` + ResultInfo } // AccessCACertificateResponse represents the response of a single CA @@ -29,55 +30,61 @@ type AccessCACertificateResponse struct { Result AccessCACertificate `json:"result"` } -// AccessCACertificates returns all CA certificates within Access. +// ListAccessCACertificates returns all AccessCACertificate within Access. // -// API reference: https://api.cloudflare.com/#access-short-lived-certificates-list-short-lived-certificates -func (api *API) AccessCACertificates(ctx context.Context, accountID string) ([]AccessCACertificate, error) { - return api.accessCACertificates(ctx, accountID, AccountRouteRoot) -} - -// ZoneLevelAccessCACertificates returns all zone level CA certificates within Access. -// -// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-list-short-lived-certificates -func (api *API) ZoneLevelAccessCACertificates(ctx context.Context, zoneID string) ([]AccessCACertificate, error) { - return api.accessCACertificates(ctx, zoneID, ZoneRouteRoot) -} +// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-list-short-lived-certificate-c-as +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-list-short-lived-certificate-c-as +func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessCACertificate, *ResultInfo, error) { + baseURL := fmt.Sprintf("/%s/%s/access/apps/ca", rc.Level, rc.Identifier) + + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false + } -func (api *API) accessCACertificates(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessCACertificate, error) { - uri := fmt.Sprintf("/%s/%s/access/apps/ca", routeRoot, id) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessCACertificate{}, err + if pageOpts.Page < 1 { + pageOpts.Page = 1 } - var accessCAListResponse AccessCACertificateListResponse - err = json.Unmarshal(res, &accessCAListResponse) - if err != nil { - return []AccessCACertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, } - return accessCAListResponse.Result, nil -} + var accessCACertificates []AccessCACertificate + var r AccessCACertificateListResponse + + for { + uri := buildURI(baseURL, resultInfo) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + accessCACertificates = append(accessCACertificates, r.Result...) + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } -// AccessCACertificate returns a single CA certificate associated with an Access -// Application. -// -// API reference: https://api.cloudflare.com/#access-short-lived-certificates-short-lived-certificate-details -func (api *API) AccessCACertificate(ctx context.Context, accountID, applicationID string) (AccessCACertificate, error) { - return api.accessCACertificate(ctx, accountID, applicationID, AccountRouteRoot) + return accessCACertificates, &resultInfo, nil } -// ZoneLevelAccessCACertificate returns a single zone level CA certificate associated with an Access -// Application. +// GetAccessCACertificate returns a single CA certificate associated within Access. // -// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-short-lived-certificate-details -func (api *API) ZoneLevelAccessCACertificate(ctx context.Context, zoneID, applicationID string) (AccessCACertificate, error) { - return api.accessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) accessCACertificate(ctx context.Context, id, applicationID string, routeRoot RouteRoot) (AccessCACertificate, error) { - uri := fmt.Sprintf("/%s/%s/access/apps/%s/ca", routeRoot, id, applicationID) +// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca +func (api *API) GetAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessCACertificate, error) { + uri := fmt.Sprintf("/%s/%s/access/apps/%s/ca", rc.Level, rc.Identifier, applicationID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -93,27 +100,15 @@ func (api *API) accessCACertificate(ctx context.Context, id, applicationID strin return accessCAResponse.Result, nil } -// CreateAccessCACertificate creates a new CA certificate for an Access -// Application. -// -// API reference: https://api.cloudflare.com/#access-short-lived-certificates-create-short-lived-certificate -func (api *API) CreateAccessCACertificate(ctx context.Context, accountID, applicationID string) (AccessCACertificate, error) { - return api.createAccessCACertificate(ctx, accountID, applicationID, AccountRouteRoot) -} - -// CreateZoneLevelAccessCACertificate creates a new zone level CA certificate for an Access -// Application. +// CreateAccessCACertificate creates a new CA certificate for an AccessApplication. // -// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-create-short-lived-certificate -func (api *API) CreateZoneLevelAccessCACertificate(ctx context.Context, zoneID string, applicationID string) (AccessCACertificate, error) { - return api.createAccessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) createAccessCACertificate(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) (AccessCACertificate, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca +func (api *API) CreateAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessCACertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/ca", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) @@ -132,26 +127,15 @@ func (api *API) createAccessCACertificate(ctx context.Context, id string, applic } // DeleteAccessCACertificate deletes an Access CA certificate on a defined -// Access Application. -// -// API reference: https://api.cloudflare.com/#access-short-lived-certificates-delete-access-certificate -func (api *API) DeleteAccessCACertificate(ctx context.Context, accountID, applicationID string) error { - return api.deleteAccessCACertificate(ctx, accountID, applicationID, AccountRouteRoot) -} - -// DeleteZoneLevelAccessCACertificate deletes a zone level Access CA certificate on a defined -// Access Application. +// AccessApplication. // -// API reference: https://api.cloudflare.com/#zone-level-access-short-lived-certificates-delete-access-certificate -func (api *API) DeleteZoneLevelAccessCACertificate(ctx context.Context, zoneID, applicationID string) error { - return api.deleteAccessCACertificate(ctx, zoneID, applicationID, ZoneRouteRoot) -} - -func (api *API) deleteAccessCACertificate(ctx context.Context, id string, applicationID string, routeRoot RouteRoot) error { +// Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-delete-a-short-lived-certificate-ca +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-delete-a-short-lived-certificate-ca +func (api *API) DeleteAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) error { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/ca", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) diff --git a/access_ca_certificate_test.go b/access_ca_certificate_test.go index d21141efe0e..a46b264209f 100644 --- a/access_ca_certificate_test.go +++ b/access_ca_certificate_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestAcessCACertificate(t *testing.T) { +func TestAccessCACertificate(t *testing.T) { setup() defer teardown() @@ -35,24 +35,24 @@ func TestAcessCACertificate(t *testing.T) { PublicKey: "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTI...3urg/XpGMdgaSs5ZdptUPw= open-ssh-ca@cloudflareaccess.org", } - mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) + mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+testAccessApplicationID+"/ca", handler) - actual, err := client.AccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.GetAccessCACertificate(context.Background(), testAccountRC, testAccessApplicationID) if assert.NoError(t, err) { assert.Equal(t, want, actual) } - mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) + mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+testAccessApplicationID+"/ca", handler) - actual, err = client.ZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.GetAccessCACertificate(context.Background(), testZoneRC, testAccessApplicationID) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestAcessCACertificates(t *testing.T) { +func TestAccessCACertificates(t *testing.T) { setup() defer teardown() @@ -80,7 +80,7 @@ func TestAcessCACertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/ca", handler) - actual, err := client.AccessCACertificates(context.Background(), testAccountID) + actual, _, err := client.ListAccessCACertificates(context.Background(), testAccountRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -88,14 +88,14 @@ func TestAcessCACertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/ca", handler) - actual, err = client.ZoneLevelAccessCACertificates(context.Background(), testZoneID) + actual, _, err = client.ListAccessCACertificates(context.Background(), testZoneRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestCreateAcessCACertificates(t *testing.T) { +func TestCreateAccessCACertificates(t *testing.T) { setup() defer teardown() @@ -123,7 +123,7 @@ func TestCreateAcessCACertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - actual, err := client.CreateAccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.CreateAccessCACertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -131,14 +131,14 @@ func TestCreateAcessCACertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - actual, err = client.CreateZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.CreateAccessCACertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) } } -func TestDeleteAcessCACertificates(t *testing.T) { +func TestDeleteAccessCACertificates(t *testing.T) { setup() defer teardown() @@ -158,13 +158,13 @@ func TestDeleteAcessCACertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - err := client.DeleteAccessCACertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err := client.DeleteAccessCACertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - err = client.DeleteZoneLevelAccessCACertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err = client.DeleteAccessCACertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) } diff --git a/cloudflare_test.go b/cloudflare_test.go index 5b7b1262ab2..659312f4da3 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -21,6 +21,12 @@ var ( // server is a test HTTP server used to provide mock API responses. server *httptest.Server + + // testAccountRC is a test account resource container + testAccountRC = AccountIdentifier(testAccountID) + + // testZoneRC is a test zone resource container + testZoneRC = ZoneIdentifier(testZoneID) ) func setup(opts ...Option) { From 0169485419e9a6ecc90ebed6d3f7b9fc41cb22e3 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 10:07:39 -0400 Subject: [PATCH 061/130] Refactor access groups --- .changelog/1319.txt | 14 +++- access_group.go | 167 ++++++++++++++++++------------------------- access_group_test.go | 28 ++++---- 3 files changed, 96 insertions(+), 113 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index f4c5868ad09..e58f44009c7 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -1,6 +1,18 @@ ```release-note:breaking-change +access_application: Merge all account and zone level operations to use Resource Container +``` +```release-note:enhancement access_application: add support for auto pagination ``` ```release-note:breaking-change -access_application: Merge all methods to use ResourceContainer +access_ca_certificate: Merge all account and zone level operations to use Resource Container +``` +```release-note:enhancement +access_ca_certificate: add support for auto pagination +``` +```release-note:breaking-change +access_group: Merge all account and zone level operations to use Resource Container +``` +```release-note:enhancement +access_group: add support for auto pagination ``` \ No newline at end of file diff --git a/access_group.go b/access_group.go index 9527e57092f..26d3437bdc8 100644 --- a/access_group.go +++ b/access_group.go @@ -21,11 +21,11 @@ type AccessGroup struct { Include []interface{} `json:"include"` // The exclude group works like a NOT logical operator. The user must - // not satisfy all of the rules in exclude. + // not satisfy all the rules in exclude. Exclude []interface{} `json:"exclude"` // The require group works like a AND logical operator. The user must - // satisfy all of the rules in require. + // satisfy all the rules in require. Require []interface{} `json:"require"` } @@ -39,7 +39,7 @@ type AccessGroupEmail struct { } // AccessGroupEmailDomain is used for managing access based on an email -// domain domain such as `example.com` instead of individual addresses. +// domain such as `example.com` instead of individual addresses. type AccessGroupEmailDomain struct { EmailDomain struct { Domain string `json:"domain"` @@ -203,69 +203,70 @@ type AccessGroupDetailResponse struct { Result AccessGroup `json:"result"` } -// AccessGroups returns all access groups for an access application. +// ListAccessGroups returns all access groups for an access application. // -// API reference: https://api.cloudflare.com/#access-groups-list-access-groups -func (api *API) AccessGroups(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]AccessGroup, ResultInfo, error) { - return api.accessGroups(ctx, accountID, pageOpts, AccountRouteRoot) -} - -// ZoneLevelAccessGroups returns all zone level access groups for an access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-groups-list-access-groups -func (api *API) ZoneLevelAccessGroups(ctx context.Context, zoneID string, pageOpts PaginationOptions) ([]AccessGroup, ResultInfo, error) { - return api.accessGroups(ctx, zoneID, pageOpts, ZoneRouteRoot) -} +// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-list-access-groups +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-list-access-groups +func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessGroup, *ResultInfo, error) { + baseURL := fmt.Sprintf("/%s/%s/access/groups", rc.Level, rc.Identifier) + + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false + } -func (api *API) accessGroups(ctx context.Context, id string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessGroup, ResultInfo, error) { - uri := buildURI( - fmt.Sprintf( - "/%s/%s/access/groups", - routeRoot, - id, - ), - pageOpts, - ) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessGroup{}, ResultInfo{}, err + if pageOpts.Page < 1 { + pageOpts.Page = 1 } - var accessGroupListResponse AccessGroupListResponse - err = json.Unmarshal(res, &accessGroupListResponse) - if err != nil { - return []AccessGroup{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, } - return accessGroupListResponse.Result, accessGroupListResponse.ResultInfo, nil -} + var accessGroups []AccessGroup + var r AccessGroupListResponse + + for { + uri := buildURI(baseURL, resultInfo) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + accessGroups = append(accessGroups, r.Result...) + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } -// AccessGroup returns a single group based on the group ID. -// -// API reference: https://api.cloudflare.com/#access-groups-access-group-details -func (api *API) AccessGroup(ctx context.Context, accountID, groupID string) (AccessGroup, error) { - return api.accessGroup(ctx, accountID, groupID, AccountRouteRoot) + return accessGroups, &r.ResultInfo, nil } -// ZoneLevelAccessGroup returns a single zone level group based on the group ID. +// GetAccessGroup returns a single group based on the group ID. // -// API reference: https://api.cloudflare.com/#zone-level-access-groups-access-group-details -func (api *API) ZoneLevelAccessGroup(ctx context.Context, zoneID, groupID string) (AccessGroup, error) { - return api.accessGroup(ctx, zoneID, groupID, ZoneRouteRoot) -} - -func (api *API) accessGroup(ctx context.Context, id, groupID string, routeRoot RouteRoot) (AccessGroup, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-get-an-access-group +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-get-an-access-group +func (api *API) GetAccessGroup(ctx context.Context, rc *ResourceContainer, groupID string) (AccessGroup, error) { uri := fmt.Sprintf( "/%s/%s/access/groups/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, groupID, ) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return AccessGroup{}, err + return AccessGroup{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessGroupDetailResponse AccessGroupDetailResponse @@ -277,30 +278,20 @@ func (api *API) accessGroup(ctx context.Context, id, groupID string, routeRoot R return accessGroupDetailResponse.Result, nil } -// CreateAccessGroup creates a new access group. +// CreateAccessGroup creates a new access group // -// API reference: https://api.cloudflare.com/#access-groups-create-access-group -func (api *API) CreateAccessGroup(ctx context.Context, accountID string, accessGroup AccessGroup) (AccessGroup, error) { - return api.createAccessGroup(ctx, accountID, accessGroup, AccountRouteRoot) -} - -// CreateZoneLevelAccessGroup creates a new zone level access group. -// -// API reference: https://api.cloudflare.com/#zone-level-access-groups-create-access-group -func (api *API) CreateZoneLevelAccessGroup(ctx context.Context, zoneID string, accessGroup AccessGroup) (AccessGroup, error) { - return api.createAccessGroup(ctx, zoneID, accessGroup, ZoneRouteRoot) -} - -func (api *API) createAccessGroup(ctx context.Context, id string, accessGroup AccessGroup, routeRoot RouteRoot) (AccessGroup, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-create-an-access-group +// Zone API Reference:https://developers.cloudflare.com/api/operations/zone-level-access-groups-create-an-access-group +func (api *API) CreateAccessGroup(ctx context.Context, rc *ResourceContainer, accessGroup AccessGroup) (AccessGroup, error) { uri := fmt.Sprintf( "/%s/%s/access/groups", - routeRoot, - id, + rc.Level, + rc.Identifier, ) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessGroup) if err != nil { - return AccessGroup{}, err + return AccessGroup{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessGroupDetailResponse AccessGroupDetailResponse @@ -312,29 +303,19 @@ func (api *API) createAccessGroup(ctx context.Context, id string, accessGroup Ac return accessGroupDetailResponse.Result, nil } -// UpdateAccessGroup updates an existing access group. -// -// API reference: https://api.cloudflare.com/#access-groups-update-access-group -func (api *API) UpdateAccessGroup(ctx context.Context, accountID string, accessGroup AccessGroup) (AccessGroup, error) { - return api.updateAccessGroup(ctx, accountID, accessGroup, AccountRouteRoot) -} - -// UpdateZoneLevelAccessGroup updates an existing zone level access group. +// UpdateAccessGroup updates an existing access group // -// API reference: https://api.cloudflare.com/#zone-level-access-groups-update-access-group -func (api *API) UpdateZoneLevelAccessGroup(ctx context.Context, zoneID string, accessGroup AccessGroup) (AccessGroup, error) { - return api.updateAccessGroup(ctx, zoneID, accessGroup, ZoneRouteRoot) -} - -func (api *API) updateAccessGroup(ctx context.Context, id string, accessGroup AccessGroup, routeRoot RouteRoot) (AccessGroup, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-update-an-access-group +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-update-an-access-group +func (api *API) UpdateAccessGroup(ctx context.Context, rc *ResourceContainer, accessGroup AccessGroup) (AccessGroup, error) { if accessGroup.ID == "" { return AccessGroup{}, fmt.Errorf("access group ID cannot be empty") } uri := fmt.Sprintf( "/%s/%s/access/groups/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, accessGroup.ID, ) @@ -352,31 +333,21 @@ func (api *API) updateAccessGroup(ctx context.Context, id string, accessGroup Ac return accessGroupDetailResponse.Result, nil } -// DeleteAccessGroup deletes an access group. -// -// API reference: https://api.cloudflare.com/#access-groups-delete-access-group -func (api *API) DeleteAccessGroup(ctx context.Context, accountID, groupID string) error { - return api.deleteAccessGroup(ctx, accountID, groupID, AccountRouteRoot) -} - -// DeleteZoneLevelAccessGroup deletes a zone level access group. +// DeleteAccessGroup deletes an access group // -// API reference: https://api.cloudflare.com/#zone-level-access-groups-delete-access-group -func (api *API) DeleteZoneLevelAccessGroup(ctx context.Context, zoneID, groupID string) error { - return api.deleteAccessGroup(ctx, zoneID, groupID, ZoneRouteRoot) -} - -func (api *API) deleteAccessGroup(ctx context.Context, id string, groupID string, routeRoot RouteRoot) error { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-delete-an-access-group +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-delete-an-access-group +func (api *API) DeleteAccessGroup(ctx context.Context, rc *ResourceContainer, groupID string) error { uri := fmt.Sprintf( "/%s/%s/access/groups/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, groupID, ) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return err + return fmt.Errorf("%s: %w", errMakeRequestError, err) } return nil diff --git a/access_group_test.go b/access_group_test.go index 7491a2aa4d4..4f961690cef 100644 --- a/access_group_test.go +++ b/access_group_test.go @@ -91,7 +91,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler) - actual, _, err := client.AccessGroups(context.Background(), testAccountID, pageOptions) + actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, pageOptions) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) @@ -99,7 +99,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, _, err = client.ZoneLevelAccessGroups(context.Background(), testZoneID, pageOptions) + actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, pageOptions) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) @@ -150,7 +150,7 @@ func TestAccessGroup(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler) - actual, err := client.AccessGroup(context.Background(), testAccountID, accessGroupID) + actual, err := client.GetAccessGroup(context.Background(), testAccountRC, accessGroupID) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -158,7 +158,7 @@ func TestAccessGroup(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler) - actual, err = client.ZoneLevelAccessGroup(context.Background(), testZoneID, accessGroupID) + actual, err = client.GetAccessGroup(context.Background(), testZoneRC, accessGroupID) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -228,7 +228,7 @@ func TestCreateAccessGroup(t *testing.T) { }, } - actual, err := client.CreateAccessGroup(context.Background(), testAccountID, accessGroup) + actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, accessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -236,7 +236,7 @@ func TestCreateAccessGroup(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, err = client.CreateZoneLevelAccessGroup(context.Background(), testZoneID, accessGroup) + actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, accessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -286,14 +286,14 @@ func TestUpdateAccessGroup(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler) - actual, err := client.UpdateAccessGroup(context.Background(), testAccountID, expectedAccessGroup) + actual, err := client.UpdateAccessGroup(context.Background(), testAccountRC, expectedAccessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) } mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler) - actual, err = client.UpdateZoneLevelAccessGroup(context.Background(), testZoneID, expectedAccessGroup) + actual, err = client.UpdateAccessGroup(context.Background(), testZoneRC, expectedAccessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -304,10 +304,10 @@ func TestUpdateAccessGroupWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessGroup(context.Background(), testAccountID, AccessGroup{}) + _, err := client.UpdateAccessGroup(context.Background(), testAccountRC, AccessGroup{}) assert.EqualError(t, err, "access group ID cannot be empty") - _, err = client.UpdateZoneLevelAccessGroup(context.Background(), testZoneID, AccessGroup{}) + _, err = client.UpdateAccessGroup(context.Background(), testZoneRC, AccessGroup{}) assert.EqualError(t, err, "access group ID cannot be empty") } @@ -330,12 +330,12 @@ func TestDeleteAccessGroup(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler) - err := client.DeleteAccessGroup(context.Background(), testAccountID, accessGroupID) + err := client.DeleteAccessGroup(context.Background(), testAccountRC, accessGroupID) assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler) - err = client.DeleteZoneLevelAccessGroup(context.Background(), testZoneID, accessGroupID) + err = client.DeleteAccessGroup(context.Background(), testZoneRC, accessGroupID) assert.NoError(t, err) } @@ -379,7 +379,7 @@ func TestCreateIPListAccessGroup(t *testing.T) { }, } - actual, err := client.CreateAccessGroup(context.Background(), testAccountID, accessGroup) + actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, accessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroupIpList, actual) @@ -387,7 +387,7 @@ func TestCreateIPListAccessGroup(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, err = client.CreateZoneLevelAccessGroup(context.Background(), testZoneID, accessGroup) + actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, accessGroup) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroupIpList, actual) From 532f353e0cded17cdb906bce6aca19e05318ed02 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 14:46:02 -0400 Subject: [PATCH 062/130] Merge access_user_tokens --- .changelog/1319.txt | 3 +++ access_user_tokens.go | 32 +++++++++++++++++--------------- access_user_tokens_test.go | 4 ++-- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index e58f44009c7..2d8e2fb1325 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -15,4 +15,7 @@ access_group: Merge all account and zone level operations to use Resource Contai ``` ```release-note:enhancement access_group: add support for auto pagination +``` +```release-note:breaking-change +access_user_token: Merge all account and zone level operations to use Resource Container ``` \ No newline at end of file diff --git a/access_user_tokens.go b/access_user_tokens.go index 81f73fa30f1..a1494089e4a 100644 --- a/access_user_tokens.go +++ b/access_user_tokens.go @@ -10,24 +10,26 @@ type AccessUserEmail struct { Email string `json:"email"` } -// RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user -// Access User. +//// RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user +//// Access User. +//// +//// API reference: https://api.cloudflare.com/#access-organizations-revoke-all-access-tokens-for-a-user +//func (api *API) RevokeAccessUserTokens(ctx context.Context, accountID string, accessUserEmail AccessUserEmail) error { +// return api.revokeUserTokens(ctx, accountID, accessUserEmail, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#access-organizations-revoke-all-access-tokens-for-a-user -func (api *API) RevokeAccessUserTokens(ctx context.Context, accountID string, accessUserEmail AccessUserEmail) error { - return api.revokeUserTokens(ctx, accountID, accessUserEmail, AccountRouteRoot) -} +//// RevokeZoneLevelAccessUserTokens revokes any outstanding tokens issued for a specific user +//// Access User. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-revoke-all-access-tokens-for-a-user +//func (api *API) RevokeZoneLevelAccessUserTokens(ctx context.Context, zoneID string, accessUserEmail AccessUserEmail) error { +// return api.revokeUserTokens(ctx, zoneID, accessUserEmail, ZoneRouteRoot) +//} -// RevokeZoneLevelAccessUserTokens revokes any outstanding tokens issued for a specific user +// RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user // Access User. -// -// API reference: https://api.cloudflare.com/#zone-level-access-organizations-revoke-all-access-tokens-for-a-user -func (api *API) RevokeZoneLevelAccessUserTokens(ctx context.Context, zoneID string, accessUserEmail AccessUserEmail) error { - return api.revokeUserTokens(ctx, zoneID, accessUserEmail, ZoneRouteRoot) -} - -func (api *API) revokeUserTokens(ctx context.Context, id string, accessUserEmail AccessUserEmail, routeRoot RouteRoot) error { - uri := fmt.Sprintf("/%s/%s/access/organizations/revoke_user", routeRoot, id) +func (api *API) RevokeAccessUserTokens(ctx context.Context, rc *ResourceContainer, accessUserEmail AccessUserEmail) error { + uri := fmt.Sprintf("/%s/%s/access/organizations/revoke_user", rc.Level, rc.Identifier) _, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessUserEmail) if err != nil { diff --git a/access_user_tokens_test.go b/access_user_tokens_test.go index c1cb268c9f3..5fb7e18919a 100644 --- a/access_user_tokens_test.go +++ b/access_user_tokens_test.go @@ -27,7 +27,7 @@ func TestRevokeAccessUserTokens(t *testing.T) { AccessUserEmail := AccessUserEmail{Email: "test@example.com"} - err := client.RevokeAccessUserTokens(context.Background(), testAccountID, AccessUserEmail) + err := client.RevokeAccessUserTokens(context.Background(), testAccountRC, AccessUserEmail) assert.NoError(t, err) } @@ -50,7 +50,7 @@ func TestRevokeZoneLevelAccessUserTokens(t *testing.T) { AccessUserEmail := AccessUserEmail{Email: "test@example.com"} - err := client.RevokeZoneLevelAccessUserTokens(context.Background(), testZoneID, AccessUserEmail) + err := client.RevokeAccessUserTokens(context.Background(), testZoneRC, AccessUserEmail) assert.NoError(t, err) } From f41e456d9755970bdd662ec3e2084986d202365c Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 15:05:31 -0400 Subject: [PATCH 063/130] Merge access_mutal_tls_certificates --- .changelog/1319.txt | 3 + access_mutual_tls_certificates.go | 161 ++++++++++--------------- access_mutual_tls_certificates_test.go | 20 +-- 3 files changed, 80 insertions(+), 104 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index 2d8e2fb1325..20ef3bb74af 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -17,5 +17,8 @@ access_group: Merge all account and zone level operations to use Resource Contai access_group: add support for auto pagination ``` ```release-note:breaking-change +access_mutual_tls_certificates: Merge all account and zone level operations to use Resource Container +``` +```release-note:breaking-change access_user_token: Merge all account and zone level operations to use Resource Container ``` \ No newline at end of file diff --git a/access_mutual_tls_certificates.go b/access_mutual_tls_certificates.go index af1eef535e6..f3e8e13b1ea 100644 --- a/access_mutual_tls_certificates.go +++ b/access_mutual_tls_certificates.go @@ -25,7 +25,8 @@ type AccessMutualTLSCertificate struct { // Mutual TLS certificates. type AccessMutualTLSCertificateListResponse struct { Response - Result []AccessMutualTLSCertificate `json:"result"` + Result []AccessMutualTLSCertificate `json:"result"` + ResultInfo `json:"result_info"` } // AccessMutualTLSCertificateDetailResponse is the API response for a single @@ -35,64 +36,69 @@ type AccessMutualTLSCertificateDetailResponse struct { Result AccessMutualTLSCertificate `json:"result"` } -// AccessMutualTLSCertificates returns all Access TLS certificates for the account -// level. +// ListAccessMutualTLSCertificates returns all Access TLS certificates // -// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-properties -func (api *API) AccessMutualTLSCertificates(ctx context.Context, accountID string) ([]AccessMutualTLSCertificate, error) { - return api.accessMutualTLSCertificates(ctx, accountID, AccountRouteRoot) -} - -// ZoneAccessMutualTLSCertificates returns all Access TLS certificates for the -// zone level. -// -// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-properties -func (api *API) ZoneAccessMutualTLSCertificates(ctx context.Context, zoneID string) ([]AccessMutualTLSCertificate, error) { - return api.accessMutualTLSCertificates(ctx, zoneID, ZoneRouteRoot) -} - -func (api *API) accessMutualTLSCertificates(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessMutualTLSCertificate, error) { - uri := fmt.Sprintf( +// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-list-mtls-certificates +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-list-mtls-certificates +func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessMutualTLSCertificate, *ResultInfo, error) { + baseURL := fmt.Sprintf( "/%s/%s/access/certificates", - routeRoot, - id, + rc.Level, + rc.Identifier, ) - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessMutualTLSCertificate{}, err + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false } - var accessMutualTLSCertificateListResponse AccessMutualTLSCertificateListResponse - err = json.Unmarshal(res, &accessMutualTLSCertificateListResponse) - if err != nil { - return []AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 } - return accessMutualTLSCertificateListResponse.Result, nil -} + if pageOpts.Page < 1 { + pageOpts.Page = 1 + } -// AccessMutualTLSCertificate returns a single account level Access Mutual TLS -// certificate. -// -// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-access-certificate-details -func (api *API) AccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string) (AccessMutualTLSCertificate, error) { - return api.accessMutualTLSCertificate(ctx, accountID, certificateID, AccountRouteRoot) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, + } + + var accessCertificates []AccessMutualTLSCertificate + var r AccessMutualTLSCertificateListResponse + + for { + uri := buildURI(baseURL, pageOpts) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + accessCertificates = append(accessCertificates, r.Result...) + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } + + return accessCertificates, &r.ResultInfo, nil } -// ZoneAccessMutualTLSCertificate returns a single zone level Access Mutual TLS +// GetAccessMutualTLSCertificate returns a single Access Mutual TLS // certificate. // -// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-access-certificate-details -func (api *API) ZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string) (AccessMutualTLSCertificate, error) { - return api.accessMutualTLSCertificate(ctx, zoneID, certificateID, ZoneRouteRoot) -} - -func (api *API) accessMutualTLSCertificate(ctx context.Context, id, certificateID string, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-get-an-mtls-certificate +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-get-an-mtls-certificate +func (api *API) GetAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) (AccessMutualTLSCertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/certificates/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, certificateID, ) @@ -110,27 +116,16 @@ func (api *API) accessMutualTLSCertificate(ctx context.Context, id, certificateI return accessMutualTLSCertificateDetailResponse.Result, nil } -// CreateAccessMutualTLSCertificate creates an account level Access TLS Mutual +// CreateAccessMutualTLSCertificate creates an Access TLS Mutual // certificate. // -// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-create-access-certificate -func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, accountID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { - return api.createAccessMutualTLSCertificate(ctx, accountID, certificate, AccountRouteRoot) -} - -// CreateZoneAccessMutualTLSCertificate creates a zone level Access TLS Mutual -// certificate. -// -// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-create-access-certificate -func (api *API) CreateZoneAccessMutualTLSCertificate(ctx context.Context, zoneID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { - return api.createAccessMutualTLSCertificate(ctx, zoneID, certificate, ZoneRouteRoot) -} - -func (api *API) createAccessMutualTLSCertificate(ctx context.Context, id string, certificate AccessMutualTLSCertificate, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-add-an-mtls-certificate +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-add-an-mtls-certificate +func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/certificates", - routeRoot, - id, + rc.Level, + rc.Identifier, ) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, certificate) @@ -150,24 +145,13 @@ func (api *API) createAccessMutualTLSCertificate(ctx context.Context, id string, // UpdateAccessMutualTLSCertificate updates an account level Access TLS Mutual // certificate. // -// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-update-access-certificate -func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { - return api.updateAccessMutualTLSCertificate(ctx, accountID, certificateID, certificate, AccountRouteRoot) -} - -// UpdateZoneAccessMutualTLSCertificate updates a zone level Access TLS Mutual -// certificate. -// -// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-update-access-certificate -func (api *API) UpdateZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { - return api.updateAccessMutualTLSCertificate(ctx, zoneID, certificateID, certificate, ZoneRouteRoot) -} - -func (api *API) updateAccessMutualTLSCertificate(ctx context.Context, id string, certificateID string, certificate AccessMutualTLSCertificate, routeRoot RouteRoot) (AccessMutualTLSCertificate, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-update-an-mtls-certificate +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-update-an-mtls-certificate +func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/certificates/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, certificateID, ) @@ -185,27 +169,16 @@ func (api *API) updateAccessMutualTLSCertificate(ctx context.Context, id string, return accessMutualTLSCertificateDetailResponse.Result, nil } -// DeleteAccessMutualTLSCertificate destroys an account level Access Mutual +// DeleteAccessMutualTLSCertificate destroys an Access Mutual // TLS certificate. // -// API reference: https://api.cloudflare.com/#access-mutual-tls-authentication-update-access-certificate -func (api *API) DeleteAccessMutualTLSCertificate(ctx context.Context, accountID, certificateID string) error { - return api.deleteAccessMutualTLSCertificate(ctx, accountID, certificateID, AccountRouteRoot) -} - -// DeleteZoneAccessMutualTLSCertificate destroys a zone level Access Mutual TLS -// certificate. -// -// API reference: https://api.cloudflare.com/#zone-level-access-mutual-tls-authentication-update-access-certificate -func (api *API) DeleteZoneAccessMutualTLSCertificate(ctx context.Context, zoneID, certificateID string) error { - return api.deleteAccessMutualTLSCertificate(ctx, zoneID, certificateID, ZoneRouteRoot) -} - -func (api *API) deleteAccessMutualTLSCertificate(ctx context.Context, id, certificateID string, routeRoot RouteRoot) error { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-delete-an-mtls-certificate +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-delete-an-mtls-certificate +func (api *API) DeleteAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string) error { uri := fmt.Sprintf( "/%s/%s/access/certificates/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, certificateID, ) diff --git a/access_mutual_tls_certificates_test.go b/access_mutual_tls_certificates_test.go index fd567398c97..67a53355384 100644 --- a/access_mutual_tls_certificates_test.go +++ b/access_mutual_tls_certificates_test.go @@ -53,7 +53,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates", handler) - actual, err := client.AccessMutualTLSCertificates(context.Background(), testAccountID) + actual, _, err := client.ListAccessMutualTLSCertificates(context.Background(), testAccountRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -61,7 +61,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates", handler) - actual, err = client.ZoneAccessMutualTLSCertificates(context.Background(), testZoneID) + actual, _, err = client.ListAccessMutualTLSCertificates(context.Background(), testZoneRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -109,7 +109,7 @@ func TestAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.AccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.GetAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -117,7 +117,7 @@ func TestAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.ZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.GetAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -170,7 +170,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates", handler) - actual, err := client.CreateAccessMutualTLSCertificate(context.Background(), testAccountID, certificate) + actual, err := client.CreateAccessMutualTLSCertificate(context.Background(), testAccountRC, certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -178,7 +178,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates", handler) - actual, err = client.CreateZoneAccessMutualTLSCertificate(context.Background(), testZoneID, certificate) + actual, err = client.CreateAccessMutualTLSCertificate(context.Background(), testZoneRC, certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -231,7 +231,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) + actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -239,7 +239,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) + actual, err = client.UpdateAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -265,13 +265,13 @@ func TestDeleteAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - err := client.DeleteAccessMutualTLSCertificate(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err := client.DeleteAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - err = client.DeleteZoneAccessMutualTLSCertificate(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + err = client.DeleteAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") assert.NoError(t, err) } From 898f9587727250c5fc7636e764e9565e90a5f8c4 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 15:18:50 -0400 Subject: [PATCH 064/130] Merge access_organization --- .changelog/1319.txt | 3 ++ access_organization.go | 82 +++++++++++++++++++------------------ access_organization_test.go | 12 +++--- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index 20ef3bb74af..122b86a5d39 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -20,5 +20,8 @@ access_group: add support for auto pagination access_mutual_tls_certificates: Merge all account and zone level operations to use Resource Container ``` ```release-note:breaking-change +access_organization: Merge all account and zone level operations to use Resource Container +``` +```release-note:breaking-change access_user_token: Merge all account and zone level operations to use Resource Container ``` \ No newline at end of file diff --git a/access_organization.go b/access_organization.go index ff2fef9ded6..39f77da7670 100644 --- a/access_organization.go +++ b/access_organization.go @@ -47,22 +47,22 @@ type AccessOrganizationDetailResponse struct { Result AccessOrganization `json:"result"` } -// AccessOrganization returns the Access organisation details. +//// AccessOrganization returns the Access organisation details. +//// +//// API reference: https://api.cloudflare.com/#access-organizations-access-organization-details +//func (api *API) AccessOrganization(ctx context.Context, accountID string) (AccessOrganization, ResultInfo, error) { +// return api.accessOrganization(ctx, accountID, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#access-organizations-access-organization-details -func (api *API) AccessOrganization(ctx context.Context, accountID string) (AccessOrganization, ResultInfo, error) { - return api.accessOrganization(ctx, accountID, AccountRouteRoot) -} - -// ZoneLevelAccessOrganization returns the zone level Access organisation details. -// -// API reference: https://api.cloudflare.com/#zone-level-access-organizations-access-organization-details -func (api *API) ZoneLevelAccessOrganization(ctx context.Context, zoneID string) (AccessOrganization, ResultInfo, error) { - return api.accessOrganization(ctx, zoneID, ZoneRouteRoot) -} +//// ZoneLevelAccessOrganization returns the zone level Access organisation details. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-access-organization-details +//func (api *API) ZoneLevelAccessOrganization(ctx context.Context, zoneID string) (AccessOrganization, ResultInfo, error) { +// return api.accessOrganization(ctx, zoneID, ZoneRouteRoot) +//} -func (api *API) accessOrganization(ctx context.Context, id string, routeRoot RouteRoot) (AccessOrganization, ResultInfo, error) { - uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id) +func (api *API) GetAccessOrganization(ctx context.Context, rc *ResourceContainer) (AccessOrganization, ResultInfo, error) { + uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -78,22 +78,22 @@ func (api *API) accessOrganization(ctx context.Context, id string, routeRoot Rou return accessOrganizationListResponse.Result, accessOrganizationListResponse.ResultInfo, nil } -// CreateAccessOrganization creates the Access organisation details. +//// CreateAccessOrganization creates the Access organisation details. +//// +//// API reference: https://api.cloudflare.com/#access-organizations-create-access-organization +//func (api *API) CreateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { +// return api.createAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#access-organizations-create-access-organization -func (api *API) CreateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { - return api.createAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) -} +//// CreateZoneLevelAccessOrganization creates the zone level Access organisation details. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-create-access-organization +//func (api *API) CreateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { +// return api.createAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) +//} -// CreateZoneLevelAccessOrganization creates the zone level Access organisation details. -// -// API reference: https://api.cloudflare.com/#zone-level-access-organizations-create-access-organization -func (api *API) CreateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { - return api.createAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) -} - -func (api *API) createAccessOrganization(ctx context.Context, id string, accessOrganization AccessOrganization, routeRoot RouteRoot) (AccessOrganization, error) { - uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id) +func (api *API) CreateAccessOrganization(ctx context.Context, rc *ResourceContainer, accessOrganization AccessOrganization) (AccessOrganization, error) { + uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessOrganization) if err != nil { @@ -112,19 +112,23 @@ func (api *API) createAccessOrganization(ctx context.Context, id string, accessO // UpdateAccessOrganization updates the Access organisation details. // // API reference: https://api.cloudflare.com/#access-organizations-update-access-organization -func (api *API) UpdateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { - return api.updateAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) -} - -// UpdateZoneLevelAccessOrganization updates the zone level Access organisation details. +//func (api *API) UpdateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { +// return api.updateAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization -func (api *API) UpdateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { - return api.updateAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) -} +//// UpdateZoneLevelAccessOrganization updates the zone level Access organisation details. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization +//func (api *API) UpdateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { +// return api.updateAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) +//} -func (api *API) updateAccessOrganization(ctx context.Context, id string, accessOrganization AccessOrganization, routeRoot RouteRoot) (AccessOrganization, error) { - uri := fmt.Sprintf("/%s/%s/access/organizations", routeRoot, id) +// UpdateAccessOrganization updates the Access organisation details. +// +// Account API reference: https://api.cloudflare.com/#access-organizations-update-access-organization +// Zone API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization +func (api *API) UpdateAccessOrganization(ctx context.Context, rc *ResourceContainer, accessOrganization AccessOrganization) (AccessOrganization, error) { + uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessOrganization) if err != nil { diff --git a/access_organization_test.go b/access_organization_test.go index 3ea79970a4c..ca7309c50bf 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -63,7 +63,7 @@ func TestAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, _, err := client.AccessOrganization(context.Background(), testAccountID) + actual, _, err := client.GetAccessOrganization(context.Background(), testAccountRC) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -71,7 +71,7 @@ func TestAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, _, err = client.ZoneLevelAccessOrganization(context.Background(), testZoneID) + actual, _, err = client.GetAccessOrganization(context.Background(), testZoneRC) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -127,7 +127,7 @@ func TestCreateAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, err := client.CreateAccessOrganization(context.Background(), testAccountID, want) + actual, err := client.CreateAccessOrganization(context.Background(), testAccountRC, want) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -135,7 +135,7 @@ func TestCreateAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, err = client.CreateZoneLevelAccessOrganization(context.Background(), testZoneID, want) + actual, err = client.CreateAccessOrganization(context.Background(), testZoneRC, want) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -193,7 +193,7 @@ func TestUpdateAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, err := client.UpdateAccessOrganization(context.Background(), testAccountID, want) + actual, err := client.UpdateAccessOrganization(context.Background(), testAccountRC, want) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -201,7 +201,7 @@ func TestUpdateAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, err = client.UpdateZoneLevelAccessOrganization(context.Background(), testZoneID, want) + actual, err = client.UpdateAccessOrganization(context.Background(), testZoneRC, want) if assert.NoError(t, err) { assert.Equal(t, want, actual) From 73f4b46638561ab5cfc90e04cc37b56f73952061 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 15:56:22 -0400 Subject: [PATCH 065/130] Merge access_service_tokens --- .changelog/1319.txt | 3 + access_service_tokens.go | 108 +++++++++++++++++----------------- access_service_tokens_test.go | 20 +++---- 3 files changed, 67 insertions(+), 64 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index 122b86a5d39..3055700b1dc 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -23,5 +23,8 @@ access_mutual_tls_certificates: Merge all account and zone level operations to u access_organization: Merge all account and zone level operations to use Resource Container ``` ```release-note:breaking-change +access_service_tokens: Merge all account and zone level operations to use Resource Container +``` +```release-note:breaking-change access_user_token: Merge all account and zone level operations to use Resource Container ``` \ No newline at end of file diff --git a/access_service_tokens.go b/access_service_tokens.go index d0f5314f20b..f2298373721 100644 --- a/access_service_tokens.go +++ b/access_service_tokens.go @@ -119,22 +119,22 @@ type AccessServiceTokensRotateSecretDetailResponse struct { Result AccessServiceTokenRotateResponse `json:"result"` } -// AccessServiceTokens returns all Access Service Tokens for an account. +//// AccessServiceTokens returns all Access Service Tokens for an account. +//// +//// API reference: https://api.cloudflare.com/#access-service-tokens-list-access-service-tokens +//func (api *API) AccessServiceTokens(ctx context.Context, accountID string) ([]AccessServiceToken, ResultInfo, error) { +// return api.accessServiceTokens(ctx, accountID, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#access-service-tokens-list-access-service-tokens -func (api *API) AccessServiceTokens(ctx context.Context, accountID string) ([]AccessServiceToken, ResultInfo, error) { - return api.accessServiceTokens(ctx, accountID, AccountRouteRoot) -} - -// ZoneLevelAccessServiceTokens returns all Access Service Tokens for a zone. -// -// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-list-access-service-tokens -func (api *API) ZoneLevelAccessServiceTokens(ctx context.Context, zoneID string) ([]AccessServiceToken, ResultInfo, error) { - return api.accessServiceTokens(ctx, zoneID, ZoneRouteRoot) -} +//// ZoneLevelAccessServiceTokens returns all Access Service Tokens for a zone. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-list-access-service-tokens +//func (api *API) ZoneLevelAccessServiceTokens(ctx context.Context, zoneID string) ([]AccessServiceToken, ResultInfo, error) { +// return api.accessServiceTokens(ctx, zoneID, ZoneRouteRoot) +//} -func (api *API) accessServiceTokens(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessServiceToken, ResultInfo, error) { - uri := fmt.Sprintf("/%s/%s/access/service_tokens", routeRoot, id) +func (api *API) ListAccessServiceTokens(ctx context.Context, rc *ResourceContainer) ([]AccessServiceToken, ResultInfo, error) { + uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -150,22 +150,22 @@ func (api *API) accessServiceTokens(ctx context.Context, id string, routeRoot Ro return accessServiceTokensListResponse.Result, accessServiceTokensListResponse.ResultInfo, nil } -// CreateAccessServiceToken creates a new Access Service Token for an account. +//// CreateAccessServiceToken creates a new Access Service Token for an account. +//// +//// API reference: https://api.cloudflare.com/#access-service-tokens-create-access-service-token +//func (api *API) CreateAccessServiceToken(ctx context.Context, accountID, name string) (AccessServiceTokenCreateResponse, error) { +// return api.createAccessServiceToken(ctx, accountID, name, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#access-service-tokens-create-access-service-token -func (api *API) CreateAccessServiceToken(ctx context.Context, accountID, name string) (AccessServiceTokenCreateResponse, error) { - return api.createAccessServiceToken(ctx, accountID, name, AccountRouteRoot) -} - -// CreateZoneLevelAccessServiceToken creates a new Access Service Token for a zone. -// -// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-create-access-service-token -func (api *API) CreateZoneLevelAccessServiceToken(ctx context.Context, zoneID, name string) (AccessServiceTokenCreateResponse, error) { - return api.createAccessServiceToken(ctx, zoneID, name, ZoneRouteRoot) -} - -func (api *API) createAccessServiceToken(ctx context.Context, id, name string, routeRoot RouteRoot) (AccessServiceTokenCreateResponse, error) { - uri := fmt.Sprintf("/%s/%s/access/service_tokens", routeRoot, id) +//// CreateZoneLevelAccessServiceToken creates a new Access Service Token for a zone. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-create-access-service-token +//func (api *API) CreateZoneLevelAccessServiceToken(ctx context.Context, zoneID, name string) (AccessServiceTokenCreateResponse, error) { +// return api.createAccessServiceToken(ctx, zoneID, name, ZoneRouteRoot) +//} + +func (api *API) CreateAccessServiceToken(ctx context.Context, rc *ResourceContainer, name string) (AccessServiceTokenCreateResponse, error) { + uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier) marshalledName, _ := json.Marshal(struct { Name string `json:"name"` }{name}) @@ -189,20 +189,20 @@ func (api *API) createAccessServiceToken(ctx context.Context, id, name string, r // account. // // API reference: https://api.cloudflare.com/#access-service-tokens-update-access-service-token -func (api *API) UpdateAccessServiceToken(ctx context.Context, accountID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { - return api.updateAccessServiceToken(ctx, accountID, uuid, name, AccountRouteRoot) -} - -// UpdateZoneLevelAccessServiceToken updates an existing Access Service Token for a -// zone. +//func (api *API) UpdateAccessServiceToken(ctx context.Context, accountID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { +// return api.updateAccessServiceToken(ctx, accountID, uuid, name, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-update-access-service-token -func (api *API) UpdateZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { - return api.updateAccessServiceToken(ctx, zoneID, uuid, name, ZoneRouteRoot) -} +//// UpdateZoneLevelAccessServiceToken updates an existing Access Service Token for a +//// zone. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-update-access-service-token +//func (api *API) UpdateZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { +// return api.updateAccessServiceToken(ctx, zoneID, uuid, name, ZoneRouteRoot) +//} -func (api *API) updateAccessServiceToken(ctx context.Context, id, uuid, name string, routeRoot RouteRoot) (AccessServiceTokenUpdateResponse, error) { - uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", routeRoot, id, uuid) +func (api *API) UpdateAccessServiceToken(ctx context.Context, rc *ResourceContainer, uuid, name string) (AccessServiceTokenUpdateResponse, error) { + uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, uuid) marshalledName, _ := json.Marshal(struct { Name string `json:"name"` @@ -226,20 +226,20 @@ func (api *API) updateAccessServiceToken(ctx context.Context, id, uuid, name str // account. // // API reference: https://api.cloudflare.com/#access-service-tokens-delete-access-service-token -func (api *API) DeleteAccessServiceToken(ctx context.Context, accountID, uuid string) (AccessServiceTokenUpdateResponse, error) { - return api.deleteAccessServiceToken(ctx, accountID, uuid, AccountRouteRoot) -} - -// DeleteZoneLevelAccessServiceToken removes an existing Access Service Token for a -// zone. +//func (api *API) DeleteAccessServiceToken(ctx context.Context, accountID, uuid string) (AccessServiceTokenUpdateResponse, error) { +// return api.deleteAccessServiceToken(ctx, accountID, uuid, AccountRouteRoot) +//} // -// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-delete-access-service-token -func (api *API) DeleteZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid string) (AccessServiceTokenUpdateResponse, error) { - return api.deleteAccessServiceToken(ctx, zoneID, uuid, ZoneRouteRoot) -} - -func (api *API) deleteAccessServiceToken(ctx context.Context, id, uuid string, routeRoot RouteRoot) (AccessServiceTokenUpdateResponse, error) { - uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", routeRoot, id, uuid) +//// DeleteZoneLevelAccessServiceToken removes an existing Access Service Token for a +//// zone. +//// +//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-delete-access-service-token +//func (api *API) DeleteZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid string) (AccessServiceTokenUpdateResponse, error) { +// return api.deleteAccessServiceToken(ctx, zoneID, uuid, ZoneRouteRoot) +//} + +func (api *API) DeleteAccessServiceToken(ctx context.Context, rc *ResourceContainer, uuid string) (AccessServiceTokenUpdateResponse, error) { + uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, uuid) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { diff --git a/access_service_tokens_test.go b/access_service_tokens_test.go index cbaa69c4652..27de1aedcb1 100644 --- a/access_service_tokens_test.go +++ b/access_service_tokens_test.go @@ -52,7 +52,7 @@ func TestAccessServiceTokens(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler) - actual, _, err := client.AccessServiceTokens(context.Background(), testAccountID) + actual, _, err := client.ListAccessServiceTokens(context.Background(), testAccountRC) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -60,7 +60,7 @@ func TestAccessServiceTokens(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler) - actual, _, err = client.ZoneLevelAccessServiceTokens(context.Background(), testZoneID) + actual, _, err = client.ListAccessServiceTokens(context.Background(), testZoneRC) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -103,7 +103,7 @@ func TestCreateAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler) - actual, err := client.CreateAccessServiceToken(context.Background(), testAccountID, "CI/CD token") + actual, err := client.CreateAccessServiceToken(context.Background(), testAccountRC, "CI/CD token") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -111,7 +111,7 @@ func TestCreateAccessServiceToken(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler) - actual, err = client.CreateZoneLevelAccessServiceToken(context.Background(), testZoneID, "CI/CD token") + actual, err = client.CreateAccessServiceToken(context.Background(), testZoneRC, "CI/CD token") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -152,7 +152,7 @@ func TestUpdateAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") + actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -160,7 +160,7 @@ func TestUpdateAccessServiceToken(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateZoneLevelAccessServiceToken(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") + actual, err = client.UpdateAccessServiceToken(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -201,7 +201,7 @@ func TestRefreshAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/refresh", handler) - actual, err := client.RefreshAccessServiceToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.RefreshAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -244,7 +244,7 @@ func TestRotateAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/rotate", handler) - actual, err := client.RotateAccessServiceToken(context.Background(), AccountIdentifier(testAccountID), "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.RotateAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -285,7 +285,7 @@ func TestDeleteAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.DeleteAccessServiceToken(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.DeleteAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -293,7 +293,7 @@ func TestDeleteAccessServiceToken(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.DeleteZoneLevelAccessServiceToken(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.DeleteAccessServiceToken(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, expected, actual) From aea67356ed58c866368a4fd875711bde380e47c9 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 16:15:11 -0400 Subject: [PATCH 066/130] Merge access policy --- .changelog/1319.txt | 15 ++++ access_policy.go | 164 ++++++++++++++++++------------------------ access_policy_test.go | 24 +++---- 3 files changed, 96 insertions(+), 107 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index 3055700b1dc..beffa338d4a 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -4,24 +4,39 @@ access_application: Merge all account and zone level operations to use Resource ```release-note:enhancement access_application: add support for auto pagination ``` + ```release-note:breaking-change access_ca_certificate: Merge all account and zone level operations to use Resource Container ``` ```release-note:enhancement access_ca_certificate: add support for auto pagination ``` + ```release-note:breaking-change access_group: Merge all account and zone level operations to use Resource Container ``` ```release-note:enhancement access_group: add support for auto pagination ``` + ```release-note:breaking-change access_mutual_tls_certificates: Merge all account and zone level operations to use Resource Container ``` +```release-note:enhancement +access_mutual_tls_certificates: add support for auto pagination +``` + ```release-note:breaking-change access_organization: Merge all account and zone level operations to use Resource Container ``` + +```release-note:breaking-change +access_policy: Merge all account and zone level operations to use Resource Container +``` +```release-note:enhancement +access_policy: add support for auto pagination +``` + ```release-note:breaking-change access_service_tokens: Merge all account and zone level operations to use Resource Container ``` diff --git a/access_policy.go b/access_policy.go index a7823f79fc1..4f98c44ae8b 100644 --- a/access_policy.go +++ b/access_policy.go @@ -35,11 +35,11 @@ type AccessPolicy struct { Include []interface{} `json:"include"` // The exclude policy works like a NOT logical operator. The user must - // not satisfy all of the rules in exclude. + // not satisfy all the rules in exclude. Exclude []interface{} `json:"exclude"` // The require policy works like a AND logical operator. The user must - // satisfy all of the rules in require. + // satisfy all the rules in require. Require []interface{} `json:"require"` } @@ -60,71 +60,75 @@ type AccessPolicyDetailResponse struct { Result AccessPolicy `json:"result"` } -// AccessPolicies returns all access policies for an access application. +// ListAccessPolicies returns all access policies for an access application. // -// API reference: https://api.cloudflare.com/#access-policy-list-access-policies -func (api *API) AccessPolicies(ctx context.Context, accountID, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, ResultInfo, error) { - return api.accessPolicies(ctx, accountID, applicationID, pageOpts, AccountRouteRoot) -} +// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-list-access-policies +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-list-access-policies +func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, *ResultInfo, error) { + baseURL := fmt.Sprintf( + "/%s/%s/access/apps/%s/policies", + rc.Level, + rc.Identifier, + applicationID, + ) -// ZoneLevelAccessPolicies returns all zone level access policies for an access application. -// -// API reference: https://api.cloudflare.com/#zone-level-access-policy-list-access-policies -func (api *API) ZoneLevelAccessPolicies(ctx context.Context, zoneID, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, ResultInfo, error) { - return api.accessPolicies(ctx, zoneID, applicationID, pageOpts, ZoneRouteRoot) -} + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false + } -func (api *API) accessPolicies(ctx context.Context, id string, applicationID string, pageOpts PaginationOptions, routeRoot RouteRoot) ([]AccessPolicy, ResultInfo, error) { - uri := buildURI( - fmt.Sprintf( - "/%s/%s/access/apps/%s/policies", - routeRoot, - id, - applicationID, - ), - pageOpts, - ) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessPolicy{}, ResultInfo{}, err + if pageOpts.Page < 1 { + pageOpts.Page = 1 } - var accessPolicyListResponse AccessPolicyListResponse - err = json.Unmarshal(res, &accessPolicyListResponse) - if err != nil { - return []AccessPolicy{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, } - return accessPolicyListResponse.Result, accessPolicyListResponse.ResultInfo, nil -} + var accessPolicies []AccessPolicy + var r AccessPolicyListResponse + for { + uri := buildURI(baseURL, pageOpts) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + accessPolicies = append(accessPolicies, r.Result...) + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } -// AccessPolicy returns a single policy based on the policy ID. -// -// API reference: https://api.cloudflare.com/#access-policy-access-policy-details -func (api *API) AccessPolicy(ctx context.Context, accountID, applicationID, policyID string) (AccessPolicy, error) { - return api.accessPolicy(ctx, accountID, applicationID, policyID, AccountRouteRoot) + return accessPolicies, &r.ResultInfo, nil } -// ZoneLevelAccessPolicy returns a single zone level policy based on the policy ID. +// GetAccessPolicy returns a single policy based on the policy ID. // -// API reference: https://api.cloudflare.com/#zone-level-access-policy-access-policy-details -func (api *API) ZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID, policyID string) (AccessPolicy, error) { - return api.accessPolicy(ctx, zoneID, applicationID, policyID, ZoneRouteRoot) -} - -func (api *API) accessPolicy(ctx context.Context, id string, applicationID string, policyID string, routeRoot RouteRoot) (AccessPolicy, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-get-an-access-policy +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-get-an-access-policy +func (api *API) GetAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, policyID string) (AccessPolicy, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, policyID, ) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return AccessPolicy{}, err + return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessPolicyDetailResponse AccessPolicyDetailResponse @@ -138,29 +142,19 @@ func (api *API) accessPolicy(ctx context.Context, id string, applicationID strin // CreateAccessPolicy creates a new access policy. // -// API reference: https://api.cloudflare.com/#access-policy-create-access-policy -func (api *API) CreateAccessPolicy(ctx context.Context, accountID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { - return api.createAccessPolicy(ctx, accountID, applicationID, accessPolicy, AccountRouteRoot) -} - -// CreateZoneLevelAccessPolicy creates a new zone level access policy. -// -// API reference: https://api.cloudflare.com/#zone-level-access-policy-create-access-policy -func (api *API) CreateZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { - return api.createAccessPolicy(ctx, zoneID, applicationID, accessPolicy, ZoneRouteRoot) -} - -func (api *API) createAccessPolicy(ctx context.Context, id, applicationID string, accessPolicy AccessPolicy, routeRoot RouteRoot) (AccessPolicy, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-create-an-access-policy +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-create-an-access-policy +func (api *API) CreateAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, ) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessPolicy) if err != nil { - return AccessPolicy{}, err + return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessPolicyDetailResponse AccessPolicyDetailResponse @@ -174,33 +168,23 @@ func (api *API) createAccessPolicy(ctx context.Context, id, applicationID string // UpdateAccessPolicy updates an existing access policy. // -// API reference: https://api.cloudflare.com/#access-policy-update-access-policy -func (api *API) UpdateAccessPolicy(ctx context.Context, accountID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { - return api.updateAccessPolicy(ctx, accountID, applicationID, accessPolicy, AccountRouteRoot) -} - -// UpdateZoneLevelAccessPolicy updates an existing zone level access policy. -// -// API reference: https://api.cloudflare.com/#zone-level-access-policy-update-access-policy -func (api *API) UpdateZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { - return api.updateAccessPolicy(ctx, zoneID, applicationID, accessPolicy, ZoneRouteRoot) -} - -func (api *API) updateAccessPolicy(ctx context.Context, id, applicationID string, accessPolicy AccessPolicy, routeRoot RouteRoot) (AccessPolicy, error) { +// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-update-an-access-policy +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-update-an-access-policy +func (api *API) UpdateAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { if accessPolicy.ID == "" { return AccessPolicy{}, fmt.Errorf("access policy ID cannot be empty") } uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, accessPolicy.ID, ) res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessPolicy) if err != nil { - return AccessPolicy{}, err + return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessPolicyDetailResponse AccessPolicyDetailResponse @@ -214,30 +198,20 @@ func (api *API) updateAccessPolicy(ctx context.Context, id, applicationID string // DeleteAccessPolicy deletes an access policy. // -// API reference: https://api.cloudflare.com/#access-policy-update-access-policy -func (api *API) DeleteAccessPolicy(ctx context.Context, accountID, applicationID, accessPolicyID string) error { - return api.deleteAccessPolicy(ctx, accountID, applicationID, accessPolicyID, AccountRouteRoot) -} - -// DeleteZoneLevelAccessPolicy deletes a zone level access policy. -// -// API reference: https://api.cloudflare.com/#zone-level-access-policy-delete-access-policy -func (api *API) DeleteZoneLevelAccessPolicy(ctx context.Context, zoneID, applicationID, accessPolicyID string) error { - return api.deleteAccessPolicy(ctx, zoneID, applicationID, accessPolicyID, ZoneRouteRoot) -} - -func (api *API) deleteAccessPolicy(ctx context.Context, id, applicationID, accessPolicyID string, routeRoot RouteRoot) error { +// Account API reference: https://developers.cloudflare.com/api/operations/access-policies-delete-an-access-policy +// Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-delete-an-access-policy +func (api *API) DeleteAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID, accessPolicyID string) error { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, applicationID, accessPolicyID, ) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return err + return fmt.Errorf("%s: %w", errMakeRequestError, err) } return nil diff --git a/access_policy_test.go b/access_policy_test.go index 1164b29d44a..4df981eac39 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -125,7 +125,7 @@ func TestAccessPolicies(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, _, err := client.AccessPolicies(context.Background(), testAccountID, accessApplicationID, pageOptions) + actual, _, err := client.ListAccessPolicies(context.Background(), testAccountRC, accessApplicationID, pageOptions) if assert.NoError(t, err) { assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual) @@ -133,7 +133,7 @@ func TestAccessPolicies(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, _, err = client.ZoneLevelAccessPolicies(context.Background(), testZoneID, accessApplicationID, pageOptions) + actual, _, err = client.ListAccessPolicies(context.Background(), testZoneRC, accessApplicationID, pageOptions) if assert.NoError(t, err) { assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual) @@ -200,7 +200,7 @@ func TestAccessPolicy(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err := client.AccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicyID) + actual, err := client.GetAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicyID) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -208,7 +208,7 @@ func TestAccessPolicy(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err = client.ZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicyID) + actual, err = client.GetAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicyID) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -307,7 +307,7 @@ func TestCreateAccessPolicy(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, err := client.CreateAccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicy) + actual, err := client.CreateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -315,7 +315,7 @@ func TestCreateAccessPolicy(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, err = client.CreateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicy) + actual, err = client.CreateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -381,14 +381,14 @@ func TestUpdateAccessPolicy(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err := client.UpdateAccessPolicy(context.Background(), testAccountID, accessApplicationID, expectedAccessPolicy) + actual, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, expectedAccessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) } mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err = client.UpdateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, expectedAccessPolicy) + actual, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, expectedAccessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -399,10 +399,10 @@ func TestUpdateAccessPolicyWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessPolicy(context.Background(), testAccountID, accessApplicationID, AccessPolicy{}) + _, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, AccessPolicy{}) assert.EqualError(t, err, "access policy ID cannot be empty") - _, err = client.UpdateZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, AccessPolicy{}) + _, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, AccessPolicy{}) assert.EqualError(t, err, "access policy ID cannot be empty") } @@ -425,12 +425,12 @@ func TestDeleteAccessPolicy(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - err := client.DeleteAccessPolicy(context.Background(), testAccountID, accessApplicationID, accessPolicyID) + err := client.DeleteAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicyID) assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - err = client.DeleteZoneLevelAccessPolicy(context.Background(), testZoneID, accessApplicationID, accessPolicyID) + err = client.DeleteAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicyID) assert.NoError(t, err) } From 0e4478bcb2df8d369af14b1ef5f1806e5a7a8f1d Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 16:16:45 -0400 Subject: [PATCH 067/130] More err to errMakeRequest --- access_audit_log.go | 2 +- access_mutual_tls_certificates.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/access_audit_log.go b/access_audit_log.go index bb488f6348e..92eb22bd8a5 100644 --- a/access_audit_log.go +++ b/access_audit_log.go @@ -48,7 +48,7 @@ func (api *API) AccessAuditLogs(ctx context.Context, accountID string, opts Acce res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return []AccessAuditLogRecord{}, err + return []AccessAuditLogRecord{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessAuditLogListResponse AccessAuditLogListResponse diff --git a/access_mutual_tls_certificates.go b/access_mutual_tls_certificates.go index f3e8e13b1ea..8ba7a7535ed 100644 --- a/access_mutual_tls_certificates.go +++ b/access_mutual_tls_certificates.go @@ -69,7 +69,7 @@ func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *Resourc var r AccessMutualTLSCertificateListResponse for { - uri := buildURI(baseURL, pageOpts) + uri := buildURI(baseURL, resultInfo) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -104,7 +104,7 @@ func (api *API) GetAccessMutualTLSCertificate(ctx context.Context, rc *ResourceC res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return AccessMutualTLSCertificate{}, err + return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse @@ -130,7 +130,7 @@ func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *Resour res, err := api.makeRequestContext(ctx, http.MethodPost, uri, certificate) if err != nil { - return AccessMutualTLSCertificate{}, err + return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse @@ -157,7 +157,7 @@ func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, rc *Resour res, err := api.makeRequestContext(ctx, http.MethodPut, uri, certificate) if err != nil { - return AccessMutualTLSCertificate{}, err + return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse @@ -184,7 +184,7 @@ func (api *API) DeleteAccessMutualTLSCertificate(ctx context.Context, rc *Resour res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return err + return fmt.Errorf("%s: %w", errMakeRequestError, err) } var accessMutualTLSCertificateDetailResponse AccessMutualTLSCertificateDetailResponse From d5330fe7fcfc57f4216d777ac54c95a5fe85e644 Mon Sep 17 00:00:00 2001 From: Cyb3r-Jak3 Date: Sun, 25 Jun 2023 16:24:56 -0400 Subject: [PATCH 068/130] Merge access_identity_provider --- .changelog/1319.txt | 7 ++ access_identity_provider.go | 163 +++++++++++++------------------ access_identity_provider_test.go | 32 +++--- 3 files changed, 96 insertions(+), 106 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index beffa338d4a..18505d6d75c 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -19,6 +19,13 @@ access_group: Merge all account and zone level operations to use Resource Contai access_group: add support for auto pagination ``` +```release-note:breaking-change +access_identity_provider: Merge all account and zone level operations to use Resource Container +``` +```release-note:enhancement +access_identity_provider: add support for auto pagination +``` + ```release-note:breaking-change access_mutual_tls_certificates: Merge all account and zone level operations to use Resource Container ``` diff --git a/access_identity_provider.go b/access_identity_provider.go index 4d21ad38a5c..5d4f9736811 100644 --- a/access_identity_provider.go +++ b/access_identity_provider.go @@ -59,79 +59,85 @@ type AccessIdentityProviderScimConfiguration struct { // Access Identity Providers. type AccessIdentityProvidersListResponse struct { Response - Result []AccessIdentityProvider `json:"result"` + Result []AccessIdentityProvider `json:"result"` + ResultInfo `json:"result_info"` } -// AccessIdentityProviderListResponse is the API response for a single +// AccessIdentityProviderResponse is the API response for a single // Access Identity Provider. -type AccessIdentityProviderListResponse struct { +type AccessIdentityProviderResponse struct { Response Result AccessIdentityProvider `json:"result"` } -// AccessIdentityProviders returns all Access Identity Providers for an +// ListAccessIdentityProviders returns all Access Identity Providers for an // account. // -// API reference: https://api.cloudflare.com/#access-identity-providers-list-access-identity-providers -func (api *API) AccessIdentityProviders(ctx context.Context, accountID string) ([]AccessIdentityProvider, error) { - return api.accessIdentityProviders(ctx, accountID, AccountRouteRoot) -} - -// ZoneLevelAccessIdentityProviders returns all Access Identity Providers for an -// account. -// -// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-list-access-identity-providers -func (api *API) ZoneLevelAccessIdentityProviders(ctx context.Context, zoneID string) ([]AccessIdentityProvider, error) { - return api.accessIdentityProviders(ctx, zoneID, ZoneRouteRoot) -} +// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-list-access-identity-providers +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-list-access-identity-providers +func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessIdentityProvider, *ResultInfo, error) { + baseURL := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier) + + autoPaginate := true + if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + autoPaginate = false + } -func (api *API) accessIdentityProviders(ctx context.Context, id string, routeRoot RouteRoot) ([]AccessIdentityProvider, error) { - uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id) + if pageOpts.PerPage < 1 { + pageOpts.PerPage = 25 + } - res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) - if err != nil { - return []AccessIdentityProvider{}, err + if pageOpts.Page < 1 { + pageOpts.Page = 1 } - var accessIdentityProviderResponse AccessIdentityProvidersListResponse - err = json.Unmarshal(res, &accessIdentityProviderResponse) - if err != nil { - return []AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + resultInfo := ResultInfo{ + Page: pageOpts.Page, + PerPage: pageOpts.PerPage, } - return accessIdentityProviderResponse.Result, nil -} + var accessProviders []AccessIdentityProvider + var r AccessIdentityProvidersListResponse + + for { + uri := buildURI(baseURL, resultInfo) + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) + } + + err = json.Unmarshal(res, &r) + if err != nil { + return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + resultInfo = r.ResultInfo.Next() + if resultInfo.Done() || autoPaginate { + break + } + } -// AccessIdentityProviderDetails returns a single Access Identity -// Provider for an account. -// -// API reference: https://api.cloudflare.com/#access-identity-providers-access-identity-providers-details -func (api *API) AccessIdentityProviderDetails(ctx context.Context, accountID, identityProviderID string) (AccessIdentityProvider, error) { - return api.accessIdentityProviderDetails(ctx, accountID, identityProviderID, AccountRouteRoot) + return accessProviders, &r.ResultInfo, nil } -// ZoneLevelAccessIdentityProviderDetails returns a single zone level Access Identity +// GetAccessIdentityProvider returns a single Access Identity // Provider for an account. // -// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-access-identity-providers-details -func (api *API) ZoneLevelAccessIdentityProviderDetails(ctx context.Context, zoneID, identityProviderID string) (AccessIdentityProvider, error) { - return api.accessIdentityProviderDetails(ctx, zoneID, identityProviderID, ZoneRouteRoot) -} - -func (api *API) accessIdentityProviderDetails(ctx context.Context, id string, identityProviderID string, routeRoot RouteRoot) (AccessIdentityProvider, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-get-an-access-identity-provider +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-get-an-access-identity-provider +func (api *API) GetAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderID string) (AccessIdentityProvider, error) { uri := fmt.Sprintf( "/%s/%s/access/identity_providers/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, identityProviderID, ) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { - return AccessIdentityProvider{}, err + return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var accessIdentityProviderResponse AccessIdentityProviderListResponse + var accessIdentityProviderResponse AccessIdentityProviderResponse err = json.Unmarshal(res, &accessIdentityProviderResponse) if err != nil { return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -142,27 +148,17 @@ func (api *API) accessIdentityProviderDetails(ctx context.Context, id string, id // CreateAccessIdentityProvider creates a new Access Identity Provider. // -// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider -func (api *API) CreateAccessIdentityProvider(ctx context.Context, accountID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { - return api.createAccessIdentityProvider(ctx, accountID, identityProviderConfiguration, AccountRouteRoot) -} - -// CreateZoneLevelAccessIdentityProvider creates a new zone level Access Identity Provider. -// -// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-create-access-identity-provider -func (api *API) CreateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { - return api.createAccessIdentityProvider(ctx, zoneID, identityProviderConfiguration, ZoneRouteRoot) -} - -func (api *API) createAccessIdentityProvider(ctx context.Context, id string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) { - uri := fmt.Sprintf("/%s/%s/access/identity_providers", routeRoot, id) +// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-add-an-access-identity-provider +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-add-an-access-identity-provider +func (api *API) CreateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { + uri := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, identityProviderConfiguration) if err != nil { - return AccessIdentityProvider{}, err + return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var accessIdentityProviderResponse AccessIdentityProviderListResponse + var accessIdentityProviderResponse AccessIdentityProviderResponse err = json.Unmarshal(res, &accessIdentityProviderResponse) if err != nil { return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -174,24 +170,13 @@ func (api *API) createAccessIdentityProvider(ctx context.Context, id string, ide // UpdateAccessIdentityProvider updates an existing Access Identity // Provider. // -// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider -func (api *API) UpdateAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { - return api.updateAccessIdentityProvider(ctx, accountID, identityProviderUUID, identityProviderConfiguration, AccountRouteRoot) -} - -// UpdateZoneLevelAccessIdentityProvider updates an existing zone level Access Identity -// Provider. -// -// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-update-access-identity-provider -func (api *API) UpdateZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { - return api.updateAccessIdentityProvider(ctx, zoneID, identityProviderUUID, identityProviderConfiguration, ZoneRouteRoot) -} - -func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider, routeRoot RouteRoot) (AccessIdentityProvider, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-update-an-access-identity-provider +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-update-an-access-identity-provider +func (api *API) UpdateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { uri := fmt.Sprintf( "/%s/%s/access/identity_providers/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, identityProviderUUID, ) @@ -200,7 +185,7 @@ func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, ide return AccessIdentityProvider{}, err } - var accessIdentityProviderResponse AccessIdentityProviderListResponse + var accessIdentityProviderResponse AccessIdentityProviderResponse err = json.Unmarshal(res, &accessIdentityProviderResponse) if err != nil { return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err) @@ -211,32 +196,22 @@ func (api *API) updateAccessIdentityProvider(ctx context.Context, id string, ide // DeleteAccessIdentityProvider deletes an Access Identity Provider. // -// API reference: https://api.cloudflare.com/#access-identity-providers-create-access-identity-provider -func (api *API) DeleteAccessIdentityProvider(ctx context.Context, accountID, identityProviderUUID string) (AccessIdentityProvider, error) { - return api.deleteAccessIdentityProvider(ctx, accountID, identityProviderUUID, AccountRouteRoot) -} - -// DeleteZoneLevelAccessIdentityProvider deletes a zone level Access Identity Provider. -// -// API reference: https://api.cloudflare.com/#zone-level-access-identity-providers-delete-access-identity-provider -func (api *API) DeleteZoneLevelAccessIdentityProvider(ctx context.Context, zoneID, identityProviderUUID string) (AccessIdentityProvider, error) { - return api.deleteAccessIdentityProvider(ctx, zoneID, identityProviderUUID, ZoneRouteRoot) -} - -func (api *API) deleteAccessIdentityProvider(ctx context.Context, id string, identityProviderUUID string, routeRoot RouteRoot) (AccessIdentityProvider, error) { +// Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-delete-an-access-identity-provider +// Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-delete-an-access-identity-provider +func (api *API) DeleteAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderUUID string) (AccessIdentityProvider, error) { uri := fmt.Sprintf( "/%s/%s/access/identity_providers/%s", - routeRoot, - id, + rc.Level, + rc.Identifier, identityProviderUUID, ) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { - return AccessIdentityProvider{}, err + return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } - var accessIdentityProviderResponse AccessIdentityProviderListResponse + var accessIdentityProviderResponse AccessIdentityProviderResponse err = json.Unmarshal(res, &accessIdentityProviderResponse) if err != nil { return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errUnmarshalError, err) diff --git a/access_identity_provider_test.go b/access_identity_provider_test.go index 3b69798ab9e..e65ff4ac38e 100644 --- a/access_identity_provider_test.go +++ b/access_identity_provider_test.go @@ -9,12 +9,14 @@ import ( "github.com/stretchr/testify/assert" ) -func TestAccessIdentityProviders(t *testing.T) { +func TestListAccessIdentityProviders(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) + assert.Equal(t, "1", r.URL.Query().Get("page")) + assert.Equal(t, "25", r.URL.Query().Get("per_page")) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, `{ "success": true, @@ -30,7 +32,13 @@ func TestAccessIdentityProviders(t *testing.T) { "client_secret": "a-secret-key" } } - ] + ], + "result_info": { + "count": 1, + "page": 1, + "per_page": 20, + "total_count": 1 + } } `) } @@ -49,7 +57,7 @@ func TestAccessIdentityProviders(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler) - actual, err := client.AccessIdentityProviders(context.Background(), testAccountID) + actual, _, err := client.ListAccessIdentityProviders(context.Background(), testAccountRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -57,7 +65,7 @@ func TestAccessIdentityProviders(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler) - actual, err = client.ZoneLevelAccessIdentityProviders(context.Background(), testZoneID) + actual, _, err = client.ListAccessIdentityProviders(context.Background(), testZoneRC, PaginationOptions{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -100,7 +108,7 @@ func TestAccessIdentityProviderDetails(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc841", handler) - actual, err := client.AccessIdentityProviderDetails(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc841") + actual, err := client.GetAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc841") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -108,7 +116,7 @@ func TestAccessIdentityProviderDetails(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc841", handler) - actual, err = client.ZoneLevelAccessIdentityProviderDetails(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc841") + actual, err = client.GetAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc841") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -160,7 +168,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler) - actual, err := client.CreateAccessIdentityProvider(context.Background(), testAccountID, newIdentityProvider) + actual, err := client.CreateAccessIdentityProvider(context.Background(), testAccountRC, newIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -168,7 +176,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler) - actual, err = client.CreateZoneLevelAccessIdentityProvider(context.Background(), testZoneID, newIdentityProvider) + actual, err = client.CreateAccessIdentityProvider(context.Background(), testZoneRC, newIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -219,7 +227,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) + actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -227,7 +235,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateZoneLevelAccessIdentityProvider(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) + actual, err = client.UpdateAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -270,7 +278,7 @@ func TestDeleteAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.DeleteAccessIdentityProvider(context.Background(), "01a7362d577a6c3019a474fd6f485823", "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.DeleteAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -278,7 +286,7 @@ func TestDeleteAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.DeleteZoneLevelAccessIdentityProvider(context.Background(), testZoneID, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.DeleteAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") if assert.NoError(t, err) { assert.Equal(t, want, actual) From 1178070be4e9b23aa1f9ce36352b20d6f30e9911 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 10:20:11 +1000 Subject: [PATCH 069/130] update changelog entry --- .changelog/1319.txt | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/.changelog/1319.txt b/.changelog/1319.txt index 18505d6d75c..be082a58648 100644 --- a/.changelog/1319.txt +++ b/.changelog/1319.txt @@ -1,52 +1,59 @@ ```release-note:breaking-change -access_application: Merge all account and zone level operations to use Resource Container +access_application: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_application: add support for auto pagination ``` ```release-note:breaking-change -access_ca_certificate: Merge all account and zone level operations to use Resource Container +access_ca_certificate: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_ca_certificate: add support for auto pagination ``` ```release-note:breaking-change -access_group: Merge all account and zone level operations to use Resource Container +access_group: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_group: add support for auto pagination ``` ```release-note:breaking-change -access_identity_provider: Merge all account and zone level operations to use Resource Container +access_identity_provider: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_identity_provider: add support for auto pagination ``` ```release-note:breaking-change -access_mutual_tls_certificates: Merge all account and zone level operations to use Resource Container +access_mutual_tls_certificates: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_mutual_tls_certificates: add support for auto pagination ``` ```release-note:breaking-change -access_organization: Merge all account and zone level operations to use Resource Container +access_organization: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` ```release-note:breaking-change -access_policy: Merge all account and zone level operations to use Resource Container +access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:enhancement access_policy: add support for auto pagination ``` ```release-note:breaking-change -access_service_tokens: Merge all account and zone level operations to use Resource Container +access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ``` + ```release-note:breaking-change -access_user_token: Merge all account and zone level operations to use Resource Container -``` \ No newline at end of file +access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods +``` From 554d7cab57f45a03f55387dd4798288523bc1975 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 10:27:01 +1000 Subject: [PATCH 070/130] refactor method signatures to use dedicated parameters --- access_application.go | 86 +++++++++++++++++++++++++++++++------- access_application_test.go | 24 +++++------ cloudflare_test.go | 2 +- 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/access_application.go b/access_application.go index 65421f2e267..090dec96c72 100644 --- a/access_application.go +++ b/access_application.go @@ -112,29 +112,84 @@ type SaasApplication struct { CustomAttributes []SAMLAttributeConfig `json:"custom_attributes,omitempty"` } +type ListAccessApplicationsParams struct { + PaginationOptions +} + +type CreateAccessApplicationParams struct { + AllowedIdps []string `json:"allowed_idps,omitempty"` + AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` + AUD string `json:"aud,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` + CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` + CustomDenyMessage string `json:"custom_deny_message,omitempty"` + CustomDenyURL string `json:"custom_deny_url,omitempty"` + Domain string `json:"domain"` + EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` + GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + Name string `json:"name"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` + PrivateAddress string `json:"private_address"` + SaasApplication *SaasApplication `json:"saas_app,omitempty"` + SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` + SelfHostedDomains []string `json:"self_hosted_domains"` + ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + SessionDuration string `json:"session_duration,omitempty"` + SkipInterstitial *bool `json:"skip_interstitial,omitempty"` + Type AccessApplicationType `json:"type,omitempty"` +} + +type UpdateAccessApplicationParams struct { + ID string `json:"id,omitempty"` + AllowedIdps []string `json:"allowed_idps,omitempty"` + AppLauncherVisible *bool `json:"app_launcher_visible,omitempty"` + AUD string `json:"aud,omitempty"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` + CorsHeaders *AccessApplicationCorsHeaders `json:"cors_headers,omitempty"` + CustomDenyMessage string `json:"custom_deny_message,omitempty"` + CustomDenyURL string `json:"custom_deny_url,omitempty"` + Domain string `json:"domain"` + EnableBindingCookie *bool `json:"enable_binding_cookie,omitempty"` + GatewayRules []AccessApplicationGatewayRule `json:"gateway_rules,omitempty"` + HttpOnlyCookieAttribute *bool `json:"http_only_cookie_attribute,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + Name string `json:"name"` + PathCookieAttribute *bool `json:"path_cookie_attribute,omitempty"` + PrivateAddress string `json:"private_address"` + SaasApplication *SaasApplication `json:"saas_app,omitempty"` + SameSiteCookieAttribute string `json:"same_site_cookie_attribute,omitempty"` + SelfHostedDomains []string `json:"self_hosted_domains"` + ServiceAuth401Redirect *bool `json:"service_auth_401_redirect,omitempty"` + SessionDuration string `json:"session_duration,omitempty"` + SkipInterstitial *bool `json:"skip_interstitial,omitempty"` + Type AccessApplicationType `json:"type,omitempty"` +} + // ListAccessApplications returns all applications within an account or zone. // // Account API reference: https://developers.cloudflare.com/api/operations/access-applications-list-access-applications // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-list-access-applications -func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessApplication, *ResultInfo, error) { +func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContainer, params ListAccessApplicationsParams) ([]AccessApplication, *ResultInfo, error) { baseURL := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 + if params.Page < 1 { + params.Page = 1 } resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + Page: params.Page, + PerPage: params.PerPage, } var applications []AccessApplication @@ -161,7 +216,8 @@ func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContaine return applications, &r.ResultInfo, nil } -// GetAccessApplication returns a single application based on the application ID for either account or zone. +// GetAccessApplication returns a single application based on the application +// ID for either account or zone. // // Account API reference: https://developers.cloudflare.com/api/operations/access-applications-get-an-access-application // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-get-an-access-application @@ -191,10 +247,10 @@ func (api *API) GetAccessApplication(ctx context.Context, rc *ResourceContainer, // // Account API reference: https://developers.cloudflare.com/api/operations/access-applications-add-an-application // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-add-a-bookmark-application -func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContainer, accessApplication AccessApplication) (AccessApplication, error) { +func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContainer, params CreateAccessApplicationParams) (AccessApplication, error) { uri := fmt.Sprintf("/%s/%s/access/apps", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessApplication) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -212,8 +268,8 @@ func (api *API) CreateAccessApplication(ctx context.Context, rc *ResourceContain // // Account API reference: https://developers.cloudflare.com/api/operations/access-applications-update-a-bookmark-application // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-applications-update-a-bookmark-application -func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContainer, accessApplication AccessApplication) (AccessApplication, error) { - if accessApplication.ID == "" { +func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContainer, params UpdateAccessApplicationParams) (AccessApplication, error) { + if params.ID == "" { return AccessApplication{}, fmt.Errorf("access application ID cannot be empty") } @@ -221,10 +277,10 @@ func (api *API) UpdateAccessApplication(ctx context.Context, rc *ResourceContain "/%s/%s/access/apps/%s", rc.Level, rc.Identifier, - accessApplication.ID, + params.ID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessApplication) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessApplication{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } diff --git a/access_application_test.go b/access_application_test.go index 8b605a36012..5baba05e943 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -87,7 +87,7 @@ func TestAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, _, err := client.ListAccessApplications(context.Background(), AccountIdentifier(testAccountID), PaginationOptions{}) + actual, _, err := client.ListAccessApplications(context.Background(), AccountIdentifier(testAccountID), ListAccessApplicationsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -95,7 +95,7 @@ func TestAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, _, err = client.ListAccessApplications(context.Background(), ZoneIdentifier(testZoneID), PaginationOptions{}) + actual, _, err = client.ListAccessApplications(context.Background(), ZoneIdentifier(testZoneID), ListAccessApplicationsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -242,7 +242,7 @@ func TestCreateAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", @@ -254,7 +254,7 @@ func TestCreateAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), AccessApplication{ + actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), CreateAccessApplicationParams{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", @@ -300,9 +300,7 @@ func TestUpdateAccessApplication(t *testing.T) { `) } - createdAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - fullAccessApplication := AccessApplication{ + fullAccessApplication := UpdateAccessApplicationParams{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", Name: "Admin Site", Domain: "test.example.com/admin", @@ -319,8 +317,6 @@ func TestUpdateAccessApplication(t *testing.T) { CustomDenyURL: "https://www.example.com", LogoURL: "https://www.example.com/example.png", SkipInterstitial: BoolPtr(true), - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) @@ -344,10 +340,10 @@ func TestUpdateAccessApplicationWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{}) + _, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), UpdateAccessApplicationParams{}) assert.EqualError(t, err, "access application ID cannot be empty") - _, err = client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{}) + _, err = client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), UpdateAccessApplicationParams{}) assert.EqualError(t, err, "access application ID cannot be empty") } @@ -546,7 +542,7 @@ func TestCreatePrivateAccessApplication(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "Admin Site", PrivateAddress: "198.51.100.0", SessionDuration: "24h", @@ -672,7 +668,7 @@ func TestCreateSaasAccessApplications(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps", handler) - actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), AccessApplication{ + actual, err := client.CreateAccessApplication(context.Background(), AccountIdentifier(testAccountID), CreateAccessApplicationParams{ Name: "Admin Saas Site", SaasApplication: &SaasApplication{ ConsumerServiceUrl: "https://examplesaas.com", @@ -688,7 +684,7 @@ func TestCreateSaasAccessApplications(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps", handler) - actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), AccessApplication{ + actual, err = client.CreateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), CreateAccessApplicationParams{ Name: "Admin Saas Site", SaasApplication: &SaasApplication{ ConsumerServiceUrl: "https://saas.example.com", diff --git a/cloudflare_test.go b/cloudflare_test.go index 659312f4da3..e333d60895a 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -481,7 +481,7 @@ func TestErrorFromResponseWithUnmarshalingError(t *testing.T) { mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/access/apps", handler) - _, err := client.CreateAccessApplication(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), AccessApplication{ + _, err := client.CreateAccessApplication(context.Background(), AccountIdentifier("01a7362d577a6c3019a474fd6f485823"), CreateAccessApplicationParams{ Name: "Admin Site", Domain: "test.example.com/admin", SessionDuration: "24h", From 2b0872854c152a2e3441902c62bc2ced9f2b69ec Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 10:31:12 +1000 Subject: [PATCH 071/130] fix lint --- access_application_test.go | 44 +++++++++++++++++++++++++++++++++++--- cloudflare_test.go | 4 ++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/access_application_test.go b/access_application_test.go index 5baba05e943..3c07a544334 100644 --- a/access_application_test.go +++ b/access_application_test.go @@ -300,7 +300,28 @@ func TestUpdateAccessApplication(t *testing.T) { `) } - fullAccessApplication := UpdateAccessApplicationParams{ + fullAccessApplication := AccessApplication{ + ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + Name: "Admin Site", + Domain: "test.example.com/admin", + SelfHostedDomains: []string{"test.example.com/admin", "test.example.com/admin2"}, + Type: "self_hosted", + SessionDuration: "24h", + AUD: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + AllowedIdps: []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}, + AutoRedirectToIdentity: BoolPtr(false), + EnableBindingCookie: BoolPtr(false), + AppLauncherVisible: BoolPtr(true), + ServiceAuth401Redirect: BoolPtr(true), + CustomDenyMessage: "denied!", + CustomDenyURL: "https://www.example.com", + LogoURL: "https://www.example.com/example.png", + SkipInterstitial: BoolPtr(true), + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + } + + params := UpdateAccessApplicationParams{ ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", Name: "Admin Site", Domain: "test.example.com/admin", @@ -321,7 +342,7 @@ func TestUpdateAccessApplication(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), fullAccessApplication) + actual, err := client.UpdateAccessApplication(context.Background(), AccountIdentifier(testAccountID), params) if assert.NoError(t, err) { assert.Equal(t, fullAccessApplication, actual) @@ -329,7 +350,24 @@ func TestUpdateAccessApplication(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) - actual, err = client.UpdateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), fullAccessApplication) + actual, err = client.UpdateAccessApplication(context.Background(), ZoneIdentifier(testZoneID), UpdateAccessApplicationParams{ + ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + Name: "Admin Site", + Domain: "test.example.com/admin", + SelfHostedDomains: []string{"test.example.com/admin", "test.example.com/admin2"}, + Type: "self_hosted", + SessionDuration: "24h", + AUD: "737646a56ab1df6ec9bddc7e5ca84eaf3b0768850f3ffb5d74f1534911fe3893", + AllowedIdps: []string{"f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}, + AutoRedirectToIdentity: BoolPtr(false), + EnableBindingCookie: BoolPtr(false), + AppLauncherVisible: BoolPtr(true), + ServiceAuth401Redirect: BoolPtr(true), + CustomDenyMessage: "denied!", + CustomDenyURL: "https://www.example.com", + LogoURL: "https://www.example.com/example.png", + SkipInterstitial: BoolPtr(true), + }) if assert.NoError(t, err) { assert.Equal(t, fullAccessApplication, actual) diff --git a/cloudflare_test.go b/cloudflare_test.go index e333d60895a..03654047c61 100644 --- a/cloudflare_test.go +++ b/cloudflare_test.go @@ -22,10 +22,10 @@ var ( // server is a test HTTP server used to provide mock API responses. server *httptest.Server - // testAccountRC is a test account resource container + // testAccountRC is a test account resource container. testAccountRC = AccountIdentifier(testAccountID) - // testZoneRC is a test zone resource container + // testZoneRC is a test zone resource container. testZoneRC = ZoneIdentifier(testZoneID) ) From a570d2768cfbba229028d9888707fa4d65164093 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 10:48:33 +1000 Subject: [PATCH 072/130] update method conventions to match the experimental client --- access_ca_certificate.go | 31 ++++++++++++++++++++----------- access_ca_certificate_test.go | 8 ++++---- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/access_ca_certificate.go b/access_ca_certificate.go index 5ca92b4a994..1bfe94f4d97 100644 --- a/access_ca_certificate.go +++ b/access_ca_certificate.go @@ -30,29 +30,37 @@ type AccessCACertificateResponse struct { Result AccessCACertificate `json:"result"` } +type ListAccessCACertificatesParams struct { + PaginationOptions +} + +type CreateAccessCACertificateParams struct { + ApplicationID string +} + // ListAccessCACertificates returns all AccessCACertificate within Access. // // Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-list-short-lived-certificate-c-as // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-list-short-lived-certificate-c-as -func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessCACertificate, *ResultInfo, error) { +func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContainer, params ListAccessCACertificatesParams) ([]AccessCACertificate, *ResultInfo, error) { baseURL := fmt.Sprintf("/%s/%s/access/apps/ca", rc.Level, rc.Identifier) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 + if params.Page < 1 { + params.Page = 1 } resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + Page: params.Page, + PerPage: params.PerPage, } var accessCACertificates []AccessCACertificate @@ -79,7 +87,8 @@ func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContai return accessCACertificates, &resultInfo, nil } -// GetAccessCACertificate returns a single CA certificate associated within Access. +// GetAccessCACertificate returns a single CA certificate associated within +// Access. // // Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-get-a-short-lived-certificate-ca @@ -104,12 +113,12 @@ func (api *API) GetAccessCACertificate(ctx context.Context, rc *ResourceContaine // // Account API reference: https://developers.cloudflare.com/api/operations/access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-short-lived-certificate-c-as-create-a-short-lived-certificate-ca -func (api *API) CreateAccessCACertificate(ctx context.Context, rc *ResourceContainer, applicationID string) (AccessCACertificate, error) { +func (api *API) CreateAccessCACertificate(ctx context.Context, rc *ResourceContainer, params CreateAccessCACertificateParams) (AccessCACertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/ca", rc.Level, rc.Identifier, - applicationID, + params.ApplicationID, ) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, nil) diff --git a/access_ca_certificate_test.go b/access_ca_certificate_test.go index a46b264209f..bb75b90a107 100644 --- a/access_ca_certificate_test.go +++ b/access_ca_certificate_test.go @@ -80,7 +80,7 @@ func TestAccessCACertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/ca", handler) - actual, _, err := client.ListAccessCACertificates(context.Background(), testAccountRC, PaginationOptions{}) + actual, _, err := client.ListAccessCACertificates(context.Background(), testAccountRC, ListAccessCACertificatesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -88,7 +88,7 @@ func TestAccessCACertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/ca", handler) - actual, _, err = client.ListAccessCACertificates(context.Background(), testZoneRC, PaginationOptions{}) + actual, _, err = client.ListAccessCACertificates(context.Background(), testZoneRC, ListAccessCACertificatesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -123,7 +123,7 @@ func TestCreateAccessCACertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - actual, err := client.CreateAccessCACertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err := client.CreateAccessCACertificate(context.Background(), testAccountRC, CreateAccessCACertificateParams{ApplicationID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -131,7 +131,7 @@ func TestCreateAccessCACertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/f174e90a-fafe-4643-bbbc-4a0ed4fc8415/ca", handler) - actual, err = client.CreateAccessCACertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415") + actual, err = client.CreateAccessCACertificate(context.Background(), testZoneRC, CreateAccessCACertificateParams{ApplicationID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) From e4ea23c7d184e03c0e98b1d47b039840cd471dd2 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 10:55:54 +1000 Subject: [PATCH 073/130] use *Params conventions for method signatures --- access_group.go | 69 ++++++++++++++++++++++++++++++++++---------- access_group_test.go | 33 ++++++++++++++------- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/access_group.go b/access_group.go index 26d3437bdc8..c04d9f3c940 100644 --- a/access_group.go +++ b/access_group.go @@ -203,29 +203,66 @@ type AccessGroupDetailResponse struct { Result AccessGroup `json:"result"` } +type ListAccessGroupsParams struct { + PaginationOptions +} + +type CreateAccessGroupParams struct { + Name string `json:"name"` + + // The include group works like an OR logical operator. The user must + // satisfy one of the rules. + Include []interface{} `json:"include"` + + // The exclude group works like a NOT logical operator. The user must + // not satisfy all the rules in exclude. + Exclude []interface{} `json:"exclude"` + + // The require group works like a AND logical operator. The user must + // satisfy all the rules in require. + Require []interface{} `json:"require"` +} + +type UpdateAccessGroupParams struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` + + // The include group works like an OR logical operator. The user must + // satisfy one of the rules. + Include []interface{} `json:"include"` + + // The exclude group works like a NOT logical operator. The user must + // not satisfy all the rules in exclude. + Exclude []interface{} `json:"exclude"` + + // The require group works like a AND logical operator. The user must + // satisfy all the rules in require. + Require []interface{} `json:"require"` +} + // ListAccessGroups returns all access groups for an access application. // // Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-list-access-groups // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-list-access-groups -func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessGroup, *ResultInfo, error) { +func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, params ListAccessGroupsParams) ([]AccessGroup, *ResultInfo, error) { baseURL := fmt.Sprintf("/%s/%s/access/groups", rc.Level, rc.Identifier) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 + if params.Page < 1 { + params.Page = 1 } resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + Page: params.Page, + PerPage: params.PerPage, } var accessGroups []AccessGroup @@ -278,18 +315,18 @@ func (api *API) GetAccessGroup(ctx context.Context, rc *ResourceContainer, group return accessGroupDetailResponse.Result, nil } -// CreateAccessGroup creates a new access group +// CreateAccessGroup creates a new access group. // // Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-create-an-access-group // Zone API Reference:https://developers.cloudflare.com/api/operations/zone-level-access-groups-create-an-access-group -func (api *API) CreateAccessGroup(ctx context.Context, rc *ResourceContainer, accessGroup AccessGroup) (AccessGroup, error) { +func (api *API) CreateAccessGroup(ctx context.Context, rc *ResourceContainer, params CreateAccessGroupParams) (AccessGroup, error) { uri := fmt.Sprintf( "/%s/%s/access/groups", rc.Level, rc.Identifier, ) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessGroup) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessGroup{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -303,12 +340,12 @@ func (api *API) CreateAccessGroup(ctx context.Context, rc *ResourceContainer, ac return accessGroupDetailResponse.Result, nil } -// UpdateAccessGroup updates an existing access group +// UpdateAccessGroup updates an existing access group. // // Account API Reference: https://developers.cloudflare.com/api/operations/access-groups-update-an-access-group // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-groups-update-an-access-group -func (api *API) UpdateAccessGroup(ctx context.Context, rc *ResourceContainer, accessGroup AccessGroup) (AccessGroup, error) { - if accessGroup.ID == "" { +func (api *API) UpdateAccessGroup(ctx context.Context, rc *ResourceContainer, params UpdateAccessGroupParams) (AccessGroup, error) { + if params.ID == "" { return AccessGroup{}, fmt.Errorf("access group ID cannot be empty") } @@ -316,10 +353,10 @@ func (api *API) UpdateAccessGroup(ctx context.Context, rc *ResourceContainer, ac "/%s/%s/access/groups/%s", rc.Level, rc.Identifier, - accessGroup.ID, + params.ID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessGroup) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessGroup{}, err } diff --git a/access_group_test.go b/access_group_test.go index 4f961690cef..1766beffd79 100644 --- a/access_group_test.go +++ b/access_group_test.go @@ -91,7 +91,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler) - actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, pageOptions) + actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, ListAccessGroupsParams{PaginationOptions{}}) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) @@ -99,7 +99,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, pageOptions) + actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, ListAccessGroupsParams{PaginationOptions{}}) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) @@ -209,7 +209,7 @@ func TestCreateAccessGroup(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler) - accessGroup := AccessGroup{ + params := CreateAccessGroupParams{ Name: "Allow devs", Include: []interface{}{ AccessGroupEmail{struct { @@ -228,7 +228,7 @@ func TestCreateAccessGroup(t *testing.T) { }, } - actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, accessGroup) + actual, err := client.CreateAccessGroup(context.Background(), testAccountRC, params) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -236,7 +236,7 @@ func TestCreateAccessGroup(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, accessGroup) + actual, err = client.CreateAccessGroup(context.Background(), testZoneRC, params) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -285,15 +285,28 @@ func TestUpdateAccessGroup(t *testing.T) { `) } + params := UpdateAccessGroupParams{ + ID: "699d98642c564d2e855e9661899b7252", + Name: "Allow devs", + Include: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + Exclude: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + Require: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + } mux.HandleFunc("/accounts/"+testAccountID+"/access/groups/"+accessGroupID, handler) - actual, err := client.UpdateAccessGroup(context.Background(), testAccountRC, expectedAccessGroup) + actual, err := client.UpdateAccessGroup(context.Background(), testAccountRC, params) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) } mux.HandleFunc("/zones/"+testZoneID+"/access/groups/"+accessGroupID, handler) - actual, err = client.UpdateAccessGroup(context.Background(), testZoneRC, expectedAccessGroup) + actual, err = client.UpdateAccessGroup(context.Background(), testZoneRC, params) if assert.NoError(t, err) { assert.Equal(t, expectedAccessGroup, actual) @@ -304,10 +317,10 @@ func TestUpdateAccessGroupWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessGroup(context.Background(), testAccountRC, AccessGroup{}) + _, err := client.UpdateAccessGroup(context.Background(), testAccountRC, UpdateAccessGroupParams{}) assert.EqualError(t, err, "access group ID cannot be empty") - _, err = client.UpdateAccessGroup(context.Background(), testZoneRC, AccessGroup{}) + _, err = client.UpdateAccessGroup(context.Background(), testZoneRC, UpdateAccessGroupParams{}) assert.EqualError(t, err, "access group ID cannot be empty") } @@ -370,7 +383,7 @@ func TestCreateIPListAccessGroup(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler) - accessGroup := AccessGroup{ + accessGroup := CreateAccessGroupParams{ Name: "Allow devs by iplist", Include: []interface{}{ AccessGroupIPList{struct { From a8d70d72ff6551fbdb8ea44c3cbe3a451a86270e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:11:36 +1000 Subject: [PATCH 074/130] access_identity_providers: use *Params conventions for method signatures --- access_identity_provider.go | 58 ++++++++++++++++++++------------ access_identity_provider_test.go | 13 +++---- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/access_identity_provider.go b/access_identity_provider.go index 5d4f9736811..c248bc8969c 100644 --- a/access_identity_provider.go +++ b/access_identity_provider.go @@ -70,37 +70,51 @@ type AccessIdentityProviderResponse struct { Result AccessIdentityProvider `json:"result"` } +type ListAccessIdentityProvidersParams struct { + ResultInfo +} + +type CreateAccessIdentityProviderParams struct { + Name string `json:"name"` + Type string `json:"type"` + Config AccessIdentityProviderConfiguration `json:"config"` + ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"` +} + +type UpdateAccessIdentityProviderParams struct { + ID string `json:"-"` + Name string `json:"name"` + Type string `json:"type"` + Config AccessIdentityProviderConfiguration `json:"config"` + ScimConfig AccessIdentityProviderScimConfiguration `json:"scim_config"` +} + // ListAccessIdentityProviders returns all Access Identity Providers for an -// account. +// account or zone. // // Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-list-access-identity-providers // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-list-access-identity-providers -func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessIdentityProvider, *ResultInfo, error) { +func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceContainer, params ListAccessIdentityProvidersParams) ([]AccessIdentityProvider, *ResultInfo, error) { baseURL := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 - } - - resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + if params.Page < 1 { + params.Page = 1 } var accessProviders []AccessIdentityProvider var r AccessIdentityProvidersListResponse for { - uri := buildURI(baseURL, resultInfo) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -110,8 +124,10 @@ func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceCon if err != nil { return []AccessIdentityProvider{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + + accessProviders = append(accessProviders, r.Result...) + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || !autoPaginate { break } } @@ -120,7 +136,7 @@ func (api *API) ListAccessIdentityProviders(ctx context.Context, rc *ResourceCon } // GetAccessIdentityProvider returns a single Access Identity -// Provider for an account. +// Provider for an account or zone. // // Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-get-an-access-identity-provider // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-get-an-access-identity-provider @@ -150,10 +166,10 @@ func (api *API) GetAccessIdentityProvider(ctx context.Context, rc *ResourceConta // // Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-add-an-access-identity-provider // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-add-an-access-identity-provider -func (api *API) CreateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { +func (api *API) CreateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, params CreateAccessIdentityProviderParams) (AccessIdentityProvider, error) { uri := fmt.Sprintf("/%s/%s/access/identity_providers", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, identityProviderConfiguration) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessIdentityProvider{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -172,15 +188,15 @@ func (api *API) CreateAccessIdentityProvider(ctx context.Context, rc *ResourceCo // // Account API Reference: https://developers.cloudflare.com/api/operations/access-identity-providers-update-an-access-identity-provider // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-identity-providers-update-an-access-identity-provider -func (api *API) UpdateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, identityProviderUUID string, identityProviderConfiguration AccessIdentityProvider) (AccessIdentityProvider, error) { +func (api *API) UpdateAccessIdentityProvider(ctx context.Context, rc *ResourceContainer, params UpdateAccessIdentityProviderParams) (AccessIdentityProvider, error) { uri := fmt.Sprintf( "/%s/%s/access/identity_providers/%s", rc.Level, rc.Identifier, - identityProviderUUID, + params.ID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, identityProviderConfiguration) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessIdentityProvider{}, err } diff --git a/access_identity_provider_test.go b/access_identity_provider_test.go index e65ff4ac38e..ad9b6935b9f 100644 --- a/access_identity_provider_test.go +++ b/access_identity_provider_test.go @@ -57,7 +57,7 @@ func TestListAccessIdentityProviders(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers", handler) - actual, _, err := client.ListAccessIdentityProviders(context.Background(), testAccountRC, PaginationOptions{}) + actual, _, err := client.ListAccessIdentityProviders(context.Background(), testAccountRC, ListAccessIdentityProvidersParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -65,7 +65,7 @@ func TestListAccessIdentityProviders(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers", handler) - actual, _, err = client.ListAccessIdentityProviders(context.Background(), testZoneRC, PaginationOptions{}) + actual, _, err = client.ListAccessIdentityProviders(context.Background(), testZoneRC, ListAccessIdentityProvidersParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -147,7 +147,7 @@ func TestCreateAccessIdentityProvider(t *testing.T) { `) } - newIdentityProvider := AccessIdentityProvider{ + newIdentityProvider := CreateAccessIdentityProviderParams{ Name: "Widget Corps OTP", Type: "github", Config: AccessIdentityProviderConfiguration{ @@ -206,7 +206,8 @@ func TestUpdateAccessIdentityProvider(t *testing.T) { `) } - updatedIdentityProvider := AccessIdentityProvider{ + updatedIdentityProvider := UpdateAccessIdentityProviderParams{ + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "Widget Corps OTP", Type: "github", Config: AccessIdentityProviderConfiguration{ @@ -227,7 +228,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) + actual, err := client.UpdateAccessIdentityProvider(context.Background(), testAccountRC, updatedIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -235,7 +236,7 @@ func TestUpdateAccessIdentityProvider(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/identity_providers/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateAccessIdentityProvider(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", updatedIdentityProvider) + actual, err = client.UpdateAccessIdentityProvider(context.Background(), testZoneRC, updatedIdentityProvider) if assert.NoError(t, err) { assert.Equal(t, want, actual) From ef07c722b806c60712d60754773f18bb57f05aeb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:16:00 +1000 Subject: [PATCH 075/130] access_mutual_tls_certificate: use *Params conventions for method signatures --- access_mutual_tls_certificates.go | 47 +++++++++++++++++++------- access_mutual_tls_certificates_test.go | 13 +++---- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/access_mutual_tls_certificates.go b/access_mutual_tls_certificates.go index 8ba7a7535ed..dd6a1c12060 100644 --- a/access_mutual_tls_certificates.go +++ b/access_mutual_tls_certificates.go @@ -36,11 +36,32 @@ type AccessMutualTLSCertificateDetailResponse struct { Result AccessMutualTLSCertificate `json:"result"` } +type ListAccessMutualTLSCertificatesParams struct { + ResultInfo +} + +type CreateAccessMutualTLSCertificateParams struct { + ExpiresOn time.Time `json:"expires_on,omitempty"` + Name string `json:"name,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + Certificate string `json:"certificate,omitempty"` + AssociatedHostnames []string `json:"associated_hostnames,omitempty"` +} + +type UpdateAccessMutualTLSCertificateParams struct { + ID string `json:"-"` + ExpiresOn time.Time `json:"expires_on,omitempty"` + Name string `json:"name,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + Certificate string `json:"certificate,omitempty"` + AssociatedHostnames []string `json:"associated_hostnames,omitempty"` +} + // ListAccessMutualTLSCertificates returns all Access TLS certificates // // Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-list-mtls-certificates // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-list-mtls-certificates -func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *ResourceContainer, pageOpts PaginationOptions) ([]AccessMutualTLSCertificate, *ResultInfo, error) { +func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *ResourceContainer, params ListAccessMutualTLSCertificatesParams) ([]AccessMutualTLSCertificate, *ResultInfo, error) { baseURL := fmt.Sprintf( "/%s/%s/access/certificates", rc.Level, @@ -48,21 +69,21 @@ func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *Resourc ) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 + if params.Page < 1 { + params.Page = 1 } resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + Page: params.Page, + PerPage: params.PerPage, } var accessCertificates []AccessMutualTLSCertificate @@ -121,14 +142,14 @@ func (api *API) GetAccessMutualTLSCertificate(ctx context.Context, rc *ResourceC // // Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-add-an-mtls-certificate // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-add-an-mtls-certificate -func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { +func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, params CreateAccessMutualTLSCertificateParams) (AccessMutualTLSCertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/certificates", rc.Level, rc.Identifier, ) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, certificate) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -147,15 +168,15 @@ func (api *API) CreateAccessMutualTLSCertificate(ctx context.Context, rc *Resour // // Account API Reference: https://developers.cloudflare.com/api/operations/access-mtls-authentication-update-an-mtls-certificate // Zone API Reference: https://developers.cloudflare.com/api/operations/zone-level-access-mtls-authentication-update-an-mtls-certificate -func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, certificateID string, certificate AccessMutualTLSCertificate) (AccessMutualTLSCertificate, error) { +func (api *API) UpdateAccessMutualTLSCertificate(ctx context.Context, rc *ResourceContainer, params UpdateAccessMutualTLSCertificateParams) (AccessMutualTLSCertificate, error) { uri := fmt.Sprintf( "/%s/%s/access/certificates/%s", rc.Level, rc.Identifier, - certificateID, + params.ID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, certificate) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessMutualTLSCertificate{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } diff --git a/access_mutual_tls_certificates_test.go b/access_mutual_tls_certificates_test.go index 67a53355384..235f02134c3 100644 --- a/access_mutual_tls_certificates_test.go +++ b/access_mutual_tls_certificates_test.go @@ -53,7 +53,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates", handler) - actual, _, err := client.ListAccessMutualTLSCertificates(context.Background(), testAccountRC, PaginationOptions{}) + actual, _, err := client.ListAccessMutualTLSCertificates(context.Background(), testAccountRC, ListAccessMutualTLSCertificatesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -61,7 +61,7 @@ func TestAccessMutualTLSCertificates(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates", handler) - actual, _, err = client.ListAccessMutualTLSCertificates(context.Background(), testZoneRC, PaginationOptions{}) + actual, _, err = client.ListAccessMutualTLSCertificates(context.Background(), testZoneRC, ListAccessMutualTLSCertificatesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -153,7 +153,7 @@ func TestCreateAccessMutualTLSCertificate(t *testing.T) { updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - certificate := AccessMutualTLSCertificate{ + certificate := CreateAccessMutualTLSCertificateParams{ Name: "Allow devs", Certificate: "-----BEGIN CERTIFICATE-----\nMIIGAjCCA+qgAwIBAgIJAI7kymlF7CWT...N4RI7KKB7nikiuUf8vhULKy5IX10\nDrUtmu/B\n-----END CERTIFICATE-----", } @@ -214,7 +214,8 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) { updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") expiresOn, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") - certificate := AccessMutualTLSCertificate{ + certificate := UpdateAccessMutualTLSCertificateParams{ + ID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "Allow devs", Certificate: "-----BEGIN CERTIFICATE-----\nMIIGAjCCA+qgAwIBAgIJAI7kymlF7CWT...N4RI7KKB7nikiuUf8vhULKy5IX10\nDrUtmu/B\n-----END CERTIFICATE-----", } @@ -231,7 +232,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) + actual, err := client.UpdateAccessMutualTLSCertificate(context.Background(), testAccountRC, certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -239,7 +240,7 @@ func TestUpdateAccessMutualTLSCertificate(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/certificates/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateAccessMutualTLSCertificate(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", certificate) + actual, err = client.UpdateAccessMutualTLSCertificate(context.Background(), testZoneRC, certificate) if assert.NoError(t, err) { assert.Equal(t, want, actual) From be471c75395d056cce508aa152dedda76bcab290 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:21:44 +1000 Subject: [PATCH 076/130] access_organization: use *Params conventions for method signatures --- access_organization.go | 74 ++++++++++++++----------------------- access_organization_test.go | 62 +++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 55 deletions(-) diff --git a/access_organization.go b/access_organization.go index 39f77da7670..d7f616cf534 100644 --- a/access_organization.go +++ b/access_organization.go @@ -47,21 +47,29 @@ type AccessOrganizationDetailResponse struct { Result AccessOrganization `json:"result"` } -//// AccessOrganization returns the Access organisation details. -//// -//// API reference: https://api.cloudflare.com/#access-organizations-access-organization-details -//func (api *API) AccessOrganization(ctx context.Context, accountID string) (AccessOrganization, ResultInfo, error) { -// return api.accessOrganization(ctx, accountID, AccountRouteRoot) -//} -// -//// ZoneLevelAccessOrganization returns the zone level Access organisation details. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-access-organization-details -//func (api *API) ZoneLevelAccessOrganization(ctx context.Context, zoneID string) (AccessOrganization, ResultInfo, error) { -// return api.accessOrganization(ctx, zoneID, ZoneRouteRoot) -//} - -func (api *API) GetAccessOrganization(ctx context.Context, rc *ResourceContainer) (AccessOrganization, ResultInfo, error) { +type GetAccessOrganizationParams struct{} + +type CreateAccessOrganizationParams struct { + Name string `json:"name"` + 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"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` +} + +type UpdateAccessOrganizationParams struct { + Name string `json:"name"` + 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"` + AutoRedirectToIdentity *bool `json:"auto_redirect_to_identity,omitempty"` +} + +func (api *API) GetAccessOrganization(ctx context.Context, rc *ResourceContainer, params GetAccessOrganizationParams) (AccessOrganization, ResultInfo, error) { uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -78,24 +86,10 @@ func (api *API) GetAccessOrganization(ctx context.Context, rc *ResourceContainer return accessOrganizationListResponse.Result, accessOrganizationListResponse.ResultInfo, nil } -//// CreateAccessOrganization creates the Access organisation details. -//// -//// API reference: https://api.cloudflare.com/#access-organizations-create-access-organization -//func (api *API) CreateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { -// return api.createAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) -//} -// -//// CreateZoneLevelAccessOrganization creates the zone level Access organisation details. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-create-access-organization -//func (api *API) CreateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { -// return api.createAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) -//} - -func (api *API) CreateAccessOrganization(ctx context.Context, rc *ResourceContainer, accessOrganization AccessOrganization) (AccessOrganization, error) { +func (api *API) CreateAccessOrganization(ctx context.Context, rc *ResourceContainer, params CreateAccessOrganizationParams) (AccessOrganization, error) { uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessOrganization) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessOrganization{}, err } @@ -109,28 +103,14 @@ func (api *API) CreateAccessOrganization(ctx context.Context, rc *ResourceContai return accessOrganizationDetailResponse.Result, nil } -// UpdateAccessOrganization updates the Access organisation details. -// -// API reference: https://api.cloudflare.com/#access-organizations-update-access-organization -//func (api *API) UpdateAccessOrganization(ctx context.Context, accountID string, accessOrganization AccessOrganization) (AccessOrganization, error) { -// return api.updateAccessOrganization(ctx, accountID, accessOrganization, AccountRouteRoot) -//} -// -//// UpdateZoneLevelAccessOrganization updates the zone level Access organisation details. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization -//func (api *API) UpdateZoneLevelAccessOrganization(ctx context.Context, zoneID string, accessOrganization AccessOrganization) (AccessOrganization, error) { -// return api.updateAccessOrganization(ctx, zoneID, accessOrganization, ZoneRouteRoot) -//} - // UpdateAccessOrganization updates the Access organisation details. // // Account API reference: https://api.cloudflare.com/#access-organizations-update-access-organization // Zone API reference: https://api.cloudflare.com/#zone-level-access-organizations-update-access-organization -func (api *API) UpdateAccessOrganization(ctx context.Context, rc *ResourceContainer, accessOrganization AccessOrganization) (AccessOrganization, error) { +func (api *API) UpdateAccessOrganization(ctx context.Context, rc *ResourceContainer, params UpdateAccessOrganizationParams) (AccessOrganization, error) { uri := fmt.Sprintf("/%s/%s/access/organizations", rc.Level, rc.Identifier) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessOrganization) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessOrganization{}, err } diff --git a/access_organization_test.go b/access_organization_test.go index ca7309c50bf..1407eb7a9cd 100644 --- a/access_organization_test.go +++ b/access_organization_test.go @@ -63,7 +63,7 @@ func TestAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, _, err := client.GetAccessOrganization(context.Background(), testAccountRC) + actual, _, err := client.GetAccessOrganization(context.Background(), testAccountRC, GetAccessOrganizationParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -71,7 +71,7 @@ func TestAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, _, err = client.GetAccessOrganization(context.Background(), testZoneRC) + actual, _, err = client.GetAccessOrganization(context.Background(), testZoneRC, GetAccessOrganizationParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -111,9 +111,9 @@ func TestCreateAccessOrganization(t *testing.T) { updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") want := AccessOrganization{ - Name: "Widget Corps Internal Applications", CreatedAt: &createdAt, UpdatedAt: &updatedAt, + Name: "Widget Corps Internal Applications", AuthDomain: "test.cloudflareaccess.com", LoginDesign: AccessOrganizationLoginDesign{ BackgroundColor: "#c5ed1b", @@ -127,7 +127,18 @@ func TestCreateAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, err := client.CreateAccessOrganization(context.Background(), testAccountRC, want) + actual, err := client.CreateAccessOrganization(context.Background(), testAccountRC, CreateAccessOrganizationParams{ + Name: "Widget Corps Internal Applications", + AuthDomain: "test.cloudflareaccess.com", + LoginDesign: AccessOrganizationLoginDesign{ + BackgroundColor: "#c5ed1b", + LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", + }, + IsUIReadOnly: BoolPtr(true), + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -135,7 +146,18 @@ func TestCreateAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, err = client.CreateAccessOrganization(context.Background(), testZoneRC, want) + actual, err = client.CreateAccessOrganization(context.Background(), testZoneRC, CreateAccessOrganizationParams{ + Name: "Widget Corps Internal Applications", + AuthDomain: "test.cloudflareaccess.com", + LoginDesign: AccessOrganizationLoginDesign{ + BackgroundColor: "#c5ed1b", + LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", + }, + IsUIReadOnly: BoolPtr(true), + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -176,9 +198,9 @@ func TestUpdateAccessOrganization(t *testing.T) { updatedAt, _ := time.Parse(time.RFC3339, "2014-01-01T05:20:00.12345Z") want := AccessOrganization{ - Name: "Widget Corps Internal Applications", CreatedAt: &createdAt, UpdatedAt: &updatedAt, + Name: "Widget Corps Internal Applications", AuthDomain: "test.cloudflareaccess.com", LoginDesign: AccessOrganizationLoginDesign{ BackgroundColor: "#c5ed1b", @@ -193,7 +215,19 @@ func TestUpdateAccessOrganization(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations", handler) - actual, err := client.UpdateAccessOrganization(context.Background(), testAccountRC, want) + actual, err := client.UpdateAccessOrganization(context.Background(), testAccountRC, UpdateAccessOrganizationParams{ + Name: "Widget Corps Internal Applications", + AuthDomain: "test.cloudflareaccess.com", + LoginDesign: AccessOrganizationLoginDesign{ + BackgroundColor: "#c5ed1b", + LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", + }, + IsUIReadOnly: BoolPtr(false), + UIReadOnlyToggleReason: "this is my reason", + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -201,7 +235,19 @@ func TestUpdateAccessOrganization(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations", handler) - actual, err = client.UpdateAccessOrganization(context.Background(), testZoneRC, want) + actual, err = client.UpdateAccessOrganization(context.Background(), testZoneRC, UpdateAccessOrganizationParams{ + Name: "Widget Corps Internal Applications", + AuthDomain: "test.cloudflareaccess.com", + LoginDesign: AccessOrganizationLoginDesign{ + BackgroundColor: "#c5ed1b", + LogoPath: "https://example.com/logo.png", + TextColor: "#c5ed1b", + HeaderText: "Widget Corp", + FooterText: "© Widget Corp", + }, + IsUIReadOnly: BoolPtr(false), + UIReadOnlyToggleReason: "this is my reason", + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) From 26c6c80b43e35b994393c2af8a824ec3c2392903 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:36:42 +1000 Subject: [PATCH 077/130] access_policy: use *Params conventions for method signatures --- access_policy.go | 93 ++++++++++++++++++++++++--------- access_policy_test.go | 119 ++++++++++++++++++++++-------------------- 2 files changed, 130 insertions(+), 82 deletions(-) diff --git a/access_policy.go b/access_policy.go index 4f98c44ae8b..b6d10031d97 100644 --- a/access_policy.go +++ b/access_policy.go @@ -3,11 +3,16 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" "time" ) +var ( + ErrMissingApplicationID = errors.New("missing required application ID") +) + type AccessApprovalGroup struct { EmailListUuid string `json:"email_list_uuid,omitempty"` EmailAddresses []string `json:"email_addresses,omitempty"` @@ -60,40 +65,80 @@ type AccessPolicyDetailResponse struct { Result AccessPolicy `json:"result"` } +type ListAccessPoliciesParams struct { + ApplicationID string `json:"-"` + ResultInfo +} + +type GetAccessPolicyParams struct { + ApplicationID string `json:"-"` + PolicyID string `json:"-"` +} + +type CreateAccessPolicyParams struct { + ApplicationID string `json:"-"` + + Precedence int `json:"precedence"` + Decision string `json:"decision"` + 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"` + ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + + // The include policy works like an OR logical operator. The user must + // satisfy one of the rules. + Include []interface{} `json:"include"` + + // The exclude policy works like a NOT logical operator. The user must + // not satisfy all the rules in exclude. + Exclude []interface{} `json:"exclude"` + + // The require policy works like a AND logical operator. The user must + // satisfy all the rules in require. + Require []interface{} `json:"require"` +} + +type DeleteAccessPolicyParams struct { + ApplicationID string `json:"-"` + PolicyID string `json:"-"` +} + // ListAccessPolicies returns all access policies for an access application. // // Account API reference: https://developers.cloudflare.com/api/operations/access-policies-list-access-policies // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-list-access-policies -func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, applicationID string, pageOpts PaginationOptions) ([]AccessPolicy, *ResultInfo, error) { +func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, params ListAccessPoliciesParams) ([]AccessPolicy, *ResultInfo, error) { + if params.ApplicationID == "" { + return []AccessPolicy{}, &ResultInfo{}, ErrMissingApplicationID + } + baseURL := fmt.Sprintf( "/%s/%s/access/apps/%s/policies", rc.Level, rc.Identifier, - applicationID, + params.ApplicationID, ) autoPaginate := true - if pageOpts.PerPage >= 1 || pageOpts.Page >= 1 { + if params.PerPage >= 1 || params.Page >= 1 { autoPaginate = false } - if pageOpts.PerPage < 1 { - pageOpts.PerPage = 25 + if params.PerPage < 1 { + params.PerPage = 25 } - if pageOpts.Page < 1 { - pageOpts.Page = 1 - } - - resultInfo := ResultInfo{ - Page: pageOpts.Page, - PerPage: pageOpts.PerPage, + if params.Page < 1 { + params.Page = 1 } var accessPolicies []AccessPolicy var r AccessPolicyListResponse for { - uri := buildURI(baseURL, pageOpts) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -104,8 +149,8 @@ func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, a return []AccessPolicy{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } accessPolicies = append(accessPolicies, r.Result...) - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || autoPaginate { break } } @@ -117,13 +162,13 @@ func (api *API) ListAccessPolicies(ctx context.Context, rc *ResourceContainer, a // // Account API reference: https://developers.cloudflare.com/api/operations/access-policies-get-an-access-policy // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-get-an-access-policy -func (api *API) GetAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, policyID string) (AccessPolicy, error) { +func (api *API) GetAccessPolicy(ctx context.Context, rc *ResourceContainer, params GetAccessPolicyParams) (AccessPolicy, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", rc.Level, rc.Identifier, - applicationID, - policyID, + params.ApplicationID, + params.PolicyID, ) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -144,15 +189,15 @@ func (api *API) GetAccessPolicy(ctx context.Context, rc *ResourceContainer, appl // // Account API reference: https://developers.cloudflare.com/api/operations/access-policies-create-an-access-policy // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-create-an-access-policy -func (api *API) CreateAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { +func (api *API) CreateAccessPolicy(ctx context.Context, rc *ResourceContainer, params CreateAccessPolicyParams) (AccessPolicy, error) { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies", rc.Level, rc.Identifier, - applicationID, + params.ApplicationID, ) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessPolicy) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } @@ -200,13 +245,13 @@ func (api *API) UpdateAccessPolicy(ctx context.Context, rc *ResourceContainer, a // // Account API reference: https://developers.cloudflare.com/api/operations/access-policies-delete-an-access-policy // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-delete-an-access-policy -func (api *API) DeleteAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID, accessPolicyID string) error { +func (api *API) DeleteAccessPolicy(ctx context.Context, rc *ResourceContainer, params DeleteAccessPolicyParams) error { uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", rc.Level, rc.Identifier, - applicationID, - accessPolicyID, + params.ApplicationID, + params.PolicyID, ) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) diff --git a/access_policy_test.go b/access_policy_test.go index 4df981eac39..f3f8a66fd85 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -69,63 +69,65 @@ func TestAccessPolicies(t *testing.T) { "errors": [], "messages": [], "result": [ - { - "id": "699d98642c564d2e855e9661899b7252", - "precedence": 1, - "decision": "allow", - "created_at": "2014-01-01T05:20:00.12345Z", - "updated_at": "2014-01-01T05:20:00.12345Z", - "name": "Allow devs", - "include": [ - { - "email": { - "email": "test@example.com" - } - } - ], - "exclude": [ - { - "email": { - "email": "test@example.com" - } - } - ], - "require": [ - { - "email": { - "email": "test@example.com" - } - } + { + "id": "699d98642c564d2e855e9661899b7252", + "precedence": 1, + "decision": "allow", + "created_at": "2014-01-01T05:20:00.12345Z", + "updated_at": "2014-01-01T05:20:00.12345Z", + "name": "Allow devs", + "include": [ + { + "email": { + "email": "test@example.com" + } + } + ], + "exclude": [ + { + "email": { + "email": "test@example.com" + } + } + ], + "require": [ + { + "email": { + "email": "test@example.com" + } + } + ], + "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, + "approval_groups": [ + { + "email_list_uuid": "2413b6d7-bbe5-48bd-8fbb-e52069c85561", + "approvals_needed": 3 + }, + { + "email_addresses": [ + "email1@example.com", + "email2@example.com" ], - "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, - "approval_groups": [ - { - "email_list_uuid": "2413b6d7-bbe5-48bd-8fbb-e52069c85561", - "approvals_needed": 3 - }, - { - "email_addresses": ["email1@example.com", "email2@example.com"], - "approvals_needed": 1 - } - ] - } + "approvals_needed": 1 + } + ] + } ], "result_info": { - "page": 1, - "per_page": 20, - "count": 1, - "total_count": 2000 + "page": 1, + "per_page": 20, + "count": 1, + "total_count": 20 } - } - `) + }`) } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, _, err := client.ListAccessPolicies(context.Background(), testAccountRC, accessApplicationID, pageOptions) + actual, _, err := client.ListAccessPolicies(context.Background(), testAccountRC, ListAccessPoliciesParams{ApplicationID: accessApplicationID}) if assert.NoError(t, err) { assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual) @@ -133,7 +135,7 @@ func TestAccessPolicies(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, _, err = client.ListAccessPolicies(context.Background(), testZoneRC, accessApplicationID, pageOptions) + actual, _, err = client.ListAccessPolicies(context.Background(), testZoneRC, ListAccessPoliciesParams{ApplicationID: accessApplicationID}) if assert.NoError(t, err) { assert.Equal(t, []AccessPolicy{expectedAccessPolicy}, actual) @@ -200,7 +202,7 @@ func TestAccessPolicy(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err := client.GetAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicyID) + actual, err := client.GetAccessPolicy(context.Background(), testAccountRC, GetAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID}) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -208,7 +210,7 @@ func TestAccessPolicy(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err = client.GetAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicyID) + actual, err = client.GetAccessPolicy(context.Background(), testZoneRC, GetAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID}) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -273,8 +275,9 @@ func TestCreateAccessPolicy(t *testing.T) { `) } - accessPolicy := AccessPolicy{ - Name: "Allow devs", + accessPolicy := CreateAccessPolicyParams{ + ApplicationID: accessApplicationID, + Name: "Allow devs", Include: []interface{}{ AccessGroupEmail{struct { Email string `json:"email"` @@ -307,7 +310,7 @@ func TestCreateAccessPolicy(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, err := client.CreateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicy) + actual, err := client.CreateAccessPolicy(context.Background(), testAccountRC, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -315,7 +318,7 @@ func TestCreateAccessPolicy(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies", handler) - actual, err = client.CreateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicy) + actual, err = client.CreateAccessPolicy(context.Background(), testZoneRC, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -425,12 +428,12 @@ func TestDeleteAccessPolicy(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - err := client.DeleteAccessPolicy(context.Background(), testAccountRC, accessApplicationID, accessPolicyID) + err := client.DeleteAccessPolicy(context.Background(), testAccountRC, DeleteAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID}) assert.NoError(t, err) mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - err = client.DeleteAccessPolicy(context.Background(), testZoneRC, accessApplicationID, accessPolicyID) + err = client.DeleteAccessPolicy(context.Background(), testZoneRC, DeleteAccessPolicyParams{ApplicationID: accessApplicationID, PolicyID: accessPolicyID}) assert.NoError(t, err) } From 882e9f32705e49d78393065b380f9cab06664286 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:43:38 +1000 Subject: [PATCH 078/130] access_service_tokens: use *Params conventions for method signatures --- access_service_tokens.go | 98 +++++++++-------------------------- access_service_tokens_test.go | 12 ++--- 2 files changed, 31 insertions(+), 79 deletions(-) diff --git a/access_service_tokens.go b/access_service_tokens.go index f2298373721..d3a4d66f8c2 100644 --- a/access_service_tokens.go +++ b/access_service_tokens.go @@ -3,11 +3,16 @@ package cloudflare import ( "context" "encoding/json" + "errors" "fmt" "net/http" "time" ) +var ( + ErrMissingServiceTokenUUID = errors.New("missing required service token UUID") +) + // AccessServiceToken represents an Access Service Token. type AccessServiceToken struct { ClientID string `json:"client_id"` @@ -119,21 +124,18 @@ type AccessServiceTokensRotateSecretDetailResponse struct { Result AccessServiceTokenRotateResponse `json:"result"` } -//// AccessServiceTokens returns all Access Service Tokens for an account. -//// -//// API reference: https://api.cloudflare.com/#access-service-tokens-list-access-service-tokens -//func (api *API) AccessServiceTokens(ctx context.Context, accountID string) ([]AccessServiceToken, ResultInfo, error) { -// return api.accessServiceTokens(ctx, accountID, AccountRouteRoot) -//} -// -//// ZoneLevelAccessServiceTokens returns all Access Service Tokens for a zone. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-list-access-service-tokens -//func (api *API) ZoneLevelAccessServiceTokens(ctx context.Context, zoneID string) ([]AccessServiceToken, ResultInfo, error) { -// return api.accessServiceTokens(ctx, zoneID, ZoneRouteRoot) -//} - -func (api *API) ListAccessServiceTokens(ctx context.Context, rc *ResourceContainer) ([]AccessServiceToken, ResultInfo, error) { +type ListAccessServiceTokensParams struct{} + +type CreateAccessServiceTokenParams struct { + Name string `json:"name"` +} + +type UpdateAccessServiceTokenParams struct { + Name string `json:"name"` + UUID string `json:"-"` +} + +func (api *API) ListAccessServiceTokens(ctx context.Context, rc *ResourceContainer, params ListAccessServiceTokensParams) ([]AccessServiceToken, ResultInfo, error) { uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) @@ -150,27 +152,9 @@ func (api *API) ListAccessServiceTokens(ctx context.Context, rc *ResourceContain return accessServiceTokensListResponse.Result, accessServiceTokensListResponse.ResultInfo, nil } -//// CreateAccessServiceToken creates a new Access Service Token for an account. -//// -//// API reference: https://api.cloudflare.com/#access-service-tokens-create-access-service-token -//func (api *API) CreateAccessServiceToken(ctx context.Context, accountID, name string) (AccessServiceTokenCreateResponse, error) { -// return api.createAccessServiceToken(ctx, accountID, name, AccountRouteRoot) -//} -// -//// CreateZoneLevelAccessServiceToken creates a new Access Service Token for a zone. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-create-access-service-token -//func (api *API) CreateZoneLevelAccessServiceToken(ctx context.Context, zoneID, name string) (AccessServiceTokenCreateResponse, error) { -// return api.createAccessServiceToken(ctx, zoneID, name, ZoneRouteRoot) -//} - -func (api *API) CreateAccessServiceToken(ctx context.Context, rc *ResourceContainer, name string) (AccessServiceTokenCreateResponse, error) { +func (api *API) CreateAccessServiceToken(ctx context.Context, rc *ResourceContainer, params CreateAccessServiceTokenParams) (AccessServiceTokenCreateResponse, error) { uri := fmt.Sprintf("/%s/%s/access/service_tokens", rc.Level, rc.Identifier) - marshalledName, _ := json.Marshal(struct { - Name string `json:"name"` - }{name}) - - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, marshalledName) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return AccessServiceTokenCreateResponse{}, err @@ -185,30 +169,14 @@ func (api *API) CreateAccessServiceToken(ctx context.Context, rc *ResourceContai return accessServiceTokenCreation.Result, nil } -// UpdateAccessServiceToken updates an existing Access Service Token for an -// account. -// -// API reference: https://api.cloudflare.com/#access-service-tokens-update-access-service-token -//func (api *API) UpdateAccessServiceToken(ctx context.Context, accountID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { -// return api.updateAccessServiceToken(ctx, accountID, uuid, name, AccountRouteRoot) -//} -// -//// UpdateZoneLevelAccessServiceToken updates an existing Access Service Token for a -//// zone. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-update-access-service-token -//func (api *API) UpdateZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid, name string) (AccessServiceTokenUpdateResponse, error) { -// return api.updateAccessServiceToken(ctx, zoneID, uuid, name, ZoneRouteRoot) -//} - -func (api *API) UpdateAccessServiceToken(ctx context.Context, rc *ResourceContainer, uuid, name string) (AccessServiceTokenUpdateResponse, error) { - uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, uuid) +func (api *API) UpdateAccessServiceToken(ctx context.Context, rc *ResourceContainer, params UpdateAccessServiceTokenParams) (AccessServiceTokenUpdateResponse, error) { + if params.UUID == "" { + return AccessServiceTokenUpdateResponse{}, ErrMissingServiceTokenUUID + } - marshalledName, _ := json.Marshal(struct { - Name string `json:"name"` - }{name}) + uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, params.UUID) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, marshalledName) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessServiceTokenUpdateResponse{}, err } @@ -222,22 +190,6 @@ func (api *API) UpdateAccessServiceToken(ctx context.Context, rc *ResourceContai return accessServiceTokenUpdate.Result, nil } -// DeleteAccessServiceToken removes an existing Access Service Token for an -// account. -// -// API reference: https://api.cloudflare.com/#access-service-tokens-delete-access-service-token -//func (api *API) DeleteAccessServiceToken(ctx context.Context, accountID, uuid string) (AccessServiceTokenUpdateResponse, error) { -// return api.deleteAccessServiceToken(ctx, accountID, uuid, AccountRouteRoot) -//} -// -//// DeleteZoneLevelAccessServiceToken removes an existing Access Service Token for a -//// zone. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-service-tokens-delete-access-service-token -//func (api *API) DeleteZoneLevelAccessServiceToken(ctx context.Context, zoneID, uuid string) (AccessServiceTokenUpdateResponse, error) { -// return api.deleteAccessServiceToken(ctx, zoneID, uuid, ZoneRouteRoot) -//} - func (api *API) DeleteAccessServiceToken(ctx context.Context, rc *ResourceContainer, uuid string) (AccessServiceTokenUpdateResponse, error) { uri := fmt.Sprintf("/%s/%s/access/service_tokens/%s", rc.Level, rc.Identifier, uuid) diff --git a/access_service_tokens_test.go b/access_service_tokens_test.go index 27de1aedcb1..5943e80bc53 100644 --- a/access_service_tokens_test.go +++ b/access_service_tokens_test.go @@ -52,7 +52,7 @@ func TestAccessServiceTokens(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler) - actual, _, err := client.ListAccessServiceTokens(context.Background(), testAccountRC) + actual, _, err := client.ListAccessServiceTokens(context.Background(), testAccountRC, ListAccessServiceTokensParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -60,7 +60,7 @@ func TestAccessServiceTokens(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler) - actual, _, err = client.ListAccessServiceTokens(context.Background(), testZoneRC) + actual, _, err = client.ListAccessServiceTokens(context.Background(), testZoneRC, ListAccessServiceTokensParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -103,7 +103,7 @@ func TestCreateAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens", handler) - actual, err := client.CreateAccessServiceToken(context.Background(), testAccountRC, "CI/CD token") + actual, err := client.CreateAccessServiceToken(context.Background(), testAccountRC, CreateAccessServiceTokenParams{Name: "CI/CD token"}) if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -111,7 +111,7 @@ func TestCreateAccessServiceToken(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens", handler) - actual, err = client.CreateAccessServiceToken(context.Background(), testZoneRC, "CI/CD token") + actual, err = client.CreateAccessServiceToken(context.Background(), testZoneRC, CreateAccessServiceTokenParams{Name: "CI/CD token"}) if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -152,7 +152,7 @@ func TestUpdateAccessServiceToken(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") + actual, err := client.UpdateAccessServiceToken(context.Background(), testAccountRC, UpdateAccessServiceTokenParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "CI/CD token"}) if assert.NoError(t, err) { assert.Equal(t, expected, actual) @@ -160,7 +160,7 @@ func TestUpdateAccessServiceToken(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/service_tokens/f174e90a-fafe-4643-bbbc-4a0ed4fc8415", handler) - actual, err = client.UpdateAccessServiceToken(context.Background(), testZoneRC, "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", "CI/CD token") + actual, err = client.UpdateAccessServiceToken(context.Background(), testZoneRC, UpdateAccessServiceTokenParams{UUID: "f174e90a-fafe-4643-bbbc-4a0ed4fc8415", Name: "CI/CD token"}) if assert.NoError(t, err) { assert.Equal(t, expected, actual) From 0ca81cae5d95088ea4f36160d360855dd03c45c7 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 11:46:10 +1000 Subject: [PATCH 079/130] access_user_tokens: use *Params conventions for method signatures --- access_user_tokens.go | 22 +++------------------- access_user_tokens_test.go | 8 ++------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/access_user_tokens.go b/access_user_tokens.go index a1494089e4a..ba32d7fbfee 100644 --- a/access_user_tokens.go +++ b/access_user_tokens.go @@ -6,32 +6,16 @@ import ( "net/http" ) -type AccessUserEmail struct { +type RevokeAccessUserTokensParams struct { Email string `json:"email"` } -//// RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user -//// Access User. -//// -//// API reference: https://api.cloudflare.com/#access-organizations-revoke-all-access-tokens-for-a-user -//func (api *API) RevokeAccessUserTokens(ctx context.Context, accountID string, accessUserEmail AccessUserEmail) error { -// return api.revokeUserTokens(ctx, accountID, accessUserEmail, AccountRouteRoot) -//} -// -//// RevokeZoneLevelAccessUserTokens revokes any outstanding tokens issued for a specific user -//// Access User. -//// -//// API reference: https://api.cloudflare.com/#zone-level-access-organizations-revoke-all-access-tokens-for-a-user -//func (api *API) RevokeZoneLevelAccessUserTokens(ctx context.Context, zoneID string, accessUserEmail AccessUserEmail) error { -// return api.revokeUserTokens(ctx, zoneID, accessUserEmail, ZoneRouteRoot) -//} - // RevokeAccessUserTokens revokes any outstanding tokens issued for a specific user // Access User. -func (api *API) RevokeAccessUserTokens(ctx context.Context, rc *ResourceContainer, accessUserEmail AccessUserEmail) error { +func (api *API) RevokeAccessUserTokens(ctx context.Context, rc *ResourceContainer, params RevokeAccessUserTokensParams) error { uri := fmt.Sprintf("/%s/%s/access/organizations/revoke_user", rc.Level, rc.Identifier) - _, err := api.makeRequestContext(ctx, http.MethodPost, uri, accessUserEmail) + _, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return err } diff --git a/access_user_tokens_test.go b/access_user_tokens_test.go index 5fb7e18919a..921c9b85cf2 100644 --- a/access_user_tokens_test.go +++ b/access_user_tokens_test.go @@ -25,9 +25,7 @@ func TestRevokeAccessUserTokens(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/organizations/revoke_user", handler) - AccessUserEmail := AccessUserEmail{Email: "test@example.com"} - - err := client.RevokeAccessUserTokens(context.Background(), testAccountRC, AccessUserEmail) + err := client.RevokeAccessUserTokens(context.Background(), testAccountRC, RevokeAccessUserTokensParams{Email: "test@example.com"}) assert.NoError(t, err) } @@ -48,9 +46,7 @@ func TestRevokeZoneLevelAccessUserTokens(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/organizations/revoke_user", handler) - AccessUserEmail := AccessUserEmail{Email: "test@example.com"} - - err := client.RevokeAccessUserTokens(context.Background(), testZoneRC, AccessUserEmail) + err := client.RevokeAccessUserTokens(context.Background(), testZoneRC, RevokeAccessUserTokensParams{Email: "test@example.com"}) assert.NoError(t, err) } From 1e579b5bc9942cb76631bd8d54cffcb6ec41a4c4 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 26 Jun 2023 12:29:10 +1000 Subject: [PATCH 080/130] fix pagination handling --- access_application.go | 14 +++++--------- access_ca_certificate.go | 15 +++++---------- access_group.go | 13 ++++--------- access_group_test.go | 4 ++-- access_mutual_tls_certificates.go | 11 +++-------- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/access_application.go b/access_application.go index 090dec96c72..1c8bd66e6c4 100644 --- a/access_application.go +++ b/access_application.go @@ -113,7 +113,7 @@ type SaasApplication struct { } type ListAccessApplicationsParams struct { - PaginationOptions + ResultInfo } type CreateAccessApplicationParams struct { @@ -187,15 +187,11 @@ func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContaine params.Page = 1 } - resultInfo := ResultInfo{ - Page: params.Page, - PerPage: params.PerPage, - } - var applications []AccessApplication var r AccessApplicationListResponse + for { - uri := buildURI(baseURL, resultInfo) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -207,8 +203,8 @@ func (api *API) ListAccessApplications(ctx context.Context, rc *ResourceContaine return []AccessApplication{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } applications = append(applications, r.Result...) - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || autoPaginate { break } } diff --git a/access_ca_certificate.go b/access_ca_certificate.go index 1bfe94f4d97..a1fc12b935d 100644 --- a/access_ca_certificate.go +++ b/access_ca_certificate.go @@ -31,7 +31,7 @@ type AccessCACertificateResponse struct { } type ListAccessCACertificatesParams struct { - PaginationOptions + ResultInfo } type CreateAccessCACertificateParams struct { @@ -58,16 +58,11 @@ func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContai params.Page = 1 } - resultInfo := ResultInfo{ - Page: params.Page, - PerPage: params.PerPage, - } - var accessCACertificates []AccessCACertificate var r AccessCACertificateListResponse for { - uri := buildURI(baseURL, resultInfo) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -78,13 +73,13 @@ func (api *API) ListAccessCACertificates(ctx context.Context, rc *ResourceContai return []AccessCACertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } accessCACertificates = append(accessCACertificates, r.Result...) - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || autoPaginate { break } } - return accessCACertificates, &resultInfo, nil + return accessCACertificates, &r.ResultInfo, nil } // GetAccessCACertificate returns a single CA certificate associated within diff --git a/access_group.go b/access_group.go index c04d9f3c940..c21a80eebef 100644 --- a/access_group.go +++ b/access_group.go @@ -204,7 +204,7 @@ type AccessGroupDetailResponse struct { } type ListAccessGroupsParams struct { - PaginationOptions + ResultInfo } type CreateAccessGroupParams struct { @@ -260,16 +260,11 @@ func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, par params.Page = 1 } - resultInfo := ResultInfo{ - Page: params.Page, - PerPage: params.PerPage, - } - var accessGroups []AccessGroup var r AccessGroupListResponse for { - uri := buildURI(baseURL, resultInfo) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -280,8 +275,8 @@ func (api *API) ListAccessGroups(ctx context.Context, rc *ResourceContainer, par return []AccessGroup{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } accessGroups = append(accessGroups, r.Result...) - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || autoPaginate { break } } diff --git a/access_group_test.go b/access_group_test.go index 1766beffd79..11f53807962 100644 --- a/access_group_test.go +++ b/access_group_test.go @@ -91,7 +91,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/access/groups", handler) - actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, ListAccessGroupsParams{PaginationOptions{}}) + actual, _, err := client.ListAccessGroups(context.Background(), testAccountRC, ListAccessGroupsParams{ResultInfo{}}) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) @@ -99,7 +99,7 @@ func TestAccessGroups(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/access/groups", handler) - actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, ListAccessGroupsParams{PaginationOptions{}}) + actual, _, err = client.ListAccessGroups(context.Background(), testZoneRC, ListAccessGroupsParams{ResultInfo{}}) if assert.NoError(t, err) { assert.Equal(t, []AccessGroup{expectedAccessGroup}, actual) diff --git a/access_mutual_tls_certificates.go b/access_mutual_tls_certificates.go index dd6a1c12060..ae80f980147 100644 --- a/access_mutual_tls_certificates.go +++ b/access_mutual_tls_certificates.go @@ -81,16 +81,11 @@ func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *Resourc params.Page = 1 } - resultInfo := ResultInfo{ - Page: params.Page, - PerPage: params.PerPage, - } - var accessCertificates []AccessMutualTLSCertificate var r AccessMutualTLSCertificateListResponse for { - uri := buildURI(baseURL, resultInfo) + uri := buildURI(baseURL, params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errMakeRequestError, err) @@ -101,8 +96,8 @@ func (api *API) ListAccessMutualTLSCertificates(ctx context.Context, rc *Resourc return []AccessMutualTLSCertificate{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err) } accessCertificates = append(accessCertificates, r.Result...) - resultInfo = r.ResultInfo.Next() - if resultInfo.Done() || autoPaginate { + params.ResultInfo = r.ResultInfo.Next() + if params.ResultInfo.Done() || autoPaginate { break } } From 4a2aca78fb51bbb01213f9720245bf358ef6af0b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Mon, 26 Jun 2023 02:42:59 +0000 Subject: [PATCH 081/130] Update CHANGELOG.md for #1319 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1d2b7b4f7..41516a44cbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,25 @@ ## 0.71.0 (Unreleased) +BREAKING CHANGES: + +* access_application: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_ca_certificate: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_group: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_identity_provider: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_mutual_tls_certificates: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_organization: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) + ENHANCEMENTS: +* access_application: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_ca_certificate: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_group: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_identity_provider: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_mutual_tls_certificates: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* access_policy: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) * device_posture_rule: support os_version_extra ([#1316](https://github.com/cloudflare/cloudflare-go/issues/1316)) * workers: Add ability to specify tail Workers in script metadata ([#1317](https://github.com/cloudflare/cloudflare-go/issues/1317)) From 098391b098ef86648ad929fae3260b6aeeba8b0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jun 2023 16:00:58 +0000 Subject: [PATCH 082/130] build(deps): bump dependabot/fetch-metadata from 1.5.1 to 1.6.0 Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 1.5.1 to 1.6.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/v1.5.1...v1.6.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 4eb7e7d16c8..ebdcadca5d1 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.5.1 + uses: dependabot/fetch-metadata@v1.6.0 - uses: actions/checkout@v3 - run: | gh pr checkout $PR_URL From 150368925073d51b10a6e3d35cbc7982614f6169 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 28 Jun 2023 16:01:18 +0000 Subject: [PATCH 083/130] add CHANGELOG for #1320 --- .changelog/1320.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1320.txt diff --git a/.changelog/1320.txt b/.changelog/1320.txt new file mode 100644 index 00000000000..6fe1268d134 --- /dev/null +++ b/.changelog/1320.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps dependabot/fetch-metadata from 1.5.1 to 1.6.0 +``` From 8c81839a086ab8207dcc31f16b962ddf628a4243 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 28 Jun 2023 21:07:33 +0000 Subject: [PATCH 084/130] Update CHANGELOG.md for #1320 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41516a44cbc..d16142f96bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ ENHANCEMENTS: * device_posture_rule: support os_version_extra ([#1316](https://github.com/cloudflare/cloudflare-go/issues/1316)) * workers: Add ability to specify tail Workers in script metadata ([#1317](https://github.com/cloudflare/cloudflare-go/issues/1317)) +DEPENDENCIES: + +* deps: bumps dependabot/fetch-metadata from 1.5.1 to 1.6.0 ([#1320](https://github.com/cloudflare/cloudflare-go/issues/1320)) + ## 0.70.0 (June 21st, 2023) BREAKING CHANGES: From 9bcfb7ab6a43e5faa056ac4b5eb17e50bea9b729 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Sun, 4 Jun 2023 23:15:48 -0400 Subject: [PATCH 085/130] adds method to create image v2 direct upload url --- images.go | 23 +++++++++++++++++++++++ images_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/images.go b/images.go index 8cb9fd2f711..6c4e752a366 100644 --- a/images.go +++ b/images.go @@ -83,6 +83,12 @@ type ImageDirectUploadURLRequest struct { Expiry time.Time `json:"expiry"` } +type ImageDirectUploadURLV2Request struct { + Expiry time.Time `json:"expiry"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + RequireSignedURLs bool `json:"requireSignedURLs"` +} + // ImageDirectUploadURLResponse is the API response for a direct image upload url. type ImageDirectUploadURLResponse struct { Result ImageDirectUploadURL `json:"result"` @@ -197,6 +203,23 @@ func (api *API) CreateImageDirectUploadURL(ctx context.Context, accountID string return imageDirectUploadURLResponse.Result, nil } +// CreateImageDirectUploadURLV2 creates an authenticated v2 direct upload url. +func (api *API) CreateImageDirectUploadURLV2(ctx context.Context, accountID string, params ImageDirectUploadURLV2Request) (ImageDirectUploadURL, error) { + uri := fmt.Sprintf("/accounts/%s/images/v2/direct_upload", accountID) + + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + if err != nil { + return ImageDirectUploadURL{}, err + } + + var imageDirectUploadURLResponse ImageDirectUploadURLResponse + err = json.Unmarshal(res, &imageDirectUploadURLResponse) + if err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return imageDirectUploadURLResponse.Result, nil +} + // ListImages lists all images. // // API Reference: https://api.cloudflare.com/#cloudflare-images-list-images diff --git a/images_test.go b/images_test.go index 25ad505d97e..25075ec4983 100644 --- a/images_test.go +++ b/images_test.go @@ -190,6 +190,53 @@ func TestCreateImageDirectUploadURL(t *testing.T) { } } +func TestCreateImageDirectUploadURLV2(t *testing.T) { + setup() + defer teardown() + + input := ImageDirectUploadURLV2Request{ + Expiry: time.Now().UTC().Add(30 * time.Minute), + Metadata: map[string]interface{}{ + "metaKey1": "metaValue1", + "metaKey2": "metaValue2", + }, + RequireSignedURLs: true, + } + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) + + var v ImageDirectUploadURLV2Request + err := json.NewDecoder(r.Body).Decode(&v) + require.NoError(t, err) + assert.Equal(t, input, v) + + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", + "uploadURL": "https://upload.imagedelivery.net/fgr33htrthytjtyereifjewoi338272s7w1383" + } + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/images/v2/direct_upload", handler) + want := ImageDirectUploadURL{ + ID: "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", + UploadURL: "https://upload.imagedelivery.net/fgr33htrthytjtyereifjewoi338272s7w1383", + } + + actual, err := client.CreateImageDirectUploadURLV2(context.Background(), testAccountID, input) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestListImages(t *testing.T) { setup() defer teardown() From 52a977ea321741eefdd2313d332aa3cd4e9306b8 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Wed, 14 Jun 2023 09:57:19 +0530 Subject: [PATCH 086/130] adds changelog --- .changelog/1308.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1308.txt diff --git a/.changelog/1308.txt b/.changelog/1308.txt new file mode 100644 index 00000000000..938cec780b8 --- /dev/null +++ b/.changelog/1308.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +images: adds `CreateImageDirectUploadURLV2` to images API +``` From f5e391e1aaa42bc03f7bcc821aff85e089f9d226 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Fri, 16 Jun 2023 16:02:52 +0530 Subject: [PATCH 087/130] fixes multipart form and test --- images.go | 34 +++++++++++++++++++++++++++++++++- images_test.go | 27 ++++++++++++++++----------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/images.go b/images.go index 6c4e752a366..0a7cd3147bb 100644 --- a/images.go +++ b/images.go @@ -203,11 +203,43 @@ func (api *API) CreateImageDirectUploadURL(ctx context.Context, accountID string return imageDirectUploadURLResponse.Result, nil } +var imagesMultipartBoundary = "----CloudflareImagesGoClientBoundary" + // CreateImageDirectUploadURLV2 creates an authenticated v2 direct upload url. func (api *API) CreateImageDirectUploadURLV2(ctx context.Context, accountID string, params ImageDirectUploadURLV2Request) (ImageDirectUploadURL, error) { uri := fmt.Sprintf("/accounts/%s/images/v2/direct_upload", accountID) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + writer.SetBoundary(imagesMultipartBoundary) + if params.RequireSignedURLs { + writer.WriteField("requireSignedURLs", "true") + } + if !params.Expiry.IsZero() { + writer.WriteField("expiry", params.Expiry.Format(time.RFC3339)) + } + if params.Metadata != nil { + metadataBytes, err := json.Marshal(params.Metadata) + if err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error marshalling metadata to JSON: %w", err) + } + writer.WriteField("metadata", string(metadataBytes)) + } + err := writer.Close() + if err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error closing multipart writer: %w", err) + } + + res, err := api.makeRequestContextWithHeaders( + ctx, + http.MethodPost, + uri, + body, + http.Header{ + "Accept": []string{"application/json"}, + "Content-Type": []string{writer.FormDataContentType()}, + }, + ) if err != nil { return ImageDirectUploadURL{}, err } diff --git a/images_test.go b/images_test.go index 25075ec4983..96c3a751f6b 100644 --- a/images_test.go +++ b/images_test.go @@ -194,23 +194,29 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { setup() defer teardown() + exp := time.Now().UTC().Add(30 * time.Minute) + metadata := map[string]interface{}{ + "metaKey1": "metaValue1", + "metaKey2": "metaValue2", + } input := ImageDirectUploadURLV2Request{ - Expiry: time.Now().UTC().Add(30 * time.Minute), - Metadata: map[string]interface{}{ - "metaKey1": "metaValue1", - "metaKey2": "metaValue2", - }, + Expiry: exp, + Metadata: metadata, RequireSignedURLs: true, } handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - - var v ImageDirectUploadURLV2Request - err := json.NewDecoder(r.Body).Decode(&v) + require.Equal(t, + fmt.Sprintf("multipart/form-data; boundary=%s", imagesMultipartBoundary), + r.Header.Get("Content-Type"), + ) + require.NoError(t, r.ParseMultipartForm(32<<20)) + require.Equal(t, exp.Format(time.RFC3339), r.Form.Get("expiry")) + require.Equal(t, "true", r.Form.Get("requireSignedURLs")) + marshalledMetadata, err := json.Marshal(metadata) require.NoError(t, err) - assert.Equal(t, input, v) - + require.Equal(t, string(marshalledMetadata), r.Form.Get("metadata")) w.Header().Set("content-type", "application/json") fmt.Fprintf(w, `{ "success": true, @@ -231,7 +237,6 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { } actual, err := client.CreateImageDirectUploadURLV2(context.Background(), testAccountID, input) - if assert.NoError(t, err) { assert.Equal(t, want, actual) } From 0d42ec8c812efabdd39812f8198eb5e0f7dacfd1 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Fri, 16 Jun 2023 18:57:40 +0530 Subject: [PATCH 088/130] adds api reference to function comment block --- images.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/images.go b/images.go index 0a7cd3147bb..ed38d9d3ed9 100644 --- a/images.go +++ b/images.go @@ -206,6 +206,8 @@ func (api *API) CreateImageDirectUploadURL(ctx context.Context, accountID string var imagesMultipartBoundary = "----CloudflareImagesGoClientBoundary" // CreateImageDirectUploadURLV2 creates an authenticated v2 direct upload url. +// +// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-create-authenticated-direct-upload-url-v-2 func (api *API) CreateImageDirectUploadURLV2(ctx context.Context, accountID string, params ImageDirectUploadURLV2Request) (ImageDirectUploadURL, error) { uri := fmt.Sprintf("/accounts/%s/images/v2/direct_upload", accountID) From b5d9256bca28a89954d24a967b4a65706ddc5685 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Mon, 26 Jun 2023 11:19:46 -0700 Subject: [PATCH 089/130] changes time.Time and bool struct params to be pointers --- images.go | 6 +++--- images_test.go | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/images.go b/images.go index ed38d9d3ed9..425d51b0b40 100644 --- a/images.go +++ b/images.go @@ -84,9 +84,9 @@ type ImageDirectUploadURLRequest struct { } type ImageDirectUploadURLV2Request struct { - Expiry time.Time `json:"expiry"` + Expiry *time.Time `json:"expiry,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` - RequireSignedURLs bool `json:"requireSignedURLs"` + RequireSignedURLs *bool `json:"requireSignedURLs,omitempty"` } // ImageDirectUploadURLResponse is the API response for a direct image upload url. @@ -214,7 +214,7 @@ func (api *API) CreateImageDirectUploadURLV2(ctx context.Context, accountID stri body := &bytes.Buffer{} writer := multipart.NewWriter(body) writer.SetBoundary(imagesMultipartBoundary) - if params.RequireSignedURLs { + if *params.RequireSignedURLs { writer.WriteField("requireSignedURLs", "true") } if !params.Expiry.IsZero() { diff --git a/images_test.go b/images_test.go index 96c3a751f6b..6bd5eec9068 100644 --- a/images_test.go +++ b/images_test.go @@ -199,10 +199,11 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { "metaKey1": "metaValue1", "metaKey2": "metaValue2", } + requireSignedURLs := true input := ImageDirectUploadURLV2Request{ - Expiry: exp, + Expiry: &exp, Metadata: metadata, - RequireSignedURLs: true, + RequireSignedURLs: &requireSignedURLs, } handler := func(w http.ResponseWriter, r *http.Request) { From aa991622526eb32f3b43a42820c947227d9f90e9 Mon Sep 17 00:00:00 2001 From: Bhavik Shah Date: Wed, 28 Jun 2023 13:55:54 -0700 Subject: [PATCH 090/130] merges v2 impl into v1 and adds resource container for accountID --- cloudflare.go | 10 ++++- errors.go | 2 + images.go | 108 ++++++++++++++++++++++++++----------------------- images_test.go | 10 +++-- 4 files changed, 74 insertions(+), 56 deletions(-) diff --git a/cloudflare.go b/cloudflare.go index 2231bd79f20..a37dc8fac67 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -21,8 +21,16 @@ import ( "golang.org/x/time/rate" ) +type ApiVersion string + +const ( + V1 ApiVersion = "v1" + V2 ApiVersion = "v2" + V4 ApiVersion = "v4" +) + var ( - Version string = "v4" + Version string = string(V4) // Deprecated: Use `client.New` configuration instead. apiURL = fmt.Sprintf("%s://%s%s", defaultScheme, defaultHostname, defaultBasePath) diff --git a/errors.go b/errors.go index 85fdc3efacb..629b3a0a1ba 100644 --- a/errors.go +++ b/errors.go @@ -32,6 +32,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" + errInvalidAPIVersion = "invalid API version" ) var ( @@ -45,6 +46,7 @@ var ( ErrRequiredAccountLevelResourceContainer = errors.New(errRequiredAccountLevelResourceContainer) ErrRequiredZoneLevelResourceContainer = errors.New(errRequiredZoneLevelResourceContainer) + ErrInvalidAPIVersion = errors.New(errInvalidAPIVersion) ) type ErrorType string diff --git a/images.go b/images.go index 425d51b0b40..0ccde0ff094 100644 --- a/images.go +++ b/images.go @@ -80,10 +80,7 @@ type ImageUpdateRequest struct { // ImageDirectUploadURLRequest is the data required for a CreateImageDirectUploadURL request. type ImageDirectUploadURLRequest struct { - Expiry time.Time `json:"expiry"` -} - -type ImageDirectUploadURLV2Request struct { + Version ApiVersion `json:"version"` Expiry *time.Time `json:"expiry,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` RequireSignedURLs *bool `json:"requireSignedURLs,omitempty"` @@ -184,64 +181,73 @@ func (api *API) UpdateImage(ctx context.Context, accountID string, id string, im return imageDetailsResponse.Result, nil } +var imagesMultipartBoundary = "----CloudflareImagesGoClientBoundary" + // CreateImageDirectUploadURL creates an authenticated direct upload url. // // API Reference: https://api.cloudflare.com/#cloudflare-images-create-authenticated-direct-upload-url -func (api *API) CreateImageDirectUploadURL(ctx context.Context, accountID string, params ImageDirectUploadURLRequest) (ImageDirectUploadURL, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1/direct_upload", accountID) - - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) - if err != nil { - return ImageDirectUploadURL{}, err +func (api *API) CreateImageDirectUploadURL(ctx context.Context, rc *ResourceContainer, params ImageDirectUploadURLRequest) (ImageDirectUploadURL, error) { + if rc.Level != AccountRouteLevel { + return ImageDirectUploadURL{}, ErrRequiredAccountLevelResourceContainer } - var imageDirectUploadURLResponse ImageDirectUploadURLResponse - err = json.Unmarshal(res, &imageDirectUploadURLResponse) - if err != nil { - return ImageDirectUploadURL{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + if params.Version != "" && params.Version != V1 && params.Version != V2 { + return ImageDirectUploadURL{}, ErrInvalidAPIVersion } - return imageDirectUploadURLResponse.Result, nil -} -var imagesMultipartBoundary = "----CloudflareImagesGoClientBoundary" - -// CreateImageDirectUploadURLV2 creates an authenticated v2 direct upload url. -// -// API Reference: https://developers.cloudflare.com/api/operations/cloudflare-images-create-authenticated-direct-upload-url-v-2 -func (api *API) CreateImageDirectUploadURLV2(ctx context.Context, accountID string, params ImageDirectUploadURLV2Request) (ImageDirectUploadURL, error) { - uri := fmt.Sprintf("/accounts/%s/images/v2/direct_upload", accountID) + var err error + var uri string + var res []byte + switch params.Version { + case V2: + uri = fmt.Sprintf("/%s/%s/images/%s/direct_upload", rc.Level, rc.Identifier, params.Version) + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + if err := writer.SetBoundary(imagesMultipartBoundary); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error setting multipart boundary") + } - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - writer.SetBoundary(imagesMultipartBoundary) - if *params.RequireSignedURLs { - writer.WriteField("requireSignedURLs", "true") - } - if !params.Expiry.IsZero() { - writer.WriteField("expiry", params.Expiry.Format(time.RFC3339)) - } - if params.Metadata != nil { - metadataBytes, err := json.Marshal(params.Metadata) - if err != nil { - return ImageDirectUploadURL{}, fmt.Errorf("error marshalling metadata to JSON: %w", err) + if *params.RequireSignedURLs { + if err = writer.WriteField("requireSignedURLs", "true"); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error writing requireSignedURLs field: %w", err) + } } - writer.WriteField("metadata", string(metadataBytes)) - } - err := writer.Close() - if err != nil { - return ImageDirectUploadURL{}, fmt.Errorf("error closing multipart writer: %w", err) + if !params.Expiry.IsZero() { + if err = writer.WriteField("expiry", params.Expiry.Format(time.RFC3339)); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error writing expiry field: %w", err) + } + } + if params.Metadata != nil { + var metadataBytes []byte + if metadataBytes, err = json.Marshal(params.Metadata); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error marshalling metadata to JSON: %w", err) + } + if err = writer.WriteField("metadata", string(metadataBytes)); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error writing metadata field: %w", err) + } + } + if err = writer.Close(); err != nil { + return ImageDirectUploadURL{}, fmt.Errorf("error closing multipart writer: %w", err) + } + + res, err = api.makeRequestContextWithHeaders( + ctx, + http.MethodPost, + uri, + body, + http.Header{ + "Accept": []string{"application/json"}, + "Content-Type": []string{writer.FormDataContentType()}, + }, + ) + case V1: + case "": + uri = fmt.Sprintf("/%s/%s/images/%s/direct_upload", rc.Level, rc.Identifier, V1) + res, err = api.makeRequestContext(ctx, http.MethodPost, uri, params) + default: + return ImageDirectUploadURL{}, ErrInvalidAPIVersion } - res, err := api.makeRequestContextWithHeaders( - ctx, - http.MethodPost, - uri, - body, - http.Header{ - "Accept": []string{"application/json"}, - "Content-Type": []string{writer.FormDataContentType()}, - }, - ) if err != nil { return ImageDirectUploadURL{}, err } diff --git a/images_test.go b/images_test.go index 6bd5eec9068..2d4acd2d45c 100644 --- a/images_test.go +++ b/images_test.go @@ -152,8 +152,9 @@ func TestCreateImageDirectUploadURL(t *testing.T) { setup() defer teardown() + expiry := time.Now().UTC().Add(30 * time.Minute) input := ImageDirectUploadURLRequest{ - Expiry: time.Now().UTC().Add(30 * time.Minute), + Expiry: &expiry, } handler := func(w http.ResponseWriter, r *http.Request) { @@ -183,7 +184,7 @@ func TestCreateImageDirectUploadURL(t *testing.T) { UploadURL: "https://upload.imagedelivery.net/fgr33htrthytjtyereifjewoi338272s7w1383", } - actual, err := client.CreateImageDirectUploadURL(context.Background(), testAccountID, input) + actual, err := client.CreateImageDirectUploadURL(context.Background(), AccountIdentifier(testAccountID), input) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -200,7 +201,8 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { "metaKey2": "metaValue2", } requireSignedURLs := true - input := ImageDirectUploadURLV2Request{ + input := ImageDirectUploadURLRequest{ + Version: V2, Expiry: &exp, Metadata: metadata, RequireSignedURLs: &requireSignedURLs, @@ -237,7 +239,7 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { UploadURL: "https://upload.imagedelivery.net/fgr33htrthytjtyereifjewoi338272s7w1383", } - actual, err := client.CreateImageDirectUploadURLV2(context.Background(), testAccountID, input) + actual, err := client.CreateImageDirectUploadURL(context.Background(), AccountIdentifier(testAccountID), input) if assert.NoError(t, err) { assert.Equal(t, want, actual) } From 78d080b8c208f525de6bfbd215cb143443b5a1eb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Jun 2023 13:27:40 +1000 Subject: [PATCH 091/130] scope API version struct to just images we don't really want this concept more broadly so let's limit the exposure of it --- cloudflare.go | 10 +--------- errors.go | 2 -- flox.nix | 25 ++++++++++++++++++++++++- images.go | 13 +++++++++++++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cloudflare.go b/cloudflare.go index a37dc8fac67..2231bd79f20 100644 --- a/cloudflare.go +++ b/cloudflare.go @@ -21,16 +21,8 @@ import ( "golang.org/x/time/rate" ) -type ApiVersion string - -const ( - V1 ApiVersion = "v1" - V2 ApiVersion = "v2" - V4 ApiVersion = "v4" -) - var ( - Version string = string(V4) + Version string = "v4" // Deprecated: Use `client.New` configuration instead. apiURL = fmt.Sprintf("%s://%s%s", defaultScheme, defaultHostname, defaultBasePath) diff --git a/errors.go b/errors.go index 629b3a0a1ba..85fdc3efacb 100644 --- a/errors.go +++ b/errors.go @@ -32,7 +32,6 @@ 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" - errInvalidAPIVersion = "invalid API version" ) var ( @@ -46,7 +45,6 @@ var ( ErrRequiredAccountLevelResourceContainer = errors.New(errRequiredAccountLevelResourceContainer) ErrRequiredZoneLevelResourceContainer = errors.New(errRequiredZoneLevelResourceContainer) - ErrInvalidAPIVersion = errors.New(errInvalidAPIVersion) ) type ErrorType string diff --git a/flox.nix b/flox.nix index 3f82311a7e0..ee6c796476c 100644 --- a/flox.nix +++ b/flox.nix @@ -1,3 +1,26 @@ { - packages.nixpkgs-flox.go_1_20 = { }; + # flox environment + # + # To learn basics about flox commands see: + # https://floxdev.com/docs/basics + # + # Check other options you can configure in this file: + # https://floxdev.com/docs/reference/flox-nix-config + # + # Get help: + # https://discourse.floxdev.com + # + # Happy hacking! + + # Look for more packages with `flox search` command. + #packages.nixpkgs-flox.go = {}; + #packages.nixpkgs-flox.nodejs = {} + + # Set environment variables + environmentVariables.YOLOCOPTER = "jacob"; + + # Run shell hook when you enter flox environment + shell.hook = '' + echo "Welcome to flox environment" + ''; } diff --git a/images.go b/images.go index 0ccde0ff094..2bfc3797c82 100644 --- a/images.go +++ b/images.go @@ -12,6 +12,18 @@ import ( "time" ) +var ( + ErrInvalidImagesAPIVersion = errors.New("invalid images API version") + ErrMissingImageID = errors.New("required image ID missing") +) + +type ImagesAPIVersion string + +const ( + V1 ImagesAPIVersion = "v1" + V2 ImagesAPIVersion = "v2" +) + // Image represents a Cloudflare Image. type Image struct { ID string `json:"id"` @@ -81,6 +93,7 @@ type ImageUpdateRequest struct { // ImageDirectUploadURLRequest is the data required for a CreateImageDirectUploadURL request. type ImageDirectUploadURLRequest struct { Version ApiVersion `json:"version"` + Version ImagesAPIVersion `json:"-"` Expiry *time.Time `json:"expiry,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` RequireSignedURLs *bool `json:"requireSignedURLs,omitempty"` From 192f7d22a7fcbf4f36cc5a21b8bcfe616db7994e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Jun 2023 13:28:05 +1000 Subject: [PATCH 092/130] images: update methods to match library conventions --- .changelog/1308.txt | 30 ++++++++++++- flox.nix | 25 +---------- images.go | 100 ++++++++++++++++++++++++++++---------------- images_test.go | 25 +++++------ 4 files changed, 107 insertions(+), 73 deletions(-) diff --git a/.changelog/1308.txt b/.changelog/1308.txt index 938cec780b8..9f5c710fecb 100644 --- a/.changelog/1308.txt +++ b/.changelog/1308.txt @@ -1,3 +1,31 @@ ```release-note:enhancement -images: adds `CreateImageDirectUploadURLV2` to images API +images: adds support for v2 when uploading images directly +``` + +```release-note:breaking-change +images: updated method signatures of `UploadImage` to match newer conventions and standards +``` + +```release-note:breaking-change +images: updated method signatures of `UpdateImage` to match newer conventions and standards +``` + +```release-note:breaking-change +images: updated method signatures of `ListImages` to match newer conventions and standards +``` + +```release-note:breaking-change +images: updated method signatures of `DeleteImage` to match newer conventions and standards +``` + +```release-note:breaking-change +images: renamed `ImageDetails` to `GetImage` to match library conventions +``` + +```release-note:breaking-change +images: renamed `BaseImage` to `GetBaseImage` to match library conventions +``` + +```release-note:breaking-change +images: renamed `ImagesStats` to `GetImagesStats` to match library conventions ``` diff --git a/flox.nix b/flox.nix index ee6c796476c..3f82311a7e0 100644 --- a/flox.nix +++ b/flox.nix @@ -1,26 +1,3 @@ { - # flox environment - # - # To learn basics about flox commands see: - # https://floxdev.com/docs/basics - # - # Check other options you can configure in this file: - # https://floxdev.com/docs/reference/flox-nix-config - # - # Get help: - # https://discourse.floxdev.com - # - # Happy hacking! - - # Look for more packages with `flox search` command. - #packages.nixpkgs-flox.go = {}; - #packages.nixpkgs-flox.nodejs = {} - - # Set environment variables - environmentVariables.YOLOCOPTER = "jacob"; - - # Run shell hook when you enter flox environment - shell.hook = '' - echo "Welcome to flox environment" - ''; + packages.nixpkgs-flox.go_1_20 = { }; } diff --git a/images.go b/images.go index 2bfc3797c82..b93b2f46de5 100644 --- a/images.go +++ b/images.go @@ -20,8 +20,8 @@ var ( type ImagesAPIVersion string const ( - V1 ImagesAPIVersion = "v1" - V2 ImagesAPIVersion = "v2" + ImagesAPIVersionV1 ImagesAPIVersion = "v1" + ImagesAPIVersionV2 ImagesAPIVersion = "v2" ) // Image represents a Cloudflare Image. @@ -34,8 +34,8 @@ type Image struct { Uploaded time.Time `json:"uploaded"` } -// ImageUploadRequest is the data required for an Image Upload request. -type ImageUploadRequest struct { +// UploadImageParams is the data required for an Image Upload request. +type UploadImageParams struct { File io.ReadCloser Name string RequireSignedURLs bool @@ -44,7 +44,7 @@ type ImageUploadRequest struct { // write writes the image upload data to a multipart writer, so // it can be used in an HTTP request. -func (b ImageUploadRequest) write(mpw *multipart.Writer) error { +func (b UploadImageParams) write(mpw *multipart.Writer) error { if b.File == nil { return errors.New("a file to upload must be specified") } @@ -84,15 +84,15 @@ func (b ImageUploadRequest) write(mpw *multipart.Writer) error { return nil } -// ImageUpdateRequest is the data required for an UpdateImage request. -type ImageUpdateRequest struct { +// UpdateImageParams is the data required for an UpdateImage request. +type UpdateImageParams struct { + ID string `json:"-"` RequireSignedURLs bool `json:"requireSignedURLs"` Metadata map[string]interface{} `json:"metadata,omitempty"` } -// ImageDirectUploadURLRequest is the data required for a CreateImageDirectUploadURL request. -type ImageDirectUploadURLRequest struct { - Version ApiVersion `json:"version"` +// CreateImageDirectUploadURLParams is the data required for a CreateImageDirectUploadURL request. +type CreateImageDirectUploadURLParams struct { Version ImagesAPIVersion `json:"-"` Expiry *time.Time `json:"expiry,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` @@ -139,15 +139,23 @@ type ImagesStatsCount struct { Allowed int64 `json:"allowed"` } +type ListImagesParams struct { + ResultInfo +} + // UploadImage uploads a single image. // // API Reference: https://api.cloudflare.com/#cloudflare-images-upload-an-image-using-a-single-http-request -func (api *API) UploadImage(ctx context.Context, accountID string, upload ImageUploadRequest) (Image, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1", accountID) +func (api *API) UploadImage(ctx context.Context, rc *ResourceContainer, params UploadImageParams) (Image, error) { + if rc.Level != AccountRouteLevel { + return Image{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1", rc.Identifier) body := &bytes.Buffer{} w := multipart.NewWriter(body) - if err := upload.write(w); err != nil { + if err := params.write(w); err != nil { _ = w.Close() return Image{}, fmt.Errorf("error writing multipart body: %w", err) } @@ -178,10 +186,14 @@ func (api *API) UploadImage(ctx context.Context, accountID string, upload ImageU // UpdateImage updates an existing image's metadata. // // API Reference: https://api.cloudflare.com/#cloudflare-images-update-image -func (api *API) UpdateImage(ctx context.Context, accountID string, id string, image ImageUpdateRequest) (Image, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1/%s", accountID, id) +func (api *API) UpdateImage(ctx context.Context, rc *ResourceContainer, params UpdateImageParams) (Image, error) { + if rc.Level != AccountRouteLevel { + return Image{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1/%s", rc.Identifier, params.ID) - res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, image) + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return Image{}, err } @@ -199,20 +211,20 @@ var imagesMultipartBoundary = "----CloudflareImagesGoClientBoundary" // CreateImageDirectUploadURL creates an authenticated direct upload url. // // API Reference: https://api.cloudflare.com/#cloudflare-images-create-authenticated-direct-upload-url -func (api *API) CreateImageDirectUploadURL(ctx context.Context, rc *ResourceContainer, params ImageDirectUploadURLRequest) (ImageDirectUploadURL, error) { +func (api *API) CreateImageDirectUploadURL(ctx context.Context, rc *ResourceContainer, params CreateImageDirectUploadURLParams) (ImageDirectUploadURL, error) { if rc.Level != AccountRouteLevel { return ImageDirectUploadURL{}, ErrRequiredAccountLevelResourceContainer } - if params.Version != "" && params.Version != V1 && params.Version != V2 { - return ImageDirectUploadURL{}, ErrInvalidAPIVersion + if params.Version != "" && params.Version != ImagesAPIVersionV1 && params.Version != ImagesAPIVersionV2 { + return ImageDirectUploadURL{}, ErrInvalidImagesAPIVersion } var err error var uri string var res []byte switch params.Version { - case V2: + case ImagesAPIVersionV2: uri = fmt.Sprintf("/%s/%s/images/%s/direct_upload", rc.Level, rc.Identifier, params.Version) body := &bytes.Buffer{} writer := multipart.NewWriter(body) @@ -253,12 +265,12 @@ func (api *API) CreateImageDirectUploadURL(ctx context.Context, rc *ResourceCont "Content-Type": []string{writer.FormDataContentType()}, }, ) - case V1: + case ImagesAPIVersionV1: case "": - uri = fmt.Sprintf("/%s/%s/images/%s/direct_upload", rc.Level, rc.Identifier, V1) + uri = fmt.Sprintf("/%s/%s/images/%s/direct_upload", rc.Level, rc.Identifier, ImagesAPIVersionV1) res, err = api.makeRequestContext(ctx, http.MethodPost, uri, params) default: - return ImageDirectUploadURL{}, ErrInvalidAPIVersion + return ImageDirectUploadURL{}, ErrInvalidImagesAPIVersion } if err != nil { @@ -276,8 +288,8 @@ func (api *API) CreateImageDirectUploadURL(ctx context.Context, rc *ResourceCont // ListImages lists all images. // // API Reference: https://api.cloudflare.com/#cloudflare-images-list-images -func (api *API) ListImages(ctx context.Context, accountID string, pageOpts PaginationOptions) ([]Image, error) { - uri := buildURI(fmt.Sprintf("/accounts/%s/images/v1", accountID), pageOpts) +func (api *API) ListImages(ctx context.Context, rc *ResourceContainer, params ListImagesParams) ([]Image, error) { + uri := buildURI(fmt.Sprintf("/accounts/%s/images/v1", rc.Identifier), params) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -292,11 +304,15 @@ func (api *API) ListImages(ctx context.Context, accountID string, pageOpts Pagin return imagesListResponse.Result.Images, nil } -// ImageDetails gets the details of an uploaded image. +// GetImage gets the details of an uploaded image. // // API Reference: https://api.cloudflare.com/#cloudflare-images-image-details -func (api *API) ImageDetails(ctx context.Context, accountID string, id string) (Image, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1/%s", accountID, id) +func (api *API) GetImage(ctx context.Context, rc *ResourceContainer, id string) (Image, error) { + if rc.Level != AccountRouteLevel { + return Image{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1/%s", rc.Identifier, id) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -311,11 +327,15 @@ func (api *API) ImageDetails(ctx context.Context, accountID string, id string) ( return imageDetailsResponse.Result, nil } -// BaseImage gets the base image used to derive variants. +// GetBaseImage gets the base image used to derive variants. // // API Reference: https://api.cloudflare.com/#cloudflare-images-base-image -func (api *API) BaseImage(ctx context.Context, accountID string, id string) ([]byte, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1/%s/blob", accountID, id) +func (api *API) GetBaseImage(ctx context.Context, rc *ResourceContainer, id string) ([]byte, error) { + if rc.Level != AccountRouteLevel { + return []byte{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1/%s/blob", rc.Identifier, id) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -327,8 +347,12 @@ func (api *API) BaseImage(ctx context.Context, accountID string, id string) ([]b // DeleteImage deletes an image. // // API Reference: https://api.cloudflare.com/#cloudflare-images-delete-image -func (api *API) DeleteImage(ctx context.Context, accountID string, id string) error { - uri := fmt.Sprintf("/accounts/%s/images/v1/%s", accountID, id) +func (api *API) DeleteImage(ctx context.Context, rc *ResourceContainer, id string) error { + if rc.Level != AccountRouteLevel { + return ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1/%s", rc.Identifier, id) _, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { @@ -337,11 +361,15 @@ func (api *API) DeleteImage(ctx context.Context, accountID string, id string) er return nil } -// ImagesStats gets an account's statistics for Cloudflare Images. +// GetImagesStats gets an account's statistics for Cloudflare Images. // // API Reference: https://api.cloudflare.com/#cloudflare-images-images-usage-statistics -func (api *API) ImagesStats(ctx context.Context, accountID string) (ImagesStatsCount, error) { - uri := fmt.Sprintf("/accounts/%s/images/v1/stats", accountID) +func (api *API) GetImagesStats(ctx context.Context, rc *ResourceContainer) (ImagesStatsCount, error) { + if rc.Level != AccountRouteLevel { + return ImagesStatsCount{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1/stats", rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { diff --git a/images_test.go b/images_test.go index 2d4acd2d45c..e52d6cf0d39 100644 --- a/images_test.go +++ b/images_test.go @@ -80,7 +80,7 @@ func TestUploadImage(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1", handler) want := expectedImageStruct - actual, err := client.UploadImage(context.Background(), testAccountID, ImageUploadRequest{ + actual, err := client.UploadImage(context.Background(), AccountIdentifier(testAccountID), UploadImageParams{ File: fakeFile{ Buffer: bytes.NewBufferString("this is definitely an image"), }, @@ -100,7 +100,8 @@ func TestUpdateImage(t *testing.T) { setup() defer teardown() - input := ImageUpdateRequest{ + input := UpdateImageParams{ + ID: "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", RequireSignedURLs: true, Metadata: map[string]interface{}{ "meta": "metaID", @@ -110,7 +111,7 @@ func TestUpdateImage(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) - var v ImageUpdateRequest + var v UpdateImageParams err := json.NewDecoder(r.Body).Decode(&v) require.NoError(t, err) assert.Equal(t, input, v) @@ -141,7 +142,7 @@ func TestUpdateImage(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/ZxR0pLaXRldlBtaFhhO2FiZGVnaA", handler) want := expectedImageStruct - actual, err := client.UpdateImage(context.Background(), testAccountID, "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", input) + actual, err := client.UpdateImage(context.Background(), AccountIdentifier(testAccountID), input) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -153,14 +154,14 @@ func TestCreateImageDirectUploadURL(t *testing.T) { defer teardown() expiry := time.Now().UTC().Add(30 * time.Minute) - input := ImageDirectUploadURLRequest{ + input := CreateImageDirectUploadURLParams{ Expiry: &expiry, } handler := func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method) - var v ImageDirectUploadURLRequest + var v CreateImageDirectUploadURLParams err := json.NewDecoder(r.Body).Decode(&v) require.NoError(t, err) assert.Equal(t, input, v) @@ -201,8 +202,8 @@ func TestCreateImageDirectUploadURLV2(t *testing.T) { "metaKey2": "metaValue2", } requireSignedURLs := true - input := ImageDirectUploadURLRequest{ - Version: V2, + input := CreateImageDirectUploadURLParams{ + Version: ImagesAPIVersionV2, Expiry: &exp, Metadata: metadata, RequireSignedURLs: &requireSignedURLs, @@ -281,7 +282,7 @@ func TestListImages(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1", handler) want := []Image{expectedImageStruct} - actual, err := client.ListImages(context.Background(), testAccountID, PaginationOptions{}) + actual, err := client.ListImages(context.Background(), AccountIdentifier(testAccountID), ListImagesParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -320,7 +321,7 @@ func TestImageDetails(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/ZxR0pLaXRldlBtaFhhO2FiZGVnaA", handler) want := expectedImageStruct - actual, err := client.ImageDetails(context.Background(), testAccountID, "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") + actual, err := client.GetImage(context.Background(), AccountIdentifier(testAccountID), "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -340,7 +341,7 @@ func TestBaseImage(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/ZxR0pLaXRldlBtaFhhO2FiZGVnaA/blob", handler) want := []byte{} - actual, err := client.BaseImage(context.Background(), testAccountID, "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") + actual, err := client.GetBaseImage(context.Background(), AccountIdentifier(testAccountID), "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") if assert.NoError(t, err) { assert.Equal(t, want, actual) @@ -365,7 +366,7 @@ func TestDeleteImage(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/ZxR0pLaXRldlBtaFhhO2FiZGVnaA", handler) - err := client.DeleteImage(context.Background(), testAccountID, "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") + err := client.DeleteImage(context.Background(), AccountIdentifier(testAccountID), "ZxR0pLaXRldlBtaFhhO2FiZGVnaA") require.NoError(t, err) } From 8f6140d223633374dac6a34f5e24c1fc6df20390 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Jun 2023 13:41:02 +1000 Subject: [PATCH 093/130] update changelog PR entry --- .changelog/{1308.txt => 1322.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1308.txt => 1322.txt} (100%) diff --git a/.changelog/1308.txt b/.changelog/1322.txt similarity index 100% rename from .changelog/1308.txt rename to .changelog/1322.txt From 768c9b2b480630db4ac2a5feda7cb5a8864a35de Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 30 Jun 2023 13:46:03 +1000 Subject: [PATCH 094/130] fix test assertion --- images_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/images_test.go b/images_test.go index e52d6cf0d39..3640d9f3131 100644 --- a/images_test.go +++ b/images_test.go @@ -101,7 +101,6 @@ func TestUpdateImage(t *testing.T) { defer teardown() input := UpdateImageParams{ - ID: "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", RequireSignedURLs: true, Metadata: map[string]interface{}{ "meta": "metaID", @@ -142,7 +141,13 @@ func TestUpdateImage(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1/ZxR0pLaXRldlBtaFhhO2FiZGVnaA", handler) want := expectedImageStruct - actual, err := client.UpdateImage(context.Background(), AccountIdentifier(testAccountID), input) + actual, err := client.UpdateImage(context.Background(), AccountIdentifier(testAccountID), UpdateImageParams{ + ID: "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", + RequireSignedURLs: true, + Metadata: map[string]interface{}{ + "meta": "metaID", + }, + }) if assert.NoError(t, err) { assert.Equal(t, want, actual) From 83a5ba9a62f85ea422eea041299074d6af6c46ed Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 30 Jun 2023 03:49:46 +0000 Subject: [PATCH 095/130] Update CHANGELOG.md for #1322 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d16142f96bd..5b2cb7e2ae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ BREAKING CHANGES: * access_policy: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) * access_service_tokens: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) * access_user_token: refactor methods to use `ResourceContainer` instead of dedicated account/zone methods ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) +* images: renamed `BaseImage` to `GetBaseImage` to match library conventions ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: renamed `ImageDetails` to `GetImage` to match library conventions ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: renamed `ImagesStats` to `GetImagesStats` to match library conventions ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: updated method signatures of `DeleteImage` to match newer conventions and standards ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: updated method signatures of `ListImages` to match newer conventions and standards ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: updated method signatures of `UpdateImage` to match newer conventions and standards ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) +* images: updated method signatures of `UploadImage` to match newer conventions and standards ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) ENHANCEMENTS: @@ -21,6 +28,7 @@ ENHANCEMENTS: * access_mutual_tls_certificates: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) * access_policy: add support for auto pagination ([#1319](https://github.com/cloudflare/cloudflare-go/issues/1319)) * device_posture_rule: support os_version_extra ([#1316](https://github.com/cloudflare/cloudflare-go/issues/1316)) +* images: adds support for v2 when uploading images directly ([#1322](https://github.com/cloudflare/cloudflare-go/issues/1322)) * workers: Add ability to specify tail Workers in script metadata ([#1317](https://github.com/cloudflare/cloudflare-go/issues/1317)) DEPENDENCIES: From 11dabfb748086f1eaa84bc67f5a286e9442782cb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 07:58:45 +1000 Subject: [PATCH 096/130] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b2cb7e2ae6..35062f2ba0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.71.0 (Unreleased) +## 0.72.0 (Unreleased) + +## 0.71.0 (July 5th, 2023) BREAKING CHANGES: From c662bc9eaaf211b01ad459bd2eb0dae16456065e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 08:49:09 +1000 Subject: [PATCH 097/130] Update .goreleaser.yml --- cmd/flarectl/.goreleaser.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cmd/flarectl/.goreleaser.yml b/cmd/flarectl/.goreleaser.yml index 66e94958b83..365e4054a52 100644 --- a/cmd/flarectl/.goreleaser.yml +++ b/cmd/flarectl/.goreleaser.yml @@ -16,13 +16,7 @@ builds: binary: flarectl mod_timestamp: '{{ .CommitTimestamp }}' archives: - - replacements: - darwin: macos - format_overrides: - - goos: windows - format: zip - format: tar.xz - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" + - name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}" checksum: disable: true changelog: From b9ac80404771c061ccb53da6a2e13c41728a1d82 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 12:23:35 +1000 Subject: [PATCH 098/130] resource_container: add explicit `Type` field for `ResourceContainer` Extend the resource container object to have an explicit `Type` instead of inferring/manipulating from the `Level`. --- .changelog/1325.txt | 3 +++ resource.go | 57 +++++++++++++++++++++++++++++++++++++++++---- resource_test.go | 38 ++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 .changelog/1325.txt diff --git a/.changelog/1325.txt b/.changelog/1325.txt new file mode 100644 index 00000000000..0742b1f7fc5 --- /dev/null +++ b/.changelog/1325.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource_container: expose `Type` on `*ResourceContainer` to explicitly denote what type of resource it is instead of inferring from `Level`. +``` diff --git a/resource.go b/resource.go index 481eae25ac7..d7819759307 100644 --- a/resource.go +++ b/resource.go @@ -2,13 +2,30 @@ package cloudflare import "fmt" -// RouteLevel holds the "level" where the resource resides. +// RouteLevel holds the "level" where the resource resides. Commonly used in +// routing configurations or builders. type RouteLevel string +// ResourceType holds the type of the resource. This is similar to `RouteLevel` +// however this is the singular version of `RouteLevel` and isn't suitable for +// use in routing. +type ResourceType string + const ( - AccountRouteLevel RouteLevel = "accounts" - ZoneRouteLevel RouteLevel = "zones" - UserRouteLevel RouteLevel = "user" + user = "user" + zone = "zone" + account = "account" + + zones = zone + "s" + accounts = account + "s" + + AccountRouteLevel RouteLevel = accounts + ZoneRouteLevel RouteLevel = zones + UserRouteLevel RouteLevel = user + + AccountType ResourceType = account + ZoneType ResourceType = zone + UserType ResourceType = user ) // ResourceContainer defines an API resource you wish to target. Should not be @@ -17,6 +34,33 @@ const ( type ResourceContainer struct { Level RouteLevel Identifier string + Type ResourceType +} + +func (r RouteLevel) String() string { + switch r { + case AccountRouteLevel: + return accounts + case ZoneRouteLevel: + return zones + case UserRouteLevel: + return user + default: + return "unknown" + } +} + +func (r ResourceType) String() string { + switch r { + case AccountType: + return account + case ZoneType: + return zone + case UserType: + return user + default: + return "unknown" + } } // Returns a URL fragment of the endpoint scoped by the container. @@ -29,7 +73,7 @@ func (rc *ResourceContainer) URLFragment() string { } if rc.Level == UserRouteLevel { - return "user" + return user } return fmt.Sprintf("%s/%s", rc.Level, rc.Identifier) @@ -47,6 +91,7 @@ func UserIdentifier(id string) *ResourceContainer { return &ResourceContainer{ Level: UserRouteLevel, Identifier: id, + Type: UserType, } } @@ -55,6 +100,7 @@ func ZoneIdentifier(id string) *ResourceContainer { return &ResourceContainer{ Level: ZoneRouteLevel, Identifier: id, + Type: ZoneType, } } @@ -63,5 +109,6 @@ func AccountIdentifier(id string) *ResourceContainer { return &ResourceContainer{ Level: AccountRouteLevel, Identifier: id, + Type: AccountType, } } diff --git a/resource_test.go b/resource_test.go index 0a9e82caa08..ad2e7295a36 100644 --- a/resource_test.go +++ b/resource_test.go @@ -6,6 +6,44 @@ import ( "github.com/stretchr/testify/assert" ) +func TestResourceProperties(t *testing.T) { + testCases := map[string]struct { + container *ResourceContainer + expectedRoute string + expectedType string + expectedIdentifier string + }{ + account: { + container: AccountIdentifier("abcd1234"), + expectedRoute: accounts, + expectedType: account, + expectedIdentifier: "abcd1234", + }, + zone: { + container: ZoneIdentifier("abcd1234"), + expectedRoute: zones, + expectedType: zone, + expectedIdentifier: "abcd1234", + }, + user: { + container: UserIdentifier("abcd1234"), + expectedRoute: user, + expectedType: user, + expectedIdentifier: "abcd1234", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + setup() + defer teardown() + + assert.Equal(t, tc.container.Level.String(), tc.expectedRoute) + assert.Equal(t, tc.container.Type.String(), tc.expectedType) + assert.Equal(t, tc.container.Identifier, tc.expectedIdentifier) + }) + } +} func TestResourcURLFragment(t *testing.T) { tests := map[string]struct { container *ResourceContainer From f1546a977770c70cd841da79b6be29b20a0152f9 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 5 Jul 2023 02:39:08 +0000 Subject: [PATCH 099/130] Update CHANGELOG.md for #1325 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35062f2ba0a..2592bcef70a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.72.0 (Unreleased) +ENHANCEMENTS: + +* resource_container: expose `Type` on `*ResourceContainer` to explicitly denote what type of resource it is instead of inferring from `Level`. ([#1325](https://github.com/cloudflare/cloudflare-go/issues/1325)) + ## 0.71.0 (July 5th, 2023) BREAKING CHANGES: From 978579f535ddf80ec4829c6469281297428155a7 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 13:41:30 +1000 Subject: [PATCH 100/130] logpush: modernise methods Updates the logpush methods to: - Use the newer client method signatures - Remove the duplicate internal methods for account/zone level methods in favour of using `*ResourceContainer` - Stop using `AccessIdentifiers` This introduces a bit more duplication in the `Create`/`Update` methods however it does allow us to handle creation and updates separately explicitly instead of bunching all the logic into a single method with conditionals. --- logpush.go | 421 +++++++++++++++++----------------------- logpush_example_test.go | 60 +++--- logpush_test.go | 32 +-- 3 files changed, 224 insertions(+), 289 deletions(-) diff --git a/logpush.go b/logpush.go index 8b3a70cb1aa..8ddf4c219f4 100644 --- a/logpush.go +++ b/logpush.go @@ -181,6 +181,106 @@ func (f *LogpushJob) UnmarshalJSON(data []byte) error { return nil } +func (f CreateLogpushJobParams) MarshalJSON() ([]byte, error) { + type Alias CreateLogpushJobParams + + var filter string + + if f.Filter != nil { + b, err := json.Marshal(f.Filter) + + if err != nil { + return nil, err + } + + filter = string(b) + } + + return json.Marshal(&struct { + Filter string `json:"filter,omitempty"` + Alias + }{ + Filter: filter, + Alias: (Alias)(f), + }) +} + +// Custom Unmarshaller for CreateLogpushJobParams filter key. +func (f *CreateLogpushJobParams) UnmarshalJSON(data []byte) error { + type Alias CreateLogpushJobParams + aux := &struct { + Filter string `json:"filter,omitempty"` + *Alias + }{ + Alias: (*Alias)(f), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + if aux != nil && aux.Filter != "" { + var filter LogpushJobFilters + if err := json.Unmarshal([]byte(aux.Filter), &filter); err != nil { + return err + } + if err := filter.Where.Validate(); err != nil { + return err + } + f.Filter = &filter + } + return nil +} + +func (f UpdateLogpushJobParams) MarshalJSON() ([]byte, error) { + type Alias UpdateLogpushJobParams + + var filter string + + if f.Filter != nil { + b, err := json.Marshal(f.Filter) + + if err != nil { + return nil, err + } + + filter = string(b) + } + + return json.Marshal(&struct { + Filter string `json:"filter,omitempty"` + Alias + }{ + Filter: filter, + Alias: (Alias)(f), + }) +} + +// Custom Unmarshaller for UpdateLogpushJobParams filter key. +func (f *UpdateLogpushJobParams) UnmarshalJSON(data []byte) error { + type Alias UpdateLogpushJobParams + aux := &struct { + Filter string `json:"filter,omitempty"` + *Alias + }{ + Alias: (*Alias)(f), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + if aux != nil && aux.Filter != "" { + var filter LogpushJobFilters + if err := json.Unmarshal([]byte(aux.Filter), &filter); err != nil { + return err + } + if err := filter.Where.Validate(); err != nil { + return err + } + f.Filter = &filter + } + return nil +} + func (filter *LogpushJobFilter) Validate() error { if filter.And != nil { if filter.Or != nil || filter.Key != "" || filter.Operator != "" || filter.Value != nil { @@ -221,33 +321,66 @@ func (filter *LogpushJobFilter) Validate() error { return nil } -// CreateAccountLogpushJob creates a new account-level Logpush Job. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-create-logpush-job -func (api *API) CreateAccountLogpushJob(ctx context.Context, accountID string, job LogpushJob) (*LogpushJob, error) { - return api.createLogpushJob(ctx, AccountRouteRoot, accountID, job) +type CreateLogpushJobParams struct { + 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"` + 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"` } -// CreateZoneLogpushJob creates a new zone-level Logpush Job. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-create-logpush-job -func (api *API) CreateZoneLogpushJob(ctx context.Context, zoneID string, job LogpushJob) (*LogpushJob, error) { - return api.createLogpushJob(ctx, ZoneRouteRoot, zoneID, job) +type ListLogpushJobsParams struct{} + +type ListLogpushJobsForDatasetParams struct { + Dataset string `json:"-"` +} + +type GetLogpushFieldsParams struct { + Dataset string `json:"-"` +} + +type UpdateLogpushJobParams struct { + ID int `json:"-"` + 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 ValidateLogpushOwnershipChallengeParams struct { + DestinationConf string `json:"destination_conf"` + OwnershipChallenge string `json:"ownership_challenge"` +} + +type GetLogpushOwnershipChallengeParams struct { + DestinationConf string `json:"destination_conf"` } // CreateLogpushJob creates a new zone-level Logpush Job. // // API reference: https://api.cloudflare.com/#logpush-jobs-create-logpush-job -// -// Deprecated: Use `CreateZoneLogpushJob` or `CreateAccountLogpushJob` depending -// on the desired resource to target. -func (api *API) CreateLogpushJob(ctx context.Context, zoneID string, job LogpushJob) (*LogpushJob, error) { - return api.createLogpushJob(ctx, ZoneRouteRoot, zoneID, job) -} - -func (api *API) createLogpushJob(ctx context.Context, identifierType RouteRoot, identifier string, job LogpushJob) (*LogpushJob, error) { - uri := fmt.Sprintf("/%s/%s/logpush/jobs", identifierType, identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, job) +func (api *API) CreateLogpushJob(ctx context.Context, rc *ResourceContainer, params CreateLogpushJobParams) (*LogpushJob, error) { + uri := fmt.Sprintf("/%s/%s/logpush/jobs", rc.Level, rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return nil, err } @@ -259,32 +392,11 @@ func (api *API) createLogpushJob(ctx context.Context, identifierType RouteRoot, return &r.Result, nil } -// ListAccountLogpushJobs returns all account-level Logpush Jobs for all datasets. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -func (api *API) ListAccountLogpushJobs(ctx context.Context, accountID string) ([]LogpushJob, error) { - return api.listLogpushJobs(ctx, AccountRouteRoot, accountID) -} - -// ListZoneLogpushJobs returns all zone-level Logpush Jobs for all datasets. +// ListAccountLogpushJobs returns all Logpush Jobs for all datasets. // // API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -func (api *API) ListZoneLogpushJobs(ctx context.Context, zoneID string) ([]LogpushJob, error) { - return api.listLogpushJobs(ctx, ZoneRouteRoot, zoneID) -} - -// LogpushJobs returns all zone-level Logpush Jobs for all datasets. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -// -// Deprecated: Use `ListZoneLogpushJobs` or `ListAccountLogpushJobs` -// depending on the desired resource to target. -func (api *API) LogpushJobs(ctx context.Context, zoneID string) ([]LogpushJob, error) { - return api.listLogpushJobs(ctx, ZoneRouteRoot, zoneID) -} - -func (api *API) listLogpushJobs(ctx context.Context, identifierType RouteRoot, identifier string) ([]LogpushJob, error) { - uri := fmt.Sprintf("/%s/%s/logpush/jobs", identifierType, identifier) +func (api *API) ListLogpushJobs(ctx context.Context, rc *ResourceContainer, params ListLogpushJobsParams) ([]LogpushJob, error) { + uri := fmt.Sprintf("/%s/%s/logpush/jobs", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []LogpushJob{}, err @@ -297,33 +409,11 @@ func (api *API) listLogpushJobs(ctx context.Context, identifierType RouteRoot, i return r.Result, nil } -// ListAccountLogpushJobsForDataset returns all account-level Logpush Jobs for a dataset. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs-for-a-dataset -func (api *API) ListAccountLogpushJobsForDataset(ctx context.Context, accountID, dataset string) ([]LogpushJob, error) { - return api.listLogpushJobsForDataset(ctx, AccountRouteRoot, accountID, dataset) -} - -// ListZoneLogpushJobsForDataset returns all zone-level Logpush Jobs for a dataset. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs-for-a-dataset -func (api *API) ListZoneLogpushJobsForDataset(ctx context.Context, zoneID, dataset string) ([]LogpushJob, error) { - return api.listLogpushJobsForDataset(ctx, ZoneRouteRoot, zoneID, dataset) -} - -// LogpushJobsForDataset returns all zone-level Logpush Jobs for a dataset. +// LogpushJobsForDataset returns all Logpush Jobs for a dataset. // // API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs-for-a-dataset -// -// Deprecated: Use `ListZoneLogpushJobsForDataset` or -// `ListAccountLogpushJobsForDataset` depending on the desired resource -// to target. -func (api *API) LogpushJobsForDataset(ctx context.Context, zoneID, dataset string) ([]LogpushJob, error) { - return api.listLogpushJobsForDataset(ctx, ZoneRouteRoot, zoneID, dataset) -} - -func (api *API) listLogpushJobsForDataset(ctx context.Context, identifierType RouteRoot, identifier, dataset string) ([]LogpushJob, error) { - uri := fmt.Sprintf("/%s/%s/logpush/datasets/%s/jobs", identifierType, identifier, dataset) +func (api *API) ListLogpushJobsForDataset(ctx context.Context, rc *ResourceContainer, params ListLogpushJobsForDatasetParams) ([]LogpushJob, error) { + uri := fmt.Sprintf("/%s/%s/logpush/datasets/%s/jobs", rc.Level, rc.Identifier, params.Dataset) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return []LogpushJob{}, err @@ -336,36 +426,11 @@ func (api *API) listLogpushJobsForDataset(ctx context.Context, identifierType Ro return r.Result, nil } -// GetAccountLogpushFields returns fields for a given account-level dataset. -// -// Account fields documentation: https://developers.cloudflare.com/logs/reference/log-fields/account -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -func (api *API) GetAccountLogpushFields(ctx context.Context, accountID, dataset string) (LogpushFields, error) { - return api.getLogpushFields(ctx, AccountRouteRoot, accountID, dataset) -} - -// GetZoneLogpushFields returns fields for a given zone-level dataset. -// -// Zone fields documentation: https://developers.cloudflare.com/logs/reference/log-fields/zone -// -// API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -func (api *API) GetZoneLogpushFields(ctx context.Context, zoneID, dataset string) (LogpushFields, error) { - return api.getLogpushFields(ctx, ZoneRouteRoot, zoneID, dataset) -} - // LogpushFields returns fields for a given dataset. // // API reference: https://api.cloudflare.com/#logpush-jobs-list-logpush-jobs -// -// Deprecated: Use `GetZoneLogpushFields` or `GetAccountLogpushFields` -// depending on the desired resource to target. -func (api *API) LogpushFields(ctx context.Context, zoneID, dataset string) (LogpushFields, error) { - return api.getLogpushFields(ctx, ZoneRouteRoot, zoneID, dataset) -} - -func (api *API) getLogpushFields(ctx context.Context, identifierType RouteRoot, identifier, dataset string) (LogpushFields, error) { - uri := fmt.Sprintf("/%s/%s/logpush/datasets/%s/fields", identifierType, identifier, dataset) +func (api *API) GetLogpushFields(ctx context.Context, rc *ResourceContainer, params GetLogpushFieldsParams) (LogpushFields, error) { + uri := fmt.Sprintf("/%s/%s/logpush/datasets/%s/fields", rc.Level, rc.Identifier, params.Dataset) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return LogpushFields{}, err @@ -378,32 +443,11 @@ func (api *API) getLogpushFields(ctx context.Context, identifierType RouteRoot, return r.Result, nil } -// GetAccountLogpushJob fetches detail about one account-level Logpush Job. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-logpush-job-details -func (api *API) GetAccountLogpushJob(ctx context.Context, accountID string, jobID int) (LogpushJob, error) { - return api.getLogpushJob(ctx, AccountRouteRoot, accountID, jobID) -} - -// GetZoneLogpushJob fetches detail about one Logpush Job for a zone. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-logpush-job-details -func (api *API) GetZoneLogpushJob(ctx context.Context, zoneID string, jobID int) (LogpushJob, error) { - return api.getLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID) -} - // LogpushJob fetches detail about one Logpush Job for a zone. // // API reference: https://api.cloudflare.com/#logpush-jobs-logpush-job-details -// -// Deprecated: Use `GetZoneLogpushJob` or `GetAccountLogpushJob` -// depending on the desired resource to target. -func (api *API) LogpushJob(ctx context.Context, zoneID string, jobID int) (LogpushJob, error) { - return api.getLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID) -} - -func (api *API) getLogpushJob(ctx context.Context, identifierType RouteRoot, identifier string, jobID int) (LogpushJob, error) { - uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", identifierType, identifier, jobID) +func (api *API) GetLogpushJob(ctx context.Context, rc *ResourceContainer, jobID int) (LogpushJob, error) { + uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", rc.Level, rc.Identifier, jobID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return LogpushJob{}, err @@ -416,33 +460,12 @@ func (api *API) getLogpushJob(ctx context.Context, identifierType RouteRoot, ide return r.Result, nil } -// UpdateAccountLogpushJob lets you update an account-level Logpush Job. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-update-logpush-job -func (api *API) UpdateAccountLogpushJob(ctx context.Context, accountID string, jobID int, job LogpushJob) error { - return api.updateLogpushJob(ctx, AccountRouteRoot, accountID, jobID, job) -} - -// UpdateZoneLogpushJob lets you update a Logpush Job for a zone. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-update-logpush-job -func (api *API) UpdateZoneLogpushJob(ctx context.Context, zoneID string, jobID int, job LogpushJob) error { - return api.updateLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID, job) -} - // UpdateLogpushJob lets you update a Logpush Job. // // API reference: https://api.cloudflare.com/#logpush-jobs-update-logpush-job -// -// Deprecated: Use `UpdateZoneLogpushJob` or `UpdateAccountLogpushJob` -// depending on the desired resource to target. -func (api *API) UpdateLogpushJob(ctx context.Context, zoneID string, jobID int, job LogpushJob) error { - return api.updateLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID, job) -} - -func (api *API) updateLogpushJob(ctx context.Context, identifierType RouteRoot, identifier string, jobID int, job LogpushJob) error { - uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", identifierType, identifier, jobID) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, job) +func (api *API) UpdateLogpushJob(ctx context.Context, rc *ResourceContainer, params UpdateLogpushJobParams) error { + uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", rc.Level, rc.Identifier, params.ID) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return err } @@ -454,32 +477,11 @@ func (api *API) updateLogpushJob(ctx context.Context, identifierType RouteRoot, return nil } -// DeleteAccountLogpushJob deletes an account-level Logpush Job. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-delete-logpush-job -func (api *API) DeleteAccountLogpushJob(ctx context.Context, accountID string, jobID int) error { - return api.deleteLogpushJob(ctx, AccountRouteRoot, accountID, jobID) -} - -// DeleteZoneLogpushJob deletes a Logpush Job for a zone. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-delete-logpush-job -func (api *API) DeleteZoneLogpushJob(ctx context.Context, zoneID string, jobID int) error { - return api.deleteLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID) -} - // DeleteLogpushJob deletes a Logpush Job for a zone. // // API reference: https://api.cloudflare.com/#logpush-jobs-delete-logpush-job -// -// Deprecated: Use `DeleteZoneLogpushJob` or `DeleteAccountLogpushJob` -// depending on the desired resource to target. -func (api *API) DeleteLogpushJob(ctx context.Context, zoneID string, jobID int) error { - return api.deleteLogpushJob(ctx, ZoneRouteRoot, zoneID, jobID) -} - -func (api *API) deleteLogpushJob(ctx context.Context, identifierType RouteRoot, identifier string, jobID int) error { - uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", identifierType, identifier, jobID) +func (api *API) DeleteLogpushJob(ctx context.Context, rc *ResourceContainer, jobID int) error { + uri := fmt.Sprintf("/%s/%s/logpush/jobs/%d", rc.Level, rc.Identifier, jobID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err @@ -492,36 +494,12 @@ func (api *API) deleteLogpushJob(ctx context.Context, identifierType RouteRoot, return nil } -// GetAccountLogpushOwnershipChallenge returns ownership challenge. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-get-ownership-challenge -func (api *API) GetAccountLogpushOwnershipChallenge(ctx context.Context, accountID, destinationConf string) (*LogpushGetOwnershipChallenge, error) { - return api.getLogpushOwnershipChallenge(ctx, AccountRouteRoot, accountID, destinationConf) -} - -// GetZoneLogpushOwnershipChallenge returns ownership challenge. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-get-ownership-challenge -func (api *API) GetZoneLogpushOwnershipChallenge(ctx context.Context, zoneID, destinationConf string) (*LogpushGetOwnershipChallenge, error) { - return api.getLogpushOwnershipChallenge(ctx, ZoneRouteRoot, zoneID, destinationConf) -} - // GetLogpushOwnershipChallenge returns ownership challenge. // // API reference: https://api.cloudflare.com/#logpush-jobs-get-ownership-challenge -// -// Deprecated: Use `GetZoneLogpushOwnershipChallenge` or -// `GetAccountLogpushOwnershipChallenge` depending on the -// desired resource to target. -func (api *API) GetLogpushOwnershipChallenge(ctx context.Context, zoneID, destinationConf string) (*LogpushGetOwnershipChallenge, error) { - return api.getLogpushOwnershipChallenge(ctx, ZoneRouteRoot, zoneID, destinationConf) -} - -func (api *API) getLogpushOwnershipChallenge(ctx context.Context, identifierType RouteRoot, identifier, destinationConf string) (*LogpushGetOwnershipChallenge, error) { - uri := fmt.Sprintf("/%s/%s/logpush/ownership", identifierType, identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, LogpushGetOwnershipChallengeRequest{ - DestinationConf: destinationConf, - }) +func (api *API) GetLogpushOwnershipChallenge(ctx context.Context, rc *ResourceContainer, params GetLogpushOwnershipChallengeParams) (*LogpushGetOwnershipChallenge, error) { + uri := fmt.Sprintf("/%s/%s/logpush/ownership", rc.Level, rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return nil, err } @@ -538,37 +516,12 @@ func (api *API) getLogpushOwnershipChallenge(ctx context.Context, identifierType return &r.Result, nil } -// ValidateAccountLogpushOwnershipChallenge returns account-level ownership challenge validation result. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-validate-ownership-challenge -func (api *API) ValidateAccountLogpushOwnershipChallenge(ctx context.Context, accountID, destinationConf, ownershipChallenge string) (bool, error) { - return api.validateLogpushOwnershipChallenge(ctx, AccountRouteRoot, accountID, destinationConf, ownershipChallenge) -} - -// ValidateZoneLogpushOwnershipChallenge returns zone-level ownership challenge validation result. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-validate-ownership-challenge -func (api *API) ValidateZoneLogpushOwnershipChallenge(ctx context.Context, zoneID, destinationConf, ownershipChallenge string) (bool, error) { - return api.validateLogpushOwnershipChallenge(ctx, ZoneRouteRoot, zoneID, destinationConf, ownershipChallenge) -} - // ValidateLogpushOwnershipChallenge returns zone-level ownership challenge validation result. // // API reference: https://api.cloudflare.com/#logpush-jobs-validate-ownership-challenge -// -// Deprecated: Use `ValidateZoneLogpushOwnershipChallenge` or -// `ValidateAccountLogpushOwnershipChallenge` depending on the -// desired resource to target. -func (api *API) ValidateLogpushOwnershipChallenge(ctx context.Context, zoneID, destinationConf, ownershipChallenge string) (bool, error) { - return api.validateLogpushOwnershipChallenge(ctx, ZoneRouteRoot, zoneID, destinationConf, ownershipChallenge) -} - -func (api *API) validateLogpushOwnershipChallenge(ctx context.Context, identifierType RouteRoot, identifier, destinationConf, ownershipChallenge string) (bool, error) { - uri := fmt.Sprintf("/%s/%s/logpush/ownership/validate", identifierType, identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, LogpushValidateOwnershipChallengeRequest{ - DestinationConf: destinationConf, - OwnershipChallenge: ownershipChallenge, - }) +func (api *API) ValidateLogpushOwnershipChallenge(ctx context.Context, rc *ResourceContainer, params ValidateLogpushOwnershipChallengeParams) (bool, error) { + uri := fmt.Sprintf("/%s/%s/logpush/ownership/validate", rc.Level, rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return false, err } @@ -580,33 +533,11 @@ func (api *API) validateLogpushOwnershipChallenge(ctx context.Context, identifie return r.Result.Valid, nil } -// CheckAccountLogpushDestinationExists returns account-level destination exists check result. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-check-destination-exists -func (api *API) CheckAccountLogpushDestinationExists(ctx context.Context, accountID, destinationConf string) (bool, error) { - return api.checkLogpushDestinationExists(ctx, AccountRouteRoot, accountID, destinationConf) -} - -// CheckZoneLogpushDestinationExists returns zone-level destination exists check result. -// -// API reference: https://api.cloudflare.com/#logpush-jobs-check-destination-exists -func (api *API) CheckZoneLogpushDestinationExists(ctx context.Context, zoneID, destinationConf string) (bool, error) { - return api.checkLogpushDestinationExists(ctx, ZoneRouteRoot, zoneID, destinationConf) -} - // CheckLogpushDestinationExists returns zone-level destination exists check result. // // API reference: https://api.cloudflare.com/#logpush-jobs-check-destination-exists -// -// Deprecated: Use `CheckZoneLogpushDestinationExists` or -// `CheckAccountLogpushDestinationExists` depending -// on the desired resource to target. -func (api *API) CheckLogpushDestinationExists(ctx context.Context, zoneID, destinationConf string) (bool, error) { - return api.checkLogpushDestinationExists(ctx, ZoneRouteRoot, zoneID, destinationConf) -} - -func (api *API) checkLogpushDestinationExists(ctx context.Context, identifierType RouteRoot, identifier, destinationConf string) (bool, error) { - uri := fmt.Sprintf("/%s/%s/logpush/validate/destination/exists", identifierType, identifier) +func (api *API) CheckLogpushDestinationExists(ctx context.Context, rc *ResourceContainer, destinationConf string) (bool, error) { + uri := fmt.Sprintf("/%s/%s/logpush/validate/destination/exists", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodPost, uri, LogpushDestinationExistsRequest{ DestinationConf: destinationConf, }) diff --git a/logpush_example_test.go b/logpush_example_test.go index cfeb0e86821..f45b3281a4e 100644 --- a/logpush_example_test.go +++ b/logpush_example_test.go @@ -9,21 +9,7 @@ import ( cloudflare "github.com/cloudflare/cloudflare-go" ) -var exampleNewLogpushJob = cloudflare.LogpushJob{ - Enabled: false, - Name: "example.com", - LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp×tamps=rfc3339", - DestinationConf: "s3://mybucket/logs?region=us-west-2", -} - -var exampleUpdatedLogpushJob = cloudflare.LogpushJob{ - Enabled: true, - Name: "updated.com", - LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp", - DestinationConf: "gs://mybucket/logs", -} - -func ExampleAPI_CreateZoneLogpushJob() { +func ExampleAPI_CreateLogpushJob() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -34,7 +20,12 @@ func ExampleAPI_CreateZoneLogpushJob() { log.Fatal(err) } - job, err := api.CreateZoneLogpushJob(context.Background(), zoneID, exampleNewLogpushJob) + job, err := api.CreateLogpushJob(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.CreateLogpushJobParams{ + Enabled: false, + Name: "example.com", + LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp×tamps=rfc3339", + DestinationConf: "s3://mybucket/logs?region=us-west-2", + }) if err != nil { log.Fatal(err) } @@ -42,7 +33,7 @@ func ExampleAPI_CreateZoneLogpushJob() { fmt.Printf("%+v\n", job) } -func ExampleAPI_UpdateZoneLogpushJob() { +func ExampleAPI_UpdateLogpushJob() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -53,13 +44,19 @@ func ExampleAPI_UpdateZoneLogpushJob() { log.Fatal(err) } - err = api.UpdateZoneLogpushJob(context.Background(), zoneID, 1, exampleUpdatedLogpushJob) + err = api.UpdateLogpushJob(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.UpdateLogpushJobParams{ + ID: 1, + Enabled: true, + Name: "updated.com", + LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp", + DestinationConf: "gs://mybucket/logs", + }) if err != nil { log.Fatal(err) } } -func ExampleAPI_ListZoneLogpushJobs() { +func ExampleAPI_ListLogpushJobs() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -70,7 +67,7 @@ func ExampleAPI_ListZoneLogpushJobs() { log.Fatal(err) } - jobs, err := api.ListZoneLogpushJobs(context.Background(), zoneID) + jobs, err := api.ListLogpushJobs(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListLogpushJobsParams{}) if err != nil { log.Fatal(err) } @@ -81,7 +78,7 @@ func ExampleAPI_ListZoneLogpushJobs() { } } -func ExampleAPI_GetZoneLogpushJob() { +func ExampleAPI_GetLogpushJob() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -92,7 +89,7 @@ func ExampleAPI_GetZoneLogpushJob() { log.Fatal(err) } - job, err := api.GetZoneLogpushJob(context.Background(), zoneID, 1) + job, err := api.GetLogpushJob(context.Background(), cloudflare.ZoneIdentifier(zoneID), 1) if err != nil { log.Fatal(err) } @@ -100,7 +97,7 @@ func ExampleAPI_GetZoneLogpushJob() { fmt.Printf("%+v\n", job) } -func ExampleAPI_DeleteZoneLogpushJob() { +func ExampleAPI_DeleteLogpushJob() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -111,13 +108,13 @@ func ExampleAPI_DeleteZoneLogpushJob() { log.Fatal(err) } - err = api.DeleteZoneLogpushJob(context.Background(), zoneID, 1) + err = api.DeleteLogpushJob(context.Background(), cloudflare.ZoneIdentifier(zoneID), 1) if err != nil { log.Fatal(err) } } -func ExampleAPI_GetZoneLogpushOwnershipChallenge() { +func ExampleAPI_GetLogpushOwnershipChallenge() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -128,7 +125,7 @@ func ExampleAPI_GetZoneLogpushOwnershipChallenge() { log.Fatal(err) } - ownershipChallenge, err := api.GetZoneLogpushOwnershipChallenge(context.Background(), zoneID, "destination_conf") + ownershipChallenge, err := api.GetLogpushOwnershipChallenge(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.GetLogpushOwnershipChallengeParams{DestinationConf: "destination_conf"}) if err != nil { log.Fatal(err) } @@ -136,7 +133,7 @@ func ExampleAPI_GetZoneLogpushOwnershipChallenge() { fmt.Printf("%+v\n", ownershipChallenge) } -func ExampleAPI_ValidateZoneLogpushOwnershipChallenge() { +func ExampleAPI_ValidateLogpushOwnershipChallenge() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -147,7 +144,10 @@ func ExampleAPI_ValidateZoneLogpushOwnershipChallenge() { log.Fatal(err) } - isValid, err := api.ValidateZoneLogpushOwnershipChallenge(context.Background(), zoneID, "destination_conf", "ownership_challenge") + isValid, err := api.ValidateLogpushOwnershipChallenge(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ValidateLogpushOwnershipChallengeParams{ + DestinationConf: "destination_conf", + OwnershipChallenge: "ownership_challenge", + }) if err != nil { log.Fatal(err) } @@ -155,7 +155,7 @@ func ExampleAPI_ValidateZoneLogpushOwnershipChallenge() { fmt.Printf("%+v\n", isValid) } -func ExampleAPI_CheckZoneLogpushDestinationExists() { +func ExampleAPI_CheckLogpushDestinationExists() { api, err := cloudflare.New(apiKey, user) if err != nil { log.Fatal(err) @@ -166,7 +166,7 @@ func ExampleAPI_CheckZoneLogpushDestinationExists() { log.Fatal(err) } - exists, err := api.CheckZoneLogpushDestinationExists(context.Background(), zoneID, "destination_conf") + exists, err := api.CheckLogpushDestinationExists(context.Background(), cloudflare.ZoneIdentifier(zoneID), "destination_conf") if err != nil { log.Fatal(err) } diff --git a/logpush_test.go b/logpush_test.go index c68e3b18b75..4585b9a40c6 100644 --- a/logpush_test.go +++ b/logpush_test.go @@ -122,7 +122,7 @@ func TestLogpushJobs(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/jobs", handler) want := []LogpushJob{expectedLogpushJobStruct} - actual, err := client.ListZoneLogpushJobs(context.Background(), testZoneID) + actual, err := client.ListLogpushJobs(context.Background(), ZoneIdentifier(testZoneID), ListLogpushJobsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -162,7 +162,7 @@ func TestGetLogpushJob(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/jobs/"+strconv.Itoa(jobID), handler) - actual, err := client.GetZoneLogpushJob(context.Background(), testZoneID, jobID) + actual, err := client.GetLogpushJob(context.Background(), ZoneIdentifier(testZoneID), jobID) if assert.NoError(t, err) { assert.Equal(t, tc.want, actual) } @@ -172,13 +172,13 @@ func TestGetLogpushJob(t *testing.T) { func TestCreateLogpushJob(t *testing.T) { testCases := map[string]struct { - newJob LogpushJob + newJob CreateLogpushJobParams payload string result string want LogpushJob }{ "core logpush job": { - newJob: LogpushJob{ + newJob: CreateLogpushJobParams{ Dataset: "http_requests", Enabled: false, Name: "example.com", @@ -198,7 +198,7 @@ func TestCreateLogpushJob(t *testing.T) { want: expectedLogpushJobStruct, }, "edge logpush job": { - newJob: LogpushJob{ + newJob: CreateLogpushJobParams{ Dataset: "http_requests", Enabled: true, Name: "example.com", @@ -218,7 +218,7 @@ func TestCreateLogpushJob(t *testing.T) { want: expectedEdgeLogpushJobStruct, }, "filtered edge logpush job": { - newJob: LogpushJob{ + newJob: CreateLogpushJobParams{ Dataset: "http_requests", Enabled: true, Name: "example.com", @@ -269,7 +269,7 @@ func TestCreateLogpushJob(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/jobs", handler) - actual, err := client.CreateZoneLogpushJob(context.Background(), testZoneID, tc.newJob) + actual, err := client.CreateLogpushJob(context.Background(), ZoneIdentifier(testZoneID), tc.newJob) if assert.NoError(t, err) { assert.Equal(t, tc.want, *actual) } @@ -280,7 +280,8 @@ func TestCreateLogpushJob(t *testing.T) { func TestUpdateLogpushJob(t *testing.T) { setup() defer teardown() - updatedJob := LogpushJob{ + updatedJob := UpdateLogpushJobParams{ + ID: jobID, Enabled: true, Name: "updated.com", LogpullOptions: "fields=RayID,ClientIP,EdgeStartTimestamp", @@ -301,7 +302,7 @@ func TestUpdateLogpushJob(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/jobs/"+strconv.Itoa(jobID), handler) - err := client.UpdateLogpushJob(context.Background(), testZoneID, jobID, updatedJob) + err := client.UpdateLogpushJob(context.Background(), ZoneIdentifier(testZoneID), updatedJob) assert.NoError(t, err) } @@ -323,7 +324,7 @@ func TestDeleteLogpushJob(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/jobs/"+strconv.Itoa(jobID), handler) - err := client.DeleteZoneLogpushJob(context.Background(), testZoneID, jobID) + err := client.DeleteLogpushJob(context.Background(), ZoneIdentifier(testZoneID), jobID) assert.NoError(t, err) } @@ -347,7 +348,7 @@ func TestGetLogpushOwnershipChallenge(t *testing.T) { want := &expectedLogpushGetOwnershipChallengeStruct - actual, err := client.GetZoneLogpushOwnershipChallenge(context.Background(), testZoneID, "destination_conf") + actual, err := client.GetLogpushOwnershipChallenge(context.Background(), ZoneIdentifier(testZoneID), GetLogpushOwnershipChallengeParams{DestinationConf: "destination_conf"}) if assert.NoError(t, err) { assert.Equal(t, want, actual) } @@ -370,7 +371,7 @@ func TestGetLogpushOwnershipChallengeWithInvalidResponse(t *testing.T) { } mux.HandleFunc("/zones/"+testZoneID+"/logpush/ownership", handler) - _, err := client.GetZoneLogpushOwnershipChallenge(context.Background(), testZoneID, "destination_conf") + _, err := client.GetLogpushOwnershipChallenge(context.Background(), ZoneIdentifier(testZoneID), GetLogpushOwnershipChallengeParams{DestinationConf: "destination_conf"}) assert.Error(t, err) } @@ -408,7 +409,10 @@ func TestValidateLogpushOwnershipChallenge(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/ownership/validate", handler) - actual, err := client.ValidateZoneLogpushOwnershipChallenge(context.Background(), testZoneID, "destination_conf", "ownership_challenge") + actual, err := client.ValidateLogpushOwnershipChallenge(context.Background(), ZoneIdentifier(testZoneID), ValidateLogpushOwnershipChallengeParams{ + DestinationConf: "destination_conf", + OwnershipChallenge: "ownership_challenge", + }) if assert.NoError(t, err) { assert.Equal(t, tc.isValid, actual) } @@ -449,7 +453,7 @@ func TestCheckLogpushDestinationExists(t *testing.T) { mux.HandleFunc("/zones/"+testZoneID+"/logpush/validate/destination/exists", handler) - actual, err := client.CheckZoneLogpushDestinationExists(context.Background(), testZoneID, "destination_conf") + actual, err := client.CheckLogpushDestinationExists(context.Background(), ZoneIdentifier(testZoneID), "destination_conf") if assert.NoError(t, err) { assert.Equal(t, tc.exists, actual) } From 0a58e188b30359b1c74d9457613a25a57708de61 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 13:41:49 +1000 Subject: [PATCH 101/130] access_policy: update more references and method signatures --- .changelog/1326.txt | 83 +++++++++++++++++++++++++++++++++++++++++++ access_policy.go | 38 +++++++++++++++++--- access_policy_test.go | 38 +++++++++++++++++--- 3 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 .changelog/1326.txt diff --git a/.changelog/1326.txt b/.changelog/1326.txt new file mode 100644 index 00000000000..fd85096d056 --- /dev/null +++ b/.changelog/1326.txt @@ -0,0 +1,83 @@ +```release-note:breaking-change +logpush: all methods are updated to use the newer client conventions for method signatures +``` + +```release-note:breaking-change +logpush: `CreateAccountLogpushJob` is removed in favour of `CreateLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `CreateZoneLogpushJob` is removed in favour of `CreateLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ListAccountLogpushJobs` is removed in favour of `ListLogpushJobs` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ListZoneLogpushJobs` is removed in favour of `ListLogpushJobs` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ListAccountLogpushJobsForDataset` is removed in favour of `ListLogpushJobsForDataset` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ListZoneLogpushJobsForDataset` is removed in favour of `ListLogpushJobsForDataset` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetAccountLogpushFields` is removed in favour of `GetLogpushFields` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetZoneLogpushFields` is removed in favour of `GetLogpushFields` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetAccountLogpushJob` is removed in favour of `GetLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetZoneLogpushJob` is removed in favour of `GetLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `UpdateAccountLogpushJob` is removed in favour of `UpdateLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `UpdateZoneLogpushJob` is removed in favour of `UpdateLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `DeleteAccountLogpushJob` is removed in favour of `DeleteLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `DeleteZoneLogpushJob` is removed in favour of `DeleteLogpushJob` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetAccountLogpushOwnershipChallenge` is removed in favour of `GetLogpushOwnershipChallenge` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `GetZoneLogpushOwnershipChallenge` is removed in favour of `GetLogpushOwnershipChallenge` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ValidateAccountLogpushOwnershipChallenge` is removed in favour of `ValidateLogpushOwnershipChallenge` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `ValidateZoneLogpushOwnershipChallenge` is removed in favour of `ValidateLogpushOwnershipChallenge` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `CheckAccountLogpushDestinationExists` is removed in favour of `CheckLogpushDestinationExists` with `ResourceContainer` method parameter +``` + +```release-note:breaking-change +logpush: `CheckZoneLogpushDestinationExists` is removed in favour of `CheckLogpushDestinationExists` with `ResourceContainer` method parameter +``` diff --git a/access_policy.go b/access_policy.go index b6d10031d97..f7da401fb9d 100644 --- a/access_policy.go +++ b/access_policy.go @@ -101,6 +101,33 @@ type CreateAccessPolicyParams struct { Require []interface{} `json:"require"` } +type UpdateAccessPolicyParams struct { + ApplicationID string `json:"-"` + PolicyID string `json:"-"` + + Precedence int `json:"precedence"` + Decision string `json:"decision"` + 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"` + ApprovalGroups []AccessApprovalGroup `json:"approval_groups"` + + // The include policy works like an OR logical operator. The user must + // satisfy one of the rules. + Include []interface{} `json:"include"` + + // The exclude policy works like a NOT logical operator. The user must + // not satisfy all the rules in exclude. + Exclude []interface{} `json:"exclude"` + + // The require policy works like a AND logical operator. The user must + // satisfy all the rules in require. + Require []interface{} `json:"require"` +} + type DeleteAccessPolicyParams struct { ApplicationID string `json:"-"` PolicyID string `json:"-"` @@ -215,19 +242,20 @@ func (api *API) CreateAccessPolicy(ctx context.Context, rc *ResourceContainer, p // // Account API reference: https://developers.cloudflare.com/api/operations/access-policies-update-an-access-policy // Zone API reference: https://developers.cloudflare.com/api/operations/zone-level-access-policies-update-an-access-policy -func (api *API) UpdateAccessPolicy(ctx context.Context, rc *ResourceContainer, applicationID string, accessPolicy AccessPolicy) (AccessPolicy, error) { - if accessPolicy.ID == "" { +func (api *API) UpdateAccessPolicy(ctx context.Context, rc *ResourceContainer, params UpdateAccessPolicyParams) (AccessPolicy, error) { + if params.PolicyID == "" { return AccessPolicy{}, fmt.Errorf("access policy ID cannot be empty") } + uri := fmt.Sprintf( "/%s/%s/access/apps/%s/policies/%s", rc.Level, rc.Identifier, - applicationID, - accessPolicy.ID, + params.ApplicationID, + params.PolicyID, ) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, accessPolicy) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return AccessPolicy{}, fmt.Errorf("%s: %w", errMakeRequestError, err) } diff --git a/access_policy_test.go b/access_policy_test.go index f3f8a66fd85..e0c16372236 100644 --- a/access_policy_test.go +++ b/access_policy_test.go @@ -329,6 +329,36 @@ func TestUpdateAccessPolicy(t *testing.T) { setup() defer teardown() + accessPolicy := UpdateAccessPolicyParams{ + ApplicationID: accessApplicationID, + PolicyID: accessPolicyID, + Precedence: 1, + Decision: "allow", + Name: "Allow devs", + Include: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + Exclude: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + Require: []interface{}{ + map[string]interface{}{"email": map[string]interface{}{"email": "test@example.com"}}, + }, + IsolationRequired: &isolationRequired, + PurposeJustificationRequired: &purposeJustificationRequired, + ApprovalRequired: &approvalRequired, + PurposeJustificationPrompt: &purposeJustificationPrompt, + ApprovalGroups: []AccessApprovalGroup{ + { + EmailListUuid: "2413b6d7-bbe5-48bd-8fbb-e52069c85561", + ApprovalsNeeded: 3, + }, + { + EmailAddresses: []string{"email1@example.com", "email2@example.com"}, + ApprovalsNeeded: 1, + }, + }, + } 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") @@ -384,14 +414,14 @@ func TestUpdateAccessPolicy(t *testing.T) { } mux.HandleFunc("/accounts/"+testAccountID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, expectedAccessPolicy) + actual, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) } mux.HandleFunc("/zones/"+testZoneID+"/access/apps/"+accessApplicationID+"/policies/"+accessPolicyID, handler) - actual, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, expectedAccessPolicy) + actual, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessPolicy) if assert.NoError(t, err) { assert.Equal(t, expectedAccessPolicy, actual) @@ -402,10 +432,10 @@ func TestUpdateAccessPolicyWithMissingID(t *testing.T) { setup() defer teardown() - _, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, accessApplicationID, AccessPolicy{}) + _, err := client.UpdateAccessPolicy(context.Background(), testAccountRC, UpdateAccessPolicyParams{ApplicationID: accessApplicationID}) assert.EqualError(t, err, "access policy ID cannot be empty") - _, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, accessApplicationID, AccessPolicy{}) + _, err = client.UpdateAccessPolicy(context.Background(), testZoneRC, UpdateAccessPolicyParams{ApplicationID: accessApplicationID}) assert.EqualError(t, err, "access policy ID cannot be empty") } From 799d6bac6e2a2b912c212693b859a166a49e93c1 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 5 Jul 2023 04:04:07 +0000 Subject: [PATCH 102/130] Update CHANGELOG.md for #1326 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2592bcef70a..d396f130df4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ ## 0.72.0 (Unreleased) +BREAKING CHANGES: + +* logpush: `CheckAccountLogpushDestinationExists` is removed in favour of `CheckLogpushDestinationExists` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `CheckZoneLogpushDestinationExists` is removed in favour of `CheckLogpushDestinationExists` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `CreateAccountLogpushJob` is removed in favour of `CreateLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `CreateZoneLogpushJob` is removed in favour of `CreateLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `DeleteAccountLogpushJob` is removed in favour of `DeleteLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `DeleteZoneLogpushJob` is removed in favour of `DeleteLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetAccountLogpushFields` is removed in favour of `GetLogpushFields` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetAccountLogpushJob` is removed in favour of `GetLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetAccountLogpushOwnershipChallenge` is removed in favour of `GetLogpushOwnershipChallenge` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetZoneLogpushFields` is removed in favour of `GetLogpushFields` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetZoneLogpushJob` is removed in favour of `GetLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `GetZoneLogpushOwnershipChallenge` is removed in favour of `GetLogpushOwnershipChallenge` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ListAccountLogpushJobsForDataset` is removed in favour of `ListLogpushJobsForDataset` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ListAccountLogpushJobs` is removed in favour of `ListLogpushJobs` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ListZoneLogpushJobsForDataset` is removed in favour of `ListLogpushJobsForDataset` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ListZoneLogpushJobs` is removed in favour of `ListLogpushJobs` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `UpdateAccountLogpushJob` is removed in favour of `UpdateLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `UpdateZoneLogpushJob` is removed in favour of `UpdateLogpushJob` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ValidateAccountLogpushOwnershipChallenge` is removed in favour of `ValidateLogpushOwnershipChallenge` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: `ValidateZoneLogpushOwnershipChallenge` is removed in favour of `ValidateLogpushOwnershipChallenge` with `ResourceContainer` method parameter ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) +* logpush: all methods are updated to use the newer client conventions for method signatures ([#1326](https://github.com/cloudflare/cloudflare-go/issues/1326)) + ENHANCEMENTS: * resource_container: expose `Type` on `*ResourceContainer` to explicitly denote what type of resource it is instead of inferring from `Level`. ([#1325](https://github.com/cloudflare/cloudflare-go/issues/1325)) From 8563e892411c1854bec07f3c910d651757248860 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 14:31:22 +1000 Subject: [PATCH 103/130] pagination: handle missing paginated responses In the event a method tries to perform pagination without the `ResultInfo` present, just return the first page instead of sitting there indefinitely. --- pagination.go | 26 ++++++++++- pagination_test.go | 106 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 pagination_test.go diff --git a/pagination.go b/pagination.go index 07d75ede84a..696dc58ee38 100644 --- a/pagination.go +++ b/pagination.go @@ -2,12 +2,32 @@ package cloudflare // Done returns true for the last page and false otherwise. func (p ResultInfo) Done() bool { + // A little hacky but if the response body is lacking a defined `ResultInfo` + // object the page will be 1 however the counts will be empty so if we have + // that response, we just assume this is the only page. + if p.Page == 1 && p.TotalPages == 0 { + return true + } + return p.Page > 1 && p.Page > p.TotalPages } // Next advances the page of a paginated API response, but does not fetch the // next page of results. func (p ResultInfo) Next() ResultInfo { + // A little hacky but if the response body is lacking a defined `ResultInfo` + // object the page will be 1 however the counts will be empty so if we have + // that response, we just assume this is the only page. + if p.Page == 1 && p.TotalPages == 0 { + return p + } + + // This shouldn't happen normally however, when it does just return the + // current page. + if p.Page > p.TotalPages { + return p + } + p.Page++ return p } @@ -15,5 +35,9 @@ func (p ResultInfo) Next() ResultInfo { // HasMorePages returns whether there is another page of results after the // current one. func (p ResultInfo) HasMorePages() bool { - return p.Page > 1 && p.Page < p.TotalPages + if p.TotalPages == 0 { + return false + } + + return p.Page >= 1 && p.Page < p.TotalPages } diff --git a/pagination_test.go b/pagination_test.go new file mode 100644 index 00000000000..eb3b07ed227 --- /dev/null +++ b/pagination_test.go @@ -0,0 +1,106 @@ +package cloudflare + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPagination_Done(t *testing.T) { + testCases := map[string]struct { + r ResultInfo + expected bool + }{ + "missing ResultInfo pagination information": { + r: ResultInfo{Page: 1}, + expected: true, + }, + "total pages greater than page": { + r: ResultInfo{Page: 1, TotalPages: 2}, + expected: false, + }, + "total pages greater than page (alot)": { + r: ResultInfo{Page: 1, TotalPages: 200}, + expected: false, + }, + // this should never happen + "total pages less than page": { + r: ResultInfo{Page: 3, TotalPages: 1}, + expected: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.r.Done(), tc.expected) + }) + } +} + +func TestPagination_Next(t *testing.T) { + testCases := map[string]struct { + r ResultInfo + expected ResultInfo + }{ + "missing ResultInfo pagination information": { + r: ResultInfo{Page: 1}, + expected: ResultInfo{Page: 1}, + }, + "total pages greater than page": { + r: ResultInfo{Page: 1, TotalPages: 3}, + expected: ResultInfo{Page: 2, TotalPages: 3}, + }, + "total pages greater than page (alot)": { + r: ResultInfo{Page: 1, TotalPages: 3000}, + expected: ResultInfo{Page: 2, TotalPages: 3000}, + }, + // bug, this should never happen + "total pages less than page": { + r: ResultInfo{Page: 3, TotalPages: 1}, + expected: ResultInfo{Page: 3, TotalPages: 1}, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + setup() + defer teardown() + + assert.Equal(t, tc.r.Next(), tc.expected) + }) + } +} + +func TestPagination_HasMorePages(t *testing.T) { + testCases := map[string]struct { + r ResultInfo + expected bool + }{ + "missing ResultInfo pagination information": { + r: ResultInfo{Page: 1}, + expected: false, + }, + "total pages greater than page": { + r: ResultInfo{Page: 1, TotalPages: 3}, + expected: true, + }, + "total pages greater than page (alot)": { + r: ResultInfo{Page: 1, TotalPages: 3000}, + expected: true, + }, + // bug, this should never happen + "total pages less than page": { + r: ResultInfo{Page: 3, TotalPages: 1}, + expected: false, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + setup() + defer teardown() + + assert.Equal(t, tc.r.HasMorePages(), tc.expected) + }) + } +} From 78fed4f6edf1eac76165ddd7a2b0710373260a66 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 5 Jul 2023 14:41:21 +1000 Subject: [PATCH 104/130] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d396f130df4..7d6dffc9b32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 0.72.0 (Unreleased) +## 0.73.0 (Unreleased) + +## 0.72.0 (July 5th, 2023) BREAKING CHANGES: From 6cc7d44f07459e3c14de5b4e62058da429b93df8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:53:05 +0000 Subject: [PATCH 105/130] build(deps): bump golang.org/x/net from 0.11.0 to 0.12.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/net/compare/v0.11.0...v0.12.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 856fd9cb6c7..cca49c771a6 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.4 github.com/urfave/cli/v2 v2.25.7 - golang.org/x/net v0.11.0 + golang.org/x/net v0.12.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.10.0 // indirect + golang.org/x/text v0.11.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a528bd1062b..b47e6c7b0e2 100644 --- a/go.sum +++ b/go.sum @@ -57,17 +57,17 @@ github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 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.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= 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.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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 5a3a6da0f3154468fed8704bfbe5852b826be932 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 5 Jul 2023 16:53:22 +0000 Subject: [PATCH 106/130] add CHANGELOG for #1328 --- .changelog/1328.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1328.txt diff --git a/.changelog/1328.txt b/.changelog/1328.txt new file mode 100644 index 00000000000..51d73f83089 --- /dev/null +++ b/.changelog/1328.txt @@ -0,0 +1,3 @@ +```release-note:dependency +deps: bumps golang.org/x/net from 0.11.0 to 0.12.0 +``` From 6fdc6f83c04b7c98e757c606f05bb4849bc9619f Mon Sep 17 00:00:00 2001 From: changelogbot Date: Wed, 5 Jul 2023 21:50:57 +0000 Subject: [PATCH 107/130] Update CHANGELOG.md for #1328 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d6dffc9b32..b024044d2f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.73.0 (Unreleased) +DEPENDENCIES: + +* deps: bumps golang.org/x/net from 0.11.0 to 0.12.0 ([#1328](https://github.com/cloudflare/cloudflare-go/issues/1328)) + ## 0.72.0 (July 5th, 2023) BREAKING CHANGES: From ee2ff710bac859c282e420c5885f654b085d5cb4 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 7 Jul 2023 13:54:46 +1000 Subject: [PATCH 108/130] split usage of `ID` and `Name` Pages, unfortunately, uses a friendly name for the identifier in the URL so to be able to update the `Name` value we need a way to differentiate the two. The way I've solved this here is that `ID` is used for addressing the resource via the UI or a stable identifier whereas `Name` is used for updating the value. --- pages_project.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pages_project.go b/pages_project.go index eed8fde8334..8ee0c66ddd8 100644 --- a/pages_project.go +++ b/pages_project.go @@ -205,6 +205,9 @@ type CreatePagesProjectParams struct { } type UpdatePagesProjectParams struct { + // `ID` is used for addressing the resource via the UI or a stable + // anchor whereas `Name` is used for updating the value. + ID string `json:"-"` Name string `json:"name,omitempty"` SubDomain string `json:"subdomain"` Domains []string `json:"domains,omitempty"` @@ -287,11 +290,11 @@ func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, p return PagesProject{}, ErrMissingAccountID } - if params.Name == "" { + if params.ID == "" { return PagesProject{}, ErrMissingName } - uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, params.Name) + uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, params.ID) res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) if err != nil { return PagesProject{}, err From bbd657eece9dbb88a1b410ee61278e61d43096e6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Fri, 7 Jul 2023 14:06:54 +1000 Subject: [PATCH 109/130] fix test assertions --- pages_project.go | 2 +- pages_project_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pages_project.go b/pages_project.go index 55af7b2639b..94c67b242ed 100644 --- a/pages_project.go +++ b/pages_project.go @@ -293,7 +293,7 @@ func (api *API) UpdatePagesProject(ctx context.Context, rc *ResourceContainer, p } if params.ID == "" { - return PagesProject{}, ErrMissingName + return PagesProject{}, ErrMissingIdentifier } uri := fmt.Sprintf("/accounts/%s/pages/projects/%s", rc.Identifier, params.ID) diff --git a/pages_project_test.go b/pages_project_test.go index d53e5cc773b..3c4b7ecc049 100644 --- a/pages_project_test.go +++ b/pages_project_test.go @@ -602,7 +602,7 @@ func TestCreatePagesProject(t *testing.T) { actual, err := client.CreatePagesProject(context.Background(), AccountIdentifier(testAccountID), *params) if assert.NoError(t, err) { - assert.Equal(t, params, actual) + assert.Equal(t, *expectedPagesProject, actual) } } @@ -611,6 +611,7 @@ func TestUpdatePagesProject(t *testing.T) { defer teardown() updateAttributes := &UpdatePagesProjectParams{ + ID: "Test Pages Project", Name: "updated-project-name", } From 0e901952195de69364344081565b0ffb0101e211 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Fri, 7 Jul 2023 04:15:34 +0000 Subject: [PATCH 110/130] Update CHANGELOG.md for #1264 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b024044d2f7..009fdce14a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ ## 0.73.0 (Unreleased) +BREAKING CHANGES: + +* pages_deployment: add support for auto pagination ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) +* pages_deployment: change DeletePagesDeploymentParams to contain all parameters ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) +* pages_project: change to use ResourceContainer for account ID ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) +* pages_project: rename PagesProject to GetPagesProject ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) + DEPENDENCIES: * deps: bumps golang.org/x/net from 0.11.0 to 0.12.0 ([#1328](https://github.com/cloudflare/cloudflare-go/issues/1328)) From 89cdca368b7a32a237dc51b62c5b741dc9649e32 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Jul 2023 12:43:01 +1000 Subject: [PATCH 111/130] rulesets: modernise methods Updates the ruleset methods to be in line with our experimental conventions. This change also makes it clearer the purpose of `GetRulesetEntrypoint` methods which were previously confusing to use. --- .changelog/1333.txt | 47 ++++++++++++ rulesets.go | 169 ++++++++++++++++---------------------------- rulesets_test.go | 48 +++++++------ 3 files changed, 135 insertions(+), 129 deletions(-) create mode 100644 .changelog/1333.txt diff --git a/.changelog/1333.txt b/.changelog/1333.txt new file mode 100644 index 00000000000..2a815350218 --- /dev/null +++ b/.changelog/1333.txt @@ -0,0 +1,47 @@ +```release-note:breaking-change +rulesets: `GetZoneRuleset` is removed in favour of `GetRuleset` +``` + +```release-note:breaking-change +rulesets: `GetAccountRuleset` is removed in favour of `GetRuleset` +``` + +```release-note:breaking-change +rulesets: `CreateZoneRuleset` is removed in favour of `CreateRuleset` +``` + +```release-note:breaking-change +rulesets: `CreateAccountRuleset` is removed in favour of `CreateRuleset` +``` + +```release-note:breaking-change +rulesets: `DeleteZoneRuleset` is removed in favour of `DeleteRuleset` +``` + +```release-note:breaking-change +rulesets: `DeleteAccountRuleset` is removed in favour of `DeleteRuleset` +``` + +```release-note:breaking-change +rulesets: `UpdateZoneRuleset` is removed in favour of `UpdateRuleset` +``` + +```release-note:breaking-change +rulesets: `UpdateAccountRuleset` is removed in favour of `UpdateRuleset` +``` + +```release-note:breaking-change +rulesets: `GetZoneRulesetPhase` is removed in favour of `GetRulesetEntrypoint` +``` + +```release-note:breaking-change +rulesets: `GetAccountRulesetPhase` is removed in favour of `GetRulesetEntrypoint` +``` + +```release-note:breaking-change +rulesets: `UpdateZoneRulesetPhase` is removed in favour of `UpdateRulesetEntrypoint` +``` + +```release-note:breaking-change +rulesets: `UpdateAccountRulesetPhase` is removed in favour of `UpdateRulesetEntrypoint` +``` diff --git a/rulesets.go b/rulesets.go index 72a7a4f3bfc..f77bc44e4e0 100644 --- a/rulesets.go +++ b/rulesets.go @@ -10,6 +10,10 @@ import ( "time" ) +var ( + ErrMissingRulesetPhase = errors.New("missing required phase") +) + const ( RulesetKindCustom RulesetKind = "custom" RulesetKindManaged RulesetKind = "managed" @@ -711,24 +715,40 @@ type UpdateRulesetResponse struct { Result Ruleset `json:"result"` } -// ListZoneRulesets fetches all rulesets for a zone. -// -// API reference: https://api.cloudflare.com/#zone-rulesets-list-zone-rulesets -func (api *API) ListZoneRulesets(ctx context.Context, zoneID string) ([]Ruleset, error) { - return api.listRulesets(ctx, ZoneRouteRoot, zoneID) +type ListRulesetsParams struct{} + +type CreateRulesetParams struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Kind string `json:"kind,omitempty"` + Version *string `json:"version,omitempty"` + Phase string `json:"phase,omitempty"` + Rules []RulesetRule `json:"rules"` + ShareableEntitlementName string `json:"shareable_entitlement_name,omitempty"` } -// ListAccountRulesets fetches all rulesets for an account. -// -// API reference: https://api.cloudflare.com/#account-rulesets-list-account-rulesets -func (api *API) ListAccountRulesets(ctx context.Context, accountID string) ([]Ruleset, error) { - return api.listRulesets(ctx, AccountRouteRoot, accountID) +type UpdateRulesetParams struct { + ID string `json:"-"` + Description string `json:"description"` + Rules []RulesetRule `json:"rules"` } -// listRulesets lists all Rulesets for a given zone or account depending on the -// identifier type provided. -func (api *API) listRulesets(ctx context.Context, identifierType RouteRoot, identifier string) ([]Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets", identifierType, identifier) +type UpdateRulesetEntrypointParams struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Kind string `json:"kind,omitempty"` + Version *string `json:"version,omitempty"` + Phase string `json:"-"` + Rules []RulesetRule `json:"rules"` +} + +// ListRulesets lists all Rulesets for a given zone or account depending on the +// ResourceContainer type provided. +// +// API reference: https://api.cloudflare.com/#zone-rulesets-list-zone-rulesets +// API reference: https://api.cloudflare.com/#account-rulesets-list-account-rulesets +func (api *API) ListRulesets(ctx context.Context, rc *ResourceContainer, params ListRulesetsParams) ([]Ruleset, error) { + uri := fmt.Sprintf("/%s/%s/rulesets", rc.Level, rc.Identifier) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -743,24 +763,12 @@ func (api *API) listRulesets(ctx context.Context, identifierType RouteRoot, iden return result.Result, nil } -// GetZoneRuleset fetches a single ruleset for a zone. +// GetRuleset fetches a single ruleset. // // API reference: https://api.cloudflare.com/#zone-rulesets-get-a-zone-ruleset -func (api *API) GetZoneRuleset(ctx context.Context, zoneID, rulesetID string) (Ruleset, error) { - return api.getRuleset(ctx, ZoneRouteRoot, zoneID, rulesetID) -} - -// GetAccountRuleset fetches a single ruleset for an account. -// // API reference: https://api.cloudflare.com/#account-rulesets-get-an-account-ruleset -func (api *API) GetAccountRuleset(ctx context.Context, accountID, rulesetID string) (Ruleset, error) { - return api.getRuleset(ctx, AccountRouteRoot, accountID, rulesetID) -} - -// getRuleset fetches a single ruleset based on the zone or account, the -// identifier and the ruleset ID. -func (api *API) getRuleset(ctx context.Context, identifierType RouteRoot, identifier, rulesetID string) (Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets/%s", identifierType, identifier, rulesetID) +func (api *API) GetRuleset(ctx context.Context, rc *ResourceContainer, rulesetID string) (Ruleset, error) { + uri := fmt.Sprintf("/%s/%s/rulesets/%s", rc.Level, rc.Identifier, rulesetID) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return Ruleset{}, err @@ -774,23 +782,13 @@ func (api *API) getRuleset(ctx context.Context, identifierType RouteRoot, identi return result.Result, nil } -// CreateZoneRuleset creates a new ruleset for a zone. +// CreateRuleset initialises a new ruleset. // // API reference: https://api.cloudflare.com/#zone-rulesets-create-zone-ruleset -func (api *API) CreateZoneRuleset(ctx context.Context, zoneID string, ruleset Ruleset) (Ruleset, error) { - return api.createRuleset(ctx, ZoneRouteRoot, zoneID, ruleset) -} - -// CreateAccountRuleset creates a new ruleset for an account. -// // API reference: https://api.cloudflare.com/#account-rulesets-create-account-ruleset -func (api *API) CreateAccountRuleset(ctx context.Context, accountID string, ruleset Ruleset) (Ruleset, error) { - return api.createRuleset(ctx, AccountRouteRoot, accountID, ruleset) -} - -func (api *API) createRuleset(ctx context.Context, identifierType RouteRoot, identifier string, ruleset Ruleset) (Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets", identifierType, identifier) - res, err := api.makeRequestContext(ctx, http.MethodPost, uri, ruleset) +func (api *API) CreateRuleset(ctx context.Context, rc *ResourceContainer, params CreateRulesetParams) (Ruleset, error) { + uri := fmt.Sprintf("/%s/%s/rulesets", rc.Level, rc.Identifier) + res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params) if err != nil { return Ruleset{}, err } @@ -803,23 +801,12 @@ func (api *API) createRuleset(ctx context.Context, identifierType RouteRoot, ide return result.Result, nil } -// DeleteZoneRuleset deletes a single ruleset for a zone. +// DeleteRuleset removes a ruleset based on the ruleset ID. // // API reference: https://api.cloudflare.com/#zone-rulesets-delete-zone-ruleset -func (api *API) DeleteZoneRuleset(ctx context.Context, zoneID, rulesetID string) error { - return api.deleteRuleset(ctx, ZoneRouteRoot, zoneID, rulesetID) -} - -// DeleteAccountRuleset deletes a single ruleset for an account. -// // API reference: https://api.cloudflare.com/#account-rulesets-delete-account-ruleset -func (api *API) DeleteAccountRuleset(ctx context.Context, accountID, rulesetID string) error { - return api.deleteRuleset(ctx, AccountRouteRoot, accountID, rulesetID) -} - -// deleteRuleset removes a ruleset based on the ruleset ID. -func (api *API) deleteRuleset(ctx context.Context, identifierType RouteRoot, identifier, rulesetID string) error { - uri := fmt.Sprintf("/%s/%s/rulesets/%s", identifierType, identifier, rulesetID) +func (api *API) DeleteRuleset(ctx context.Context, rc *ResourceContainer, rulesetID string) error { + uri := fmt.Sprintf("/%s/%s/rulesets/%s", rc.Level, rc.Identifier, rulesetID) res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil) if err != nil { return err @@ -835,25 +822,17 @@ func (api *API) deleteRuleset(ctx context.Context, identifierType RouteRoot, ide return nil } -// UpdateZoneRuleset updates a single ruleset for a zone. +// UpdateRuleset updates a ruleset based on the ruleset ID. // // API reference: https://api.cloudflare.com/#zone-rulesets-update-a-zone-ruleset -func (api *API) UpdateZoneRuleset(ctx context.Context, zoneID, rulesetID, description string, rules []RulesetRule) (Ruleset, error) { - return api.updateRuleset(ctx, ZoneRouteRoot, zoneID, rulesetID, description, rules) -} - -// UpdateAccountRuleset updates a single ruleset for an account. -// // API reference: https://api.cloudflare.com/#account-rulesets-update-account-ruleset -func (api *API) UpdateAccountRuleset(ctx context.Context, accountID, rulesetID, description string, rules []RulesetRule) (Ruleset, error) { - return api.updateRuleset(ctx, AccountRouteRoot, accountID, rulesetID, description, rules) -} +func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params UpdateRulesetParams) (Ruleset, error) { + if params.ID == "" { + return Ruleset{}, ErrMissingResourceIdentifier + } -// updateRuleset updates a ruleset based on the ruleset ID. -func (api *API) updateRuleset(ctx context.Context, identifierType RouteRoot, identifier, rulesetID, description string, rules []RulesetRule) (Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets/%s", identifierType, identifier, rulesetID) - payload := UpdateRulesetRequest{Description: description, Rules: rules} - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, payload) + uri := fmt.Sprintf("/%s/%s/rulesets/%s", rc.Level, rc.Identifier, params.ID) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return Ruleset{}, err } @@ -866,24 +845,9 @@ func (api *API) updateRuleset(ctx context.Context, identifierType RouteRoot, ide return result.Result, nil } -// GetZoneRulesetPhase returns a ruleset phase for a zone. -// -// API reference: TBA. -func (api *API) GetZoneRulesetPhase(ctx context.Context, zoneID, rulesetPhase string) (Ruleset, error) { - return api.getRulesetPhase(ctx, ZoneRouteRoot, zoneID, rulesetPhase) -} - -// GetAccountRulesetPhase returns a ruleset phase for an account. -// -// API reference: TBA. -func (api *API) GetAccountRulesetPhase(ctx context.Context, accountID, rulesetPhase string) (Ruleset, error) { - return api.getRulesetPhase(ctx, AccountRouteRoot, accountID, rulesetPhase) -} - -// getRulesetPhase returns a ruleset phase based on the zone or account and the -// identifier. -func (api *API) getRulesetPhase(ctx context.Context, identifierType RouteRoot, identifier, rulesetPhase string) (Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", identifierType, identifier, rulesetPhase) +// GetRulesetEntrypoint returns a ruleset phase based on the resource entrypoint. +func (api *API) GetRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, phase string) (Ruleset, error) { + uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", rc.Level, rc.Identifier, phase) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { return Ruleset{}, err @@ -897,25 +861,14 @@ func (api *API) getRulesetPhase(ctx context.Context, identifierType RouteRoot, i return result.Result, nil } -// UpdateZoneRulesetPhase updates a ruleset phase for a zone. -// -// API reference: TBA. -func (api *API) UpdateZoneRulesetPhase(ctx context.Context, zoneID, rulesetPhase string, ruleset Ruleset) (Ruleset, error) { - return api.updateRulesetPhase(ctx, ZoneRouteRoot, zoneID, rulesetPhase, ruleset) -} - -// UpdateAccountRulesetPhase updates a ruleset phase for an account. -// -// API reference: TBA. -func (api *API) UpdateAccountRulesetPhase(ctx context.Context, accountID, rulesetPhase string, ruleset Ruleset) (Ruleset, error) { - return api.updateRulesetPhase(ctx, AccountRouteRoot, accountID, rulesetPhase, ruleset) -} +// UpdateRulesetEntrypoint updates a ruleset phase based on the entrypoint. +func (api *API) UpdateRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, params UpdateRulesetEntrypointParams) (Ruleset, error) { + if params.Phase == "" { + return Ruleset{}, ErrMissingRulesetPhase + } -// updateRulesetPhase updates a ruleset phase based on the zone or account, the -// identifier and the rules. -func (api *API) updateRulesetPhase(ctx context.Context, identifierType RouteRoot, identifier, rulesetPhase string, ruleset Ruleset) (Ruleset, error) { - uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", identifierType, identifier, rulesetPhase) - res, err := api.makeRequestContext(ctx, http.MethodPut, uri, ruleset) + uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", rc.Level, rc.Identifier, params.Phase) + res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params) if err != nil { return Ruleset{}, err } diff --git a/rulesets_test.go b/rulesets_test.go index 52e9ed88ce4..d2d654a1f09 100644 --- a/rulesets_test.go +++ b/rulesets_test.go @@ -52,12 +52,12 @@ func TestListRulesets(t *testing.T) { }, } - zoneActual, err := client.ListZoneRulesets(context.Background(), testZoneID) + zoneActual, err := client.ListRulesets(context.Background(), ZoneIdentifier(testZoneID), ListRulesetsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.ListAccountRulesets(context.Background(), testAccountID) + accountActual, err := client.ListRulesets(context.Background(), AccountIdentifier(testAccountID), ListRulesetsParams{}) if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -101,12 +101,12 @@ func TestGetRuleset_MagicTransit(t *testing.T) { Phase: string(RulesetPhaseMagicTransit), } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "2c0fc9fa937b11eaa1b71c4d701ab86e") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "2c0fc9fa937b11eaa1b71c4d701ab86e") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "2c0fc9fa937b11eaa1b71c4d701ab86e") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "2c0fc9fa937b11eaa1b71c4d701ab86e") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -188,12 +188,12 @@ func TestGetRuleset_WAF(t *testing.T) { Rules: rules, } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -343,12 +343,12 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) { Rules: rules, } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -454,12 +454,12 @@ func TestGetRuleset_SetConfig(t *testing.T) { Rules: rules, } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -543,12 +543,12 @@ func TestGetRuleset_RedirectFromValue(t *testing.T) { Rules: rules, } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -623,12 +623,12 @@ func TestGetRuleset_CompressResponse(t *testing.T) { Rules: rules, } - zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9") + zoneActual, err := client.GetRuleset(context.Background(), ZoneIdentifier(testZoneID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9") + accountActual, err := client.GetRuleset(context.Background(), AccountIdentifier(testAccountID), "b232b534beea4e00a21dcbb7a8a545e9") if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -691,7 +691,7 @@ func TestCreateRuleset(t *testing.T) { Enabled: BoolPtr(true), }} - newRuleset := Ruleset{ + newRuleset := CreateRulesetParams{ Name: "my example ruleset", Description: "Test magic transit ruleset", Kind: "root", @@ -710,12 +710,12 @@ func TestCreateRuleset(t *testing.T) { Rules: rules, } - zoneActual, err := client.CreateZoneRuleset(context.Background(), testZoneID, newRuleset) + zoneActual, err := client.CreateRuleset(context.Background(), ZoneIdentifier(testZoneID), newRuleset) if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.CreateAccountRuleset(context.Background(), testAccountID, newRuleset) + accountActual, err := client.CreateRuleset(context.Background(), AccountIdentifier(testAccountID), newRuleset) if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } @@ -734,10 +734,10 @@ func TestDeleteRuleset(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/rulesets/2c0fc9fa937b11eaa1b71c4d701ab86e", handler) mux.HandleFunc("/zones/"+testZoneID+"/rulesets/2c0fc9fa937b11eaa1b71c4d701ab86e", handler) - zErr := client.DeleteZoneRuleset(context.Background(), testZoneID, "2c0fc9fa937b11eaa1b71c4d701ab86e") + zErr := client.DeleteRuleset(context.Background(), ZoneIdentifier(testZoneID), "2c0fc9fa937b11eaa1b71c4d701ab86e") assert.NoError(t, zErr) - aErr := client.DeleteAccountRuleset(context.Background(), testAccountID, "2c0fc9fa937b11eaa1b71c4d701ab86e") + aErr := client.DeleteRuleset(context.Background(), AccountIdentifier(testAccountID), "2c0fc9fa937b11eaa1b71c4d701ab86e") assert.NoError(t, aErr) } @@ -823,6 +823,12 @@ func TestUpdateRuleset(t *testing.T) { Enabled: BoolPtr(true), }} + updated := UpdateRulesetParams{ + ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", + Description: "Test Firewall Ruleset Update", + Rules: rules, + } + want := Ruleset{ ID: "2c0fc9fa937b11eaa1b71c4d701ab86e", Name: "ruleset1", @@ -834,12 +840,12 @@ func TestUpdateRuleset(t *testing.T) { Rules: rules, } - zoneActual, err := client.UpdateZoneRuleset(context.Background(), testZoneID, "2c0fc9fa937b11eaa1b71c4d701ab86e", "Test Firewall Ruleset Update", rules) + zoneActual, err := client.UpdateRuleset(context.Background(), ZoneIdentifier(testZoneID), updated) if assert.NoError(t, err) { assert.Equal(t, want, zoneActual) } - accountActual, err := client.UpdateAccountRuleset(context.Background(), testAccountID, "2c0fc9fa937b11eaa1b71c4d701ab86e", "Test Firewall Ruleset Update", rules) + accountActual, err := client.UpdateRuleset(context.Background(), AccountIdentifier(testAccountID), updated) if assert.NoError(t, err) { assert.Equal(t, want, accountActual) } From 697218334d72bf03b12f86b976b829f2363b5f05 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Jul 2023 19:27:18 +1000 Subject: [PATCH 112/130] Update rulesets.go Co-authored-by: Zak Cutner --- rulesets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rulesets.go b/rulesets.go index f77bc44e4e0..8fe5ae30ab4 100644 --- a/rulesets.go +++ b/rulesets.go @@ -845,7 +845,7 @@ func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params return result.Result, nil } -// GetRulesetEntrypoint returns a ruleset phase based on the resource entrypoint. +// GetRulesetEntrypoint returns an entrypoint ruleset based on the phase. func (api *API) GetRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, phase string) (Ruleset, error) { uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", rc.Level, rc.Identifier, phase) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) From 8c5587819befba6aa4865474f5a8a5f179b1c8cb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 12 Jul 2023 19:27:25 +1000 Subject: [PATCH 113/130] Update rulesets.go Co-authored-by: Zak Cutner --- rulesets.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rulesets.go b/rulesets.go index 8fe5ae30ab4..20483ac2bc5 100644 --- a/rulesets.go +++ b/rulesets.go @@ -861,7 +861,7 @@ func (api *API) GetRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, return result.Result, nil } -// UpdateRulesetEntrypoint updates a ruleset phase based on the entrypoint. +// UpdateRulesetEntrypoint updates an entrypoint ruleset based on the phase. func (api *API) UpdateRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, params UpdateRulesetEntrypointParams) (Ruleset, error) { if params.Phase == "" { return Ruleset{}, ErrMissingRulesetPhase From 1b7ab7a71b4b3992fc47d6bf1f93adb293eabf78 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 13 Jul 2023 13:21:49 +1000 Subject: [PATCH 114/130] s/RulesetEntrypoint/EntrypointRuleset --- rulesets.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rulesets.go b/rulesets.go index 20483ac2bc5..80ebed208c7 100644 --- a/rulesets.go +++ b/rulesets.go @@ -733,7 +733,7 @@ type UpdateRulesetParams struct { Rules []RulesetRule `json:"rules"` } -type UpdateRulesetEntrypointParams struct { +type UpdateEntrypointRulesetParams struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` Kind string `json:"kind,omitempty"` @@ -845,8 +845,8 @@ func (api *API) UpdateRuleset(ctx context.Context, rc *ResourceContainer, params return result.Result, nil } -// GetRulesetEntrypoint returns an entrypoint ruleset based on the phase. -func (api *API) GetRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, phase string) (Ruleset, error) { +// GetEntrypointRuleset returns a ruleset phase based on the resource entrypoint. +func (api *API) GetEntrypointRuleset(ctx context.Context, rc *ResourceContainer, phase string) (Ruleset, error) { uri := fmt.Sprintf("/%s/%s/rulesets/phases/%s/entrypoint", rc.Level, rc.Identifier, phase) res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) if err != nil { @@ -861,8 +861,8 @@ func (api *API) GetRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, return result.Result, nil } -// UpdateRulesetEntrypoint updates an entrypoint ruleset based on the phase. -func (api *API) UpdateRulesetEntrypoint(ctx context.Context, rc *ResourceContainer, params UpdateRulesetEntrypointParams) (Ruleset, error) { +// UpdateEntrypointRuleset updates a ruleset phase based on the entrypoint. +func (api *API) UpdateEntrypointRuleset(ctx context.Context, rc *ResourceContainer, params UpdateEntrypointRulesetParams) (Ruleset, error) { if params.Phase == "" { return Ruleset{}, ErrMissingRulesetPhase } From 2df43e581568c2a79c6f5e6e971a80c5a708d9a6 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 13 Jul 2023 13:24:02 +1000 Subject: [PATCH 115/130] update CHANGELOG --- .changelog/1333.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.changelog/1333.txt b/.changelog/1333.txt index 2a815350218..81026e8158e 100644 --- a/.changelog/1333.txt +++ b/.changelog/1333.txt @@ -31,17 +31,17 @@ rulesets: `UpdateAccountRuleset` is removed in favour of `UpdateRuleset` ``` ```release-note:breaking-change -rulesets: `GetZoneRulesetPhase` is removed in favour of `GetRulesetEntrypoint` +rulesets: `GetZoneRulesetPhase` is removed in favour of `GetEntrypointRuleset` ``` ```release-note:breaking-change -rulesets: `GetAccountRulesetPhase` is removed in favour of `GetRulesetEntrypoint` +rulesets: `GetAccountRulesetPhase` is removed in favour of `GetEntrypointRuleset` ``` ```release-note:breaking-change -rulesets: `UpdateZoneRulesetPhase` is removed in favour of `UpdateRulesetEntrypoint` +rulesets: `UpdateZoneRulesetPhase` is removed in favour of `UpdateEntrypointRuleset` ``` ```release-note:breaking-change -rulesets: `UpdateAccountRulesetPhase` is removed in favour of `UpdateRulesetEntrypoint` +rulesets: `UpdateAccountRulesetPhase` is removed in favour of `UpdateEntrypointRuleset` ``` From 800881d176514c7ca399493d7a2bf4398c0c89a0 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 13 Jul 2023 13:31:27 +1000 Subject: [PATCH 116/130] bump golint-ci timeout to 5m --- .golintci.yaml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.golintci.yaml b/.golintci.yaml index c885d96e12c..c4e5df2c685 100644 --- a/.golintci.yaml +++ b/.golintci.yaml @@ -1,17 +1,8 @@ run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 1m - - # exit code when at least one issue was found, default is 1 + timeout: 5m issues-exit-code: 1 - - # include test files or not, default is true tests: true - - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ skip-dirs-use-default: true - modules-download-mode: readonly linters: From d22150baf7402d43359245c9482eefa09b26f001 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 13 Jul 2023 13:45:38 +1000 Subject: [PATCH 117/130] add cache step to golangci lint steps --- .github/workflows/lint.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c9c53ae5d3b..39b9094c311 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,6 +12,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go${{ matrix.go-version }}-${{ hashFiles('**/go.mod') }}-${{ hashFiles('**/go.sum') }} - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: From b8dab62e3f9bde53e278cc0f94bd9bff4cc5d8bb Mon Sep 17 00:00:00 2001 From: changelogbot Date: Thu, 13 Jul 2023 03:51:13 +0000 Subject: [PATCH 118/130] Update CHANGELOG.md for #1333 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 009fdce14a0..238d67ab248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ BREAKING CHANGES: * pages_deployment: change DeletePagesDeploymentParams to contain all parameters ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) * pages_project: change to use ResourceContainer for account ID ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) * pages_project: rename PagesProject to GetPagesProject ([#1264](https://github.com/cloudflare/cloudflare-go/issues/1264)) +* rulesets: `CreateAccountRuleset` is removed in favour of `CreateRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `CreateZoneRuleset` is removed in favour of `CreateRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `DeleteAccountRuleset` is removed in favour of `DeleteRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `DeleteZoneRuleset` is removed in favour of `DeleteRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `GetAccountRulesetPhase` is removed in favour of `GetEntrypointRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `GetAccountRuleset` is removed in favour of `GetRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `GetZoneRulesetPhase` is removed in favour of `GetEntrypointRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `GetZoneRuleset` is removed in favour of `GetRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `UpdateAccountRulesetPhase` is removed in favour of `UpdateEntrypointRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `UpdateAccountRuleset` is removed in favour of `UpdateRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `UpdateZoneRulesetPhase` is removed in favour of `UpdateEntrypointRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +* rulesets: `UpdateZoneRuleset` is removed in favour of `UpdateRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) DEPENDENCIES: From 3f5ef8bebd5a7bd676f6de4900b559e648f0d973 Mon Sep 17 00:00:00 2001 From: dojolew Date: Sat, 15 Jul 2023 09:37:48 +0100 Subject: [PATCH 119/130] Add image upload by url --- images.go | 77 +++++++++++++++++++++++++++++++++++++ images_test.go | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/images.go b/images.go index b93b2f46de5..281f0537867 100644 --- a/images.go +++ b/images.go @@ -84,6 +84,43 @@ func (b UploadImageParams) write(mpw *multipart.Writer) error { return nil } +// UploadImageByUrlParams is the data required for an Image Upload by URL request. +type UploadImageByUrlParams struct { + Url string + RequireSignedURLs bool + Metadata map[string]interface{} +} + +func (b UploadImageByUrlParams) write(mpw *multipart.Writer) error { + err := mpw.WriteField("url", b.Url) + if err != nil { + return err + } + + // According to the Cloudflare docs, this field defaults to false. + // For simplicity, we will only send it if the value is true, however + // if the default is changed to true, this logic will need to be updated. + if b.RequireSignedURLs { + err = mpw.WriteField("requireSignedURLs", "true") + if err != nil { + return err + } + } + + if b.Metadata != nil { + part, err := mpw.CreateFormField("metadata") + if err != nil { + return err + } + err = json.NewEncoder(part).Encode(b.Metadata) + if err != nil { + return err + } + } + + return nil +} + // UpdateImageParams is the data required for an UpdateImage request. type UpdateImageParams struct { ID string `json:"-"` @@ -183,6 +220,46 @@ func (api *API) UploadImage(ctx context.Context, rc *ResourceContainer, params U return imageDetailsResponse.Result, nil } +// UploadImageByUrl uploads a single image from a given url. +// +// API Reference: https://api.cloudflare.com/#cloudflare-images-upload-an-image-using-a-single-http-request +func (api *API) UploadImageByUrl(ctx context.Context, rc *ResourceContainer, params UploadImageByUrlParams) (Image, error) { + if rc.Level != AccountRouteLevel { + return Image{}, ErrRequiredAccountLevelResourceContainer + } + + uri := fmt.Sprintf("/accounts/%s/images/v1", rc.Identifier) + + body := &bytes.Buffer{} + w := multipart.NewWriter(body) + if err := params.write(w); err != nil { + _ = w.Close() + return Image{}, fmt.Errorf("error writing multipart body: %w", err) + } + _ = w.Close() + + res, err := api.makeRequestContextWithHeaders( + ctx, + http.MethodPost, + uri, + body, + http.Header{ + "Accept": []string{"application/json"}, + "Content-Type": []string{w.FormDataContentType()}, + }, + ) + if err != nil { + return Image{}, err + } + + var imageDetailsResponse ImageDetailsResponse + err = json.Unmarshal(res, &imageDetailsResponse) + if err != nil { + return Image{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return imageDetailsResponse.Result, nil +} + // UpdateImage updates an existing image's metadata. // // API Reference: https://api.cloudflare.com/#cloudflare-images-update-image diff --git a/images_test.go b/images_test.go index 3640d9f3131..d4fa864838f 100644 --- a/images_test.go +++ b/images_test.go @@ -96,6 +96,61 @@ func TestUploadImage(t *testing.T) { } } +func TestUploadImageByUrl(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) + + u, err := parseImageMultipartUploadByUrl(r) + if !assert.NoError(t, err) { + w.WriteHeader(http.StatusBadRequest) + return + } + assert.Equal(t, u.RequireSignedURLs, true) + assert.Equal(t, u.Metadata, map[string]interface{}{"meta": "metaID"}) + assert.Equal(t, u.Url, "https://www.images-elsewhere.com/avatar.png") + + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "ZxR0pLaXRldlBtaFhhO2FiZGVnaA", + "filename": "avatar.png", + "metadata": { + "meta": "metaID" + }, + "requireSignedURLs": true, + "variants": [ + "https://imagedelivery.net/MTt4OTd0b0w5aj/ZxR0pLaXRldlBtaFhhO2FiZGVnaA/hero", + "https://imagedelivery.net/MTt4OTd0b0w5aj/ZxR0pLaXRldlBtaFhhO2FiZGVnaA/original", + "https://imagedelivery.net/MTt4OTd0b0w5aj/ZxR0pLaXRldlBtaFhhO2FiZGVnaA/thumbnail" + ], + "uploaded": "2014-01-02T02:20:00Z" + } + } + `) + } + + mux.HandleFunc("/accounts/"+testAccountID+"/images/v1", handler) + want := expectedImageStruct + + actual, err := client.UploadImageByUrl(context.Background(), AccountIdentifier(testAccountID), UploadImageByUrlParams{ + Url: "https://www.images-elsewhere.com/avatar.png", + RequireSignedURLs: true, + Metadata: map[string]interface{}{ + "meta": "metaID", + }, + }) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestUpdateImage(t *testing.T) { setup() defer teardown() @@ -432,6 +487,52 @@ func parseImageMultipartUpload(r *http.Request) (imageMultipartUpload, error) { return u, nil } +type imageMultipartUploadByUrl struct { + Url string + RequireSignedURLs bool + Metadata map[string]interface{} +} + +func parseImageMultipartUploadByUrl(r *http.Request) (imageMultipartUploadByUrl, error) { + var u imageMultipartUploadByUrl + mdBytes, err := getImageFormValue(r, "metadata") + if err != nil { + if !strings.HasPrefix(err.Error(), "no value found for key") { + return u, err + } + } + if mdBytes != nil { + err = json.Unmarshal(mdBytes, &u.Metadata) + if err != nil { + return u, err + } + } + + rsuBytes, err := getImageFormValue(r, "requireSignedURLs") + if err != nil { + if !strings.HasPrefix(err.Error(), "no value found for key") { + return u, err + } + } + if rsuBytes != nil { + if bytes.Equal(rsuBytes, []byte("true")) { + u.RequireSignedURLs = true + } + } + + urlBytes, err := getImageFormValue(r, "url") + if err != nil { + if !strings.HasPrefix(err.Error(), "no value found for key") { + return u, err + } + } + if urlBytes != nil { + u.Url = string(urlBytes) + } + + return u, nil +} + // See getFormValue for more information, the only difference between // getFormValue and this one is the max memory. func getImageFormValue(r *http.Request, key string) ([]byte, error) { From fcecaaad0c0de098be4d5454712b516c8342fe0f Mon Sep 17 00:00:00 2001 From: lewisyearsley Date: Sat, 15 Jul 2023 10:59:59 +0100 Subject: [PATCH 120/130] changelog --- .changelog/1336.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1336.txt diff --git a/.changelog/1336.txt b/.changelog/1336.txt new file mode 100644 index 00000000000..13b520854ae --- /dev/null +++ b/.changelog/1336.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +images: adds ability to upload image by url +``` From 8c5b7b7203520e902045b274746279f22d9e941b Mon Sep 17 00:00:00 2001 From: lewisyearsley Date: Sat, 15 Jul 2023 11:08:48 +0100 Subject: [PATCH 121/130] correct changelog name --- .changelog/{1336.txt => 1335.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{1336.txt => 1335.txt} (100%) diff --git a/.changelog/1336.txt b/.changelog/1335.txt similarity index 100% rename from .changelog/1336.txt rename to .changelog/1335.txt From 75b6a902a2ad2dd06dc0f1662ada1d85bfb2da63 Mon Sep 17 00:00:00 2001 From: lewisyearsley Date: Mon, 17 Jul 2023 08:54:43 +0100 Subject: [PATCH 122/130] combine image upload methods into one --- images.go | 94 ++++++++------------------------------------------ images_test.go | 67 +++++++++-------------------------- 2 files changed, 31 insertions(+), 130 deletions(-) diff --git a/images.go b/images.go index 281f0537867..ed2d331a207 100644 --- a/images.go +++ b/images.go @@ -37,6 +37,7 @@ type Image struct { // UploadImageParams is the data required for an Image Upload request. type UploadImageParams struct { File io.ReadCloser + Url string Name string RequireSignedURLs bool Metadata map[string]interface{} @@ -45,63 +46,36 @@ type UploadImageParams struct { // write writes the image upload data to a multipart writer, so // it can be used in an HTTP request. func (b UploadImageParams) write(mpw *multipart.Writer) error { - if b.File == nil { - return errors.New("a file to upload must be specified") + if b.File == nil && b.Url == "" { + return errors.New("a file or url to upload must be specified") } - name := b.Name - part, err := mpw.CreateFormFile("file", name) - if err != nil { - return err - } - _, err = io.Copy(part, b.File) - if err != nil { - _ = b.File.Close() - return err - } - _ = b.File.Close() - // According to the Cloudflare docs, this field defaults to false. - // For simplicity, we will only send it if the value is true, however - // if the default is changed to true, this logic will need to be updated. - if b.RequireSignedURLs { - err = mpw.WriteField("requireSignedURLs", "true") + if b.File != nil { + name := b.Name + part, err := mpw.CreateFormFile("file", name) if err != nil { return err } - } - - if b.Metadata != nil { - part, err = mpw.CreateFormField("metadata") + _, err = io.Copy(part, b.File) if err != nil { + _ = b.File.Close() return err } - err = json.NewEncoder(part).Encode(b.Metadata) + _ = b.File.Close() + } + + if b.Url != "" { + err := mpw.WriteField("url", b.Url) if err != nil { return err } } - return nil -} - -// UploadImageByUrlParams is the data required for an Image Upload by URL request. -type UploadImageByUrlParams struct { - Url string - RequireSignedURLs bool - Metadata map[string]interface{} -} - -func (b UploadImageByUrlParams) write(mpw *multipart.Writer) error { - err := mpw.WriteField("url", b.Url) - if err != nil { - return err - } - // According to the Cloudflare docs, this field defaults to false. // For simplicity, we will only send it if the value is true, however // if the default is changed to true, this logic will need to be updated. if b.RequireSignedURLs { - err = mpw.WriteField("requireSignedURLs", "true") + err := mpw.WriteField("requireSignedURLs", "true") if err != nil { return err } @@ -220,46 +194,6 @@ func (api *API) UploadImage(ctx context.Context, rc *ResourceContainer, params U return imageDetailsResponse.Result, nil } -// UploadImageByUrl uploads a single image from a given url. -// -// API Reference: https://api.cloudflare.com/#cloudflare-images-upload-an-image-using-a-single-http-request -func (api *API) UploadImageByUrl(ctx context.Context, rc *ResourceContainer, params UploadImageByUrlParams) (Image, error) { - if rc.Level != AccountRouteLevel { - return Image{}, ErrRequiredAccountLevelResourceContainer - } - - uri := fmt.Sprintf("/accounts/%s/images/v1", rc.Identifier) - - body := &bytes.Buffer{} - w := multipart.NewWriter(body) - if err := params.write(w); err != nil { - _ = w.Close() - return Image{}, fmt.Errorf("error writing multipart body: %w", err) - } - _ = w.Close() - - res, err := api.makeRequestContextWithHeaders( - ctx, - http.MethodPost, - uri, - body, - http.Header{ - "Accept": []string{"application/json"}, - "Content-Type": []string{w.FormDataContentType()}, - }, - ) - if err != nil { - return Image{}, err - } - - var imageDetailsResponse ImageDetailsResponse - err = json.Unmarshal(res, &imageDetailsResponse) - if err != nil { - return Image{}, fmt.Errorf("%s: %w", errUnmarshalError, err) - } - return imageDetailsResponse.Result, nil -} - // UpdateImage updates an existing image's metadata. // // API Reference: https://api.cloudflare.com/#cloudflare-images-update-image diff --git a/images_test.go b/images_test.go index d4fa864838f..d723b4b75e4 100644 --- a/images_test.go +++ b/images_test.go @@ -103,7 +103,7 @@ func TestUploadImageByUrl(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) - u, err := parseImageMultipartUploadByUrl(r) + u, err := parseImageMultipartUpload(r) if !assert.NoError(t, err) { w.WriteHeader(http.StatusBadRequest) return @@ -138,7 +138,7 @@ func TestUploadImageByUrl(t *testing.T) { mux.HandleFunc("/accounts/"+testAccountID+"/images/v1", handler) want := expectedImageStruct - actual, err := client.UploadImageByUrl(context.Background(), AccountIdentifier(testAccountID), UploadImageByUrlParams{ + actual, err := client.UploadImage(context.Background(), AccountIdentifier(testAccountID), UploadImageParams{ Url: "https://www.images-elsewhere.com/avatar.png", RequireSignedURLs: true, Metadata: map[string]interface{}{ @@ -442,6 +442,7 @@ type imageMultipartUpload struct { // this is for testing, never read an entire file into memory, // especially when being done on a per-http request basis. File []byte + Url string RequireSignedURLs bool Metadata map[string]interface{} } @@ -473,62 +474,28 @@ func parseImageMultipartUpload(r *http.Request) (imageMultipartUpload, error) { } } - f, _, err := r.FormFile("file") - if err != nil { - return u, err - } - defer f.Close() - - u.File, err = io.ReadAll(f) - if err != nil { - return u, err - } - - return u, nil -} - -type imageMultipartUploadByUrl struct { - Url string - RequireSignedURLs bool - Metadata map[string]interface{} -} - -func parseImageMultipartUploadByUrl(r *http.Request) (imageMultipartUploadByUrl, error) { - var u imageMultipartUploadByUrl - mdBytes, err := getImageFormValue(r, "metadata") - if err != nil { - if !strings.HasPrefix(err.Error(), "no value found for key") { - return u, err - } - } - if mdBytes != nil { - err = json.Unmarshal(mdBytes, &u.Metadata) + if _, ok := r.MultipartForm.Value["url"]; ok { + urlBytes, err := getImageFormValue(r, "url") if err != nil { - return u, err + if !strings.HasPrefix(err.Error(), "no value found for key") { + return u, err + } } - } - - rsuBytes, err := getImageFormValue(r, "requireSignedURLs") - if err != nil { - if !strings.HasPrefix(err.Error(), "no value found for key") { - return u, err + if urlBytes != nil { + u.Url = string(urlBytes) } - } - if rsuBytes != nil { - if bytes.Equal(rsuBytes, []byte("true")) { - u.RequireSignedURLs = true + } else { + f, _, err := r.FormFile("file") + if err != nil { + return u, err } - } + defer f.Close() - urlBytes, err := getImageFormValue(r, "url") - if err != nil { - if !strings.HasPrefix(err.Error(), "no value found for key") { + u.File, err = io.ReadAll(f) + if err != nil { return u, err } } - if urlBytes != nil { - u.Url = string(urlBytes) - } return u, nil } From ee3da50605bc97ad48ddc384cb1d1c3a2e7671cc Mon Sep 17 00:00:00 2001 From: joshuamsager Date: Mon, 17 Jul 2023 12:01:21 -0400 Subject: [PATCH 123/130] Add Regional Tiered Cache API support --- regional_tiered_cache.go | 82 +++++++++++++++++++++++++++++++ regional_tiered_cache_test.go | 90 +++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 regional_tiered_cache.go create mode 100644 regional_tiered_cache_test.go diff --git a/regional_tiered_cache.go b/regional_tiered_cache.go new file mode 100644 index 00000000000..4451fac8ea0 --- /dev/null +++ b/regional_tiered_cache.go @@ -0,0 +1,82 @@ +package cloudflare + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "time" +) + +// RegionalTieredCache is the structure of the API object for the regional tiered cache +// setting. +type RegionalTieredCache struct { + ID string `json:"id,omitempty"` + ModifiedOn time.Time `json:"modified_on,omitempty"` + Value string `json:"value"` +} + +// RegionalTieredCacheDetailsResponse is the API response for the regional tiered cache +// setting. +type RegionalTieredCacheDetailsResponse struct { + Result RegionalTieredCache `json:"result"` + Response +} + +type zoneRegionalTieredCacheSingleResponse struct { + Response + Result RegionalTieredCache `json:"result"` +} + +type GetRegionalTieredCacheParams struct{} + +type UpdateRegionalTieredCacheParams struct { + Value string `json:"value"` +} + +// GetRegionalTieredCache returns information about the current regional tiered cache settings. +// +// API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-get-regional-tiered-cache-setting +func (api *API) GetRegionalTieredCache(ctx context.Context, rc *ResourceContainer, params GetRegionalTieredCacheParams) (RegionalTieredCache, error) { + if rc.Level != ZoneRouteLevel { + return RegionalTieredCache{}, ErrRequiredZoneLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/cache/regional_tiered_cache", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return RegionalTieredCache{}, err + } + + var RegionalTieredCacheDetailsResponse RegionalTieredCacheDetailsResponse + err = json.Unmarshal(res, &RegionalTieredCacheDetailsResponse) + if err != nil { + return RegionalTieredCache{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + return RegionalTieredCacheDetailsResponse.Result, nil +} + +// UpdateRegionalTieredCache updates the regional tiered cache setting for a zone +// +// API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-change-regional-tiered-cache-setting +func (api *API) UpdateRegionalTieredCache(ctx context.Context, rc *ResourceContainer, params UpdateRegionalTieredCacheParams) (RegionalTieredCache, error) { + if rc.Level != ZoneRouteLevel { + return RegionalTieredCache{}, ErrRequiredZoneLevelResourceContainer + } + + uri := fmt.Sprintf("/%s/%s/cache/regional_tiered_cache", rc.Level, rc.Identifier) + + res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params) + if err != nil { + return RegionalTieredCache{}, err + } + + response := &zoneRegionalTieredCacheSingleResponse{} + err = json.Unmarshal(res, &response) + if err != nil { + return RegionalTieredCache{}, fmt.Errorf("%s: %w", errUnmarshalError, err) + } + + return response.Result, nil +} diff --git a/regional_tiered_cache_test.go b/regional_tiered_cache_test.go new file mode 100644 index 00000000000..30ae210ffc2 --- /dev/null +++ b/regional_tiered_cache_test.go @@ -0,0 +1,90 @@ +package cloudflare + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var regionalTieredCacheTimestampString = "2019-02-20T22:37:07.107449Z" +var regionalTieredCacheTimestamp, _ = time.Parse(time.RFC3339Nano, regionalTieredCacheTimestampString) + +func TestRegionalTieredCache(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": "regional_tiered_cache", + "value": "on", + "modified_on": "%s" + } + } + `, regionalTieredCacheTimestampString) + } + + mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/regional_tiered_cache", handler) + want := RegionalTieredCache{ + ID: "regional_tiered_cache", + Value: "on", + ModifiedOn: regionalTieredCacheTimestamp, + } + + actual, err := client.GetRegionalTieredCache( + context.Background(), + ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), + GetRegionalTieredCacheParams{}, + ) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + +func TestUpdateRegionalTieredCache(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": "regional_tiered_cache", + "value": "off", + "modified_on": "%s" + } + } + `, regionalTieredCacheTimestampString) + } + + mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/regional_tiered_cache", handler) + want := RegionalTieredCache{ + ID: "regional_tiered_cache", + Value: "off", + ModifiedOn: regionalTieredCacheTimestamp, + } + + actual, err := client.UpdateRegionalTieredCache( + context.Background(), + ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), + UpdateRegionalTieredCacheParams{Value: "off"}, + ) + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} From 96ea409bce7a48df0655aa0c37d3196f42d5ebc0 Mon Sep 17 00:00:00 2001 From: joshuamsager Date: Mon, 17 Jul 2023 12:13:39 -0400 Subject: [PATCH 124/130] changelog entry --- .changelog/1336.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1336.txt diff --git a/.changelog/1336.txt b/.changelog/1336.txt new file mode 100644 index 00000000000..f949bdc25e7 --- /dev/null +++ b/.changelog/1336.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +zone: Added `GetRegionalTieredCache` and `UpdateRegionalTieredCache` to allow setting Regional Tiered Cache for a zone. +``` From 4165acced5447870fa7053fa8b32584a01d46c2d Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 18 Jul 2023 13:43:03 +1000 Subject: [PATCH 125/130] `Url` => `URL` --- images.go | 8 ++++---- images_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/images.go b/images.go index ed2d331a207..281b49bf50f 100644 --- a/images.go +++ b/images.go @@ -37,7 +37,7 @@ type Image struct { // UploadImageParams is the data required for an Image Upload request. type UploadImageParams struct { File io.ReadCloser - Url string + URL string Name string RequireSignedURLs bool Metadata map[string]interface{} @@ -46,7 +46,7 @@ type UploadImageParams struct { // write writes the image upload data to a multipart writer, so // it can be used in an HTTP request. func (b UploadImageParams) write(mpw *multipart.Writer) error { - if b.File == nil && b.Url == "" { + if b.File == nil && b.URL == "" { return errors.New("a file or url to upload must be specified") } @@ -64,8 +64,8 @@ func (b UploadImageParams) write(mpw *multipart.Writer) error { _ = b.File.Close() } - if b.Url != "" { - err := mpw.WriteField("url", b.Url) + if b.URL != "" { + err := mpw.WriteField("url", b.URL) if err != nil { return err } diff --git a/images_test.go b/images_test.go index d723b4b75e4..7a37cf5a451 100644 --- a/images_test.go +++ b/images_test.go @@ -139,7 +139,7 @@ func TestUploadImageByUrl(t *testing.T) { want := expectedImageStruct actual, err := client.UploadImage(context.Background(), AccountIdentifier(testAccountID), UploadImageParams{ - Url: "https://www.images-elsewhere.com/avatar.png", + URL: "https://www.images-elsewhere.com/avatar.png", RequireSignedURLs: true, Metadata: map[string]interface{}{ "meta": "metaID", From 5a38e52cca775cd8e98a4b2e0becccbc82d0e9a3 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 18 Jul 2023 13:43:39 +1000 Subject: [PATCH 126/130] add test coverage for mutually exclusive options --- images.go | 4 ++++ images_test.go | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/images.go b/images.go index 281b49bf50f..59209ad1f78 100644 --- a/images.go +++ b/images.go @@ -162,6 +162,10 @@ func (api *API) UploadImage(ctx context.Context, rc *ResourceContainer, params U return Image{}, ErrRequiredAccountLevelResourceContainer } + if params.File != nil && params.URL != "" { + return Image{}, errors.New("file and url uploads are mutually exclusive and can only be performed individually") + } + uri := fmt.Sprintf("/accounts/%s/images/v1", rc.Identifier) body := &bytes.Buffer{} diff --git a/images_test.go b/images_test.go index 7a37cf5a451..43cd8ad3498 100644 --- a/images_test.go +++ b/images_test.go @@ -252,6 +252,20 @@ func TestCreateImageDirectUploadURL(t *testing.T) { } } +func TestCreateImageConflictingTypes(t *testing.T) { + setup() + defer teardown() + + _, err := client.UploadImage(context.Background(), AccountIdentifier(testAccountID), UploadImageParams{ + URL: "https://example.com/foo.jpg", + File: fakeFile{ + Buffer: bytes.NewBufferString("this is definitely an image"), + }, + }) + + assert.Error(t, err) +} + func TestCreateImageDirectUploadURLV2(t *testing.T) { setup() defer teardown() From 4b8e45e051bd7c74b8dd48ce11bcc7e3f7698702 Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 18 Jul 2023 04:19:19 +0000 Subject: [PATCH 127/130] Update CHANGELOG.md for #1335 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 238d67ab248..9a05b6462bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ BREAKING CHANGES: * rulesets: `UpdateZoneRulesetPhase` is removed in favour of `UpdateEntrypointRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) * rulesets: `UpdateZoneRuleset` is removed in favour of `UpdateRuleset` ([#1333](https://github.com/cloudflare/cloudflare-go/issues/1333)) +ENHANCEMENTS: + +* images: adds ability to upload image by url ([#1335](https://github.com/cloudflare/cloudflare-go/issues/1335)) + DEPENDENCIES: * deps: bumps golang.org/x/net from 0.11.0 to 0.12.0 ([#1328](https://github.com/cloudflare/cloudflare-go/issues/1328)) From 9c9b0d7c1ee2c5b23e89fe8350d7c21058b652a1 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 18 Jul 2023 14:21:51 +1000 Subject: [PATCH 128/130] update lint --- regional_tiered_cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regional_tiered_cache.go b/regional_tiered_cache.go index 4451fac8ea0..0994de14e2d 100644 --- a/regional_tiered_cache.go +++ b/regional_tiered_cache.go @@ -57,7 +57,7 @@ func (api *API) GetRegionalTieredCache(ctx context.Context, rc *ResourceContaine return RegionalTieredCacheDetailsResponse.Result, nil } -// UpdateRegionalTieredCache updates the regional tiered cache setting for a zone +// UpdateRegionalTieredCache updates the regional tiered cache setting for a zone. // // API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-change-regional-tiered-cache-setting func (api *API) UpdateRegionalTieredCache(ctx context.Context, rc *ResourceContainer, params UpdateRegionalTieredCacheParams) (RegionalTieredCache, error) { From b29950dcc417acde778ae456a42fe0366cc6ac20 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Tue, 18 Jul 2023 14:24:08 +1000 Subject: [PATCH 129/130] swap out hardcoded zone IDs for testZoneID --- regional_tiered_cache.go | 6 ++++-- regional_tiered_cache_test.go | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/regional_tiered_cache.go b/regional_tiered_cache.go index 0994de14e2d..31471178ada 100644 --- a/regional_tiered_cache.go +++ b/regional_tiered_cache.go @@ -34,7 +34,8 @@ type UpdateRegionalTieredCacheParams struct { Value string `json:"value"` } -// GetRegionalTieredCache returns information about the current regional tiered cache settings. +// GetRegionalTieredCache returns information about the current regional tiered +// cache settings. // // API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-get-regional-tiered-cache-setting func (api *API) GetRegionalTieredCache(ctx context.Context, rc *ResourceContainer, params GetRegionalTieredCacheParams) (RegionalTieredCache, error) { @@ -57,7 +58,8 @@ func (api *API) GetRegionalTieredCache(ctx context.Context, rc *ResourceContaine return RegionalTieredCacheDetailsResponse.Result, nil } -// UpdateRegionalTieredCache updates the regional tiered cache setting for a zone. +// UpdateRegionalTieredCache updates the regional tiered cache setting for a +// zone. // // API reference: https://developers.cloudflare.com/api/operations/zone-cache-settings-change-regional-tiered-cache-setting func (api *API) UpdateRegionalTieredCache(ctx context.Context, rc *ResourceContainer, params UpdateRegionalTieredCacheParams) (RegionalTieredCache, error) { diff --git a/regional_tiered_cache_test.go b/regional_tiered_cache_test.go index 30ae210ffc2..df74f3bfe29 100644 --- a/regional_tiered_cache_test.go +++ b/regional_tiered_cache_test.go @@ -33,7 +33,7 @@ func TestRegionalTieredCache(t *testing.T) { `, regionalTieredCacheTimestampString) } - mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/regional_tiered_cache", handler) + mux.HandleFunc("/zones/"+testZoneID+"/cache/regional_tiered_cache", handler) want := RegionalTieredCache{ ID: "regional_tiered_cache", Value: "on", @@ -42,7 +42,7 @@ func TestRegionalTieredCache(t *testing.T) { actual, err := client.GetRegionalTieredCache( context.Background(), - ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), + ZoneIdentifier(testZoneID), GetRegionalTieredCacheParams{}, ) @@ -71,7 +71,7 @@ func TestUpdateRegionalTieredCache(t *testing.T) { `, regionalTieredCacheTimestampString) } - mux.HandleFunc("/zones/01a7362d577a6c3019a474fd6f485823/cache/regional_tiered_cache", handler) + mux.HandleFunc("/zones/"+testZoneID+"/cache/regional_tiered_cache", handler) want := RegionalTieredCache{ ID: "regional_tiered_cache", Value: "off", @@ -80,7 +80,7 @@ func TestUpdateRegionalTieredCache(t *testing.T) { actual, err := client.UpdateRegionalTieredCache( context.Background(), - ZoneIdentifier("01a7362d577a6c3019a474fd6f485823"), + ZoneIdentifier(testZoneID), UpdateRegionalTieredCacheParams{Value: "off"}, ) From a6d449b740021e442e709c9526e13dda7a45768b Mon Sep 17 00:00:00 2001 From: changelogbot Date: Tue, 18 Jul 2023 04:28:46 +0000 Subject: [PATCH 130/130] Update CHANGELOG.md for #1336 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a05b6462bf..e1f0900bdb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ BREAKING CHANGES: ENHANCEMENTS: * images: adds ability to upload image by url ([#1335](https://github.com/cloudflare/cloudflare-go/issues/1335)) +* zone: Added `GetRegionalTieredCache` and `UpdateRegionalTieredCache` to allow setting Regional Tiered Cache for a zone. ([#1336](https://github.com/cloudflare/cloudflare-go/issues/1336)) DEPENDENCIES: