From a98482d3ca4c24ba1fbc26c4c9cd33de4dded521 Mon Sep 17 00:00:00 2001 From: Akemi Davisson Date: Thu, 16 Jun 2022 08:58:26 -0500 Subject: [PATCH 1/8] Adds recently supported per_page/pagination teams_list --- internal/provider/resource_cloudflare_teams_list.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/provider/resource_cloudflare_teams_list.go b/internal/provider/resource_cloudflare_teams_list.go index a30f589d0b..66413bb707 100644 --- a/internal/provider/resource_cloudflare_teams_list.go +++ b/internal/provider/resource_cloudflare_teams_list.go @@ -73,6 +73,7 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData listItems, _, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ AccountID: accountID, ListID: d.Id(), + PaginationOptions: cloudflare.PaginationOptions{ PerPage: 1000 }, }) if err != nil { return diag.FromErr(fmt.Errorf("error finding Teams List %q: %w", d.Id(), err)) From e1a338400a4da8b501238b563525cb2ff60085fb Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 20 Jun 2022 15:03:30 +1000 Subject: [PATCH 2/8] iterate all available team list items --- .../resource_cloudflare_teams_list.go | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/internal/provider/resource_cloudflare_teams_list.go b/internal/provider/resource_cloudflare_teams_list.go index 66413bb707..9b18c6b0fc 100644 --- a/internal/provider/resource_cloudflare_teams_list.go +++ b/internal/provider/resource_cloudflare_teams_list.go @@ -70,15 +70,32 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData d.Set("type", list.Type) d.Set("description", list.Description) - listItems, _, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ - AccountID: accountID, - ListID: d.Id(), - PaginationOptions: cloudflare.PaginationOptions{ PerPage: 1000 }, + var allListItems []cloudflare.TeamsListItem + + listItems, responseInfo, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ + AccountID: accountID, + ListID: d.Id(), + PaginationOptions: cloudflare.PaginationOptions{PerPage: 1000}, }) if err != nil { return diag.FromErr(fmt.Errorf("error finding Teams List %q: %w", d.Id(), err)) } - d.Set("items", convertListItemsToSchema(listItems)) + + allListItems = append(allListItems, listItems...) + + for i := 2; i < responseInfo.TotalPages; i++ { + listItems, _, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ + AccountID: accountID, + ListID: d.Id(), + PaginationOptions: cloudflare.PaginationOptions{PerPage: 1000, Page: i}, + }) + if err != nil { + return diag.FromErr(fmt.Errorf("error finding Teams List %q: %w", d.Id(), err)) + } + allListItems = append(allListItems, listItems...) + } + + d.Set("items", convertListItemsToSchema(allListItems)) return nil } From e62fb75762c994d121aa1eeec78c5c6a52094377 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 20 Jun 2022 15:29:59 +1000 Subject: [PATCH 3/8] add changelog --- .changelog/1706.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/1706.txt diff --git a/.changelog/1706.txt b/.changelog/1706.txt new file mode 100644 index 0000000000..356f384718 --- /dev/null +++ b/.changelog/1706.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/cloudflare_teams_list: handle pagination for larger Team List accounts +``` From 59a50e425021c7751e1d2e3f2aad0907fd0e941a Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 22 Jun 2022 15:14:31 +1000 Subject: [PATCH 4/8] fix loop logic for trailing page --- internal/provider/resource_cloudflare_teams_list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/provider/resource_cloudflare_teams_list.go b/internal/provider/resource_cloudflare_teams_list.go index 9b18c6b0fc..8f8a55c6d0 100644 --- a/internal/provider/resource_cloudflare_teams_list.go +++ b/internal/provider/resource_cloudflare_teams_list.go @@ -83,7 +83,7 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData allListItems = append(allListItems, listItems...) - for i := 2; i < responseInfo.TotalPages; i++ { + for i := 2; i <= responseInfo.TotalPages; i++ { listItems, _, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ AccountID: accountID, ListID: d.Id(), From 6c305da89fcb2466f982569cafd31fcae5630748 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 21 Jul 2022 12:45:41 +1000 Subject: [PATCH 5/8] fix test setup --- internal/provider/resource_cloudflare_teams_list_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/provider/resource_cloudflare_teams_list_test.go b/internal/provider/resource_cloudflare_teams_list_test.go index 410de1d22e..77218b9ace 100644 --- a/internal/provider/resource_cloudflare_teams_list_test.go +++ b/internal/provider/resource_cloudflare_teams_list_test.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) -func TestAccCloudflareTeamsListBasic(t *testing.T) { +func TestAccCloudflareTeamsList_Basic(t *testing.T) { // Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access // service does not yet support the API tokens and it results in // misleading state error messages. @@ -27,6 +27,7 @@ func TestAccCloudflareTeamsListBasic(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { + testAccPreCheck(t) testAccessAccPreCheck(t) }, ProviderFactories: providerFactories, @@ -47,7 +48,7 @@ func TestAccCloudflareTeamsListBasic(t *testing.T) { }) } -func TestAccCloudflareTeamsListReordered(t *testing.T) { +func TestAccCloudflareTeamsList_Reordered(t *testing.T) { // Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access // service does not yet support the API tokens and it results in // misleading state error messages. @@ -62,6 +63,7 @@ func TestAccCloudflareTeamsListReordered(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { + testAccPreCheck(t) testAccessAccPreCheck(t) }, ProviderFactories: providerFactories, From 053fd68a944bf43753377db3b18d3bbce09985fc Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Thu, 20 Oct 2022 12:32:51 +1100 Subject: [PATCH 6/8] resource/cloudflare_teams_list: update to use built in iterator --- .../resource_cloudflare_teams_list.go | 43 +++++--------- .../resource_cloudflare_teams_list_test.go | 57 ++++++++++++++++++- 2 files changed, 69 insertions(+), 31 deletions(-) diff --git a/internal/provider/resource_cloudflare_teams_list.go b/internal/provider/resource_cloudflare_teams_list.go index 7b09f24813..be3d40fe93 100644 --- a/internal/provider/resource_cloudflare_teams_list.go +++ b/internal/provider/resource_cloudflare_teams_list.go @@ -28,7 +28,7 @@ func resourceCloudflareTeamsList() *schema.Resource { func resourceCloudflareTeamsListCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*cloudflare.API) - newTeamsList := cloudflare.TeamsList{ + newTeamsList := cloudflare.CreateTeamsListParams{ Name: d.Get("name").(string), Type: d.Get("type").(string), Description: d.Get("description").(string), @@ -43,7 +43,7 @@ func resourceCloudflareTeamsListCreate(ctx context.Context, d *schema.ResourceDa accountID := d.Get("account_id").(string) - list, err := client.CreateTeamsList(ctx, accountID, newTeamsList) + list, err := client.CreateTeamsList(ctx, cloudflare.AccountIdentifier(accountID), newTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error creating Teams List for account %q: %w", accountID, err)) } @@ -57,7 +57,7 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData client := meta.(*cloudflare.API) accountID := d.Get("account_id").(string) - list, err := client.TeamsList(ctx, accountID, d.Id()) + list, err := client.GetTeamsList(ctx, cloudflare.AccountIdentifier(accountID), d.Id()) if err != nil { var notFoundError *cloudflare.NotFoundError if errors.As(err, ¬FoundError) { @@ -72,32 +72,14 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData d.Set("type", list.Type) d.Set("description", list.Description) - var allListItems []cloudflare.TeamsListItem - - listItems, responseInfo, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ - AccountID: accountID, - ListID: d.Id(), - PaginationOptions: cloudflare.PaginationOptions{PerPage: 1000}, + listItems, _, err := client.ListTeamsListItems(ctx, cloudflare.AccountIdentifier(accountID), cloudflare.ListTeamsListItemsParams{ + ListID: d.Id(), }) if err != nil { return diag.FromErr(fmt.Errorf("error finding Teams List %q: %w", d.Id(), err)) } - allListItems = append(allListItems, listItems...) - - for i := 2; i <= responseInfo.TotalPages; i++ { - listItems, _, err := client.TeamsListItems(ctx, cloudflare.TeamsListItemsParams{ - AccountID: accountID, - ListID: d.Id(), - PaginationOptions: cloudflare.PaginationOptions{PerPage: 1000, Page: i}, - }) - if err != nil { - return diag.FromErr(fmt.Errorf("error finding Teams List %q: %w", d.Id(), err)) - } - allListItems = append(allListItems, listItems...) - } - - d.Set("items", convertListItemsToSchema(allListItems)) + d.Set("items", convertListItemsToSchema(listItems)) return nil } @@ -105,7 +87,7 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData func resourceCloudflareTeamsListUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*cloudflare.API) - updatedTeamsList := cloudflare.TeamsList{ + updatedTeamsList := cloudflare.UpdateTeamsListParams{ ID: d.Id(), Name: d.Get("name").(string), Type: d.Get("type").(string), @@ -116,7 +98,7 @@ func resourceCloudflareTeamsListUpdate(ctx context.Context, d *schema.ResourceDa accountID := d.Get("account_id").(string) - teamsList, err := client.UpdateTeamsList(ctx, accountID, updatedTeamsList) + teamsList, err := client.UpdateTeamsList(ctx, cloudflare.AccountIdentifier(accountID), updatedTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error updating Teams List for account %q: %w", accountID, err)) } @@ -128,9 +110,10 @@ func resourceCloudflareTeamsListUpdate(ctx context.Context, d *schema.ResourceDa oldItemsIface, newItemsIface := d.GetChange("items") oldItems := oldItemsIface.(*schema.Set).List() newItems := newItemsIface.(*schema.Set).List() - patchTeamsList := cloudflare.PatchTeamsList{ID: d.Id()} + patchTeamsList := cloudflare.PatchTeamsListParams{ID: d.Id()} setListItemDiff(&patchTeamsList, oldItems, newItems) - l, err := client.PatchTeamsList(ctx, accountID, patchTeamsList) + + l, err := client.PatchTeamsList(ctx, cloudflare.AccountIdentifier(accountID), patchTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error updating Teams List for account %q: %w", accountID, err)) } @@ -148,7 +131,7 @@ func resourceCloudflareTeamsListDelete(ctx context.Context, d *schema.ResourceDa tflog.Debug(ctx, fmt.Sprintf("Deleting Cloudflare Teams List using ID: %s", appID)) - err := client.DeleteTeamsList(ctx, accountID, appID) + err := client.DeleteTeamsList(ctx, cloudflare.AccountIdentifier(accountID), appID) if err != nil { return diag.FromErr(fmt.Errorf("error deleting Teams List for account %q: %w", accountID, err)) } @@ -177,7 +160,7 @@ func resourceCloudflareTeamsListImport(ctx context.Context, d *schema.ResourceDa return []*schema.ResourceData{d}, nil } -func setListItemDiff(patchList *cloudflare.PatchTeamsList, oldItems, newItems []interface{}) { +func setListItemDiff(patchList *cloudflare.PatchTeamsListParams, oldItems, newItems []interface{}) { counts := make(map[string]int) for _, val := range newItems { counts[val.(string)] += 1 diff --git a/internal/provider/resource_cloudflare_teams_list_test.go b/internal/provider/resource_cloudflare_teams_list_test.go index 77218b9ace..114795a5f9 100644 --- a/internal/provider/resource_cloudflare_teams_list_test.go +++ b/internal/provider/resource_cloudflare_teams_list_test.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "os" + "strconv" + "strings" "testing" "github.com/cloudflare/cloudflare-go" @@ -48,6 +50,42 @@ func TestAccCloudflareTeamsList_Basic(t *testing.T) { }) } +func TestAccCloudflareTeamsList_LottaListItems(t *testing.T) { + // Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access + // service does not yet support the API tokens and it results in + // misleading state error messages. + if os.Getenv("CLOUDFLARE_API_TOKEN") != "" { + defer func(apiToken string) { + os.Setenv("CLOUDFLARE_API_TOKEN", apiToken) + }(os.Getenv("CLOUDFLARE_API_TOKEN")) + os.Setenv("CLOUDFLARE_API_TOKEN", "") + } + + rnd := generateRandomResourceName() + name := fmt.Sprintf("cloudflare_teams_list.%s", rnd) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccessAccPreCheck(t) + }, + ProviderFactories: providerFactories, + CheckDestroy: testAccCheckCloudflareTeamsListDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCloudflareTeamsListConfigBigItemCount(rnd, accountID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "account_id", accountID), + resource.TestCheckResourceAttr(name, "name", rnd), + resource.TestCheckResourceAttr(name, "type", "SERIAL"), + resource.TestCheckResourceAttr(name, "description", "My description"), + resource.TestCheckResourceAttr(name, "items.#", "1000"), + ), + }, + }, + }) +} + func TestAccCloudflareTeamsList_Reordered(t *testing.T) { // Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the Access // service does not yet support the API tokens and it results in @@ -91,6 +129,23 @@ resource "cloudflare_teams_list" "%[1]s" { `, rnd, accountID) } +func testAccCloudflareTeamsListConfigBigItemCount(rnd, accountID string) string { + items := []string{} + for i := 0; i < 1000; i++ { + items = append(items, `"example-`+strconv.Itoa(i)+`"`) + } + + return fmt.Sprintf(` +resource "cloudflare_teams_list" "%[1]s" { + account_id = "%[2]s" + name = "%[1]s" + description = "My description" + type = "SERIAL" + items = [%[3]s] +} +`, rnd, accountID, strings.Join(items, ",")) +} + func testAccCloudflareTeamsListConfigReorderedItems(rnd, accountID string) string { return fmt.Sprintf(` resource "cloudflare_teams_list" "%[1]s" { @@ -111,7 +166,7 @@ func testAccCheckCloudflareTeamsListDestroy(s *terraform.State) error { continue } - _, err := client.TeamsList(context.Background(), rs.Primary.Attributes["account_id"], rs.Primary.ID) + _, err := client.GetTeamsList(context.Background(), cloudflare.AccountIdentifier(rs.Primary.Attributes["account_id"]), rs.Primary.ID) if err == nil { return fmt.Errorf("Teams List still exists") } From b5215812f35ea834bbbde4d8a0d595986f446c1a Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 31 Oct 2022 11:37:09 +1100 Subject: [PATCH 7/8] swap to t.Setenv --- internal/provider/resource_cloudflare_teams_list_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/internal/provider/resource_cloudflare_teams_list_test.go b/internal/provider/resource_cloudflare_teams_list_test.go index 8d53edf76e..49eb358cd5 100644 --- a/internal/provider/resource_cloudflare_teams_list_test.go +++ b/internal/provider/resource_cloudflare_teams_list_test.go @@ -85,10 +85,7 @@ func TestAccCloudflareTeamsList_Reordered(t *testing.T) { // service does not yet support the API tokens and it results in // misleading state error messages. if os.Getenv("CLOUDFLARE_API_TOKEN") != "" { - defer func(apiToken string) { - os.Setenv("CLOUDFLARE_API_TOKEN", apiToken) - }(os.Getenv("CLOUDFLARE_API_TOKEN")) - os.Setenv("CLOUDFLARE_API_TOKEN", "") + t.Setenv("CLOUDFLARE_API_TOKEN", "") } rnd := generateRandomResourceName() @@ -160,7 +157,7 @@ func testAccCheckCloudflareTeamsListDestroy(s *terraform.State) error { continue } - identifier := cloudflare.AccountIdentifier(rs.Primary.Attributes["account_id"]) + identifier := cloudflare.AccountIdentifier(rs.Primary.Attributes["account_id"]) _, err := client.GetTeamsList(context.Background(), identifier, rs.Primary.ID) if err == nil { return fmt.Errorf("Teams List still exists") From e98fa40dadb0a7b5d069d4dd30611c7017d30680 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 31 Oct 2022 11:38:09 +1100 Subject: [PATCH 8/8] clean up indentation --- internal/provider/resource_cloudflare_teams_list.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/provider/resource_cloudflare_teams_list.go b/internal/provider/resource_cloudflare_teams_list.go index ab06708845..48dc38c2df 100644 --- a/internal/provider/resource_cloudflare_teams_list.go +++ b/internal/provider/resource_cloudflare_teams_list.go @@ -42,8 +42,8 @@ func resourceCloudflareTeamsListCreate(ctx context.Context, d *schema.ResourceDa tflog.Debug(ctx, fmt.Sprintf("Creating Cloudflare Teams List from struct: %+v", newTeamsList)) accountID := d.Get("account_id").(string) - - identifier := cloudflare.AccountIdentifier(accountID) + + identifier := cloudflare.AccountIdentifier(accountID) list, err := client.CreateTeamsList(ctx, identifier, newTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error creating Teams List for account %q: %w", accountID, err)) @@ -75,7 +75,7 @@ func resourceCloudflareTeamsListRead(ctx context.Context, d *schema.ResourceData d.Set("type", list.Type) d.Set("description", list.Description) - listItems, _, err := client.ListTeamsListItems(ctx, identifier, cloudflare.ListTeamsListItemsParams{ + listItems, _, err := client.ListTeamsListItems(ctx, identifier, cloudflare.ListTeamsListItemsParams{ ListID: d.Id(), }) if err != nil { @@ -101,7 +101,7 @@ func resourceCloudflareTeamsListUpdate(ctx context.Context, d *schema.ResourceDa accountID := d.Get("account_id").(string) - identifier := cloudflare.AccountIdentifier(accountID) + identifier := cloudflare.AccountIdentifier(accountID) teamsList, err := client.UpdateTeamsList(ctx, identifier, updatedTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error updating Teams List for account %q: %w", accountID, err)) @@ -117,7 +117,7 @@ func resourceCloudflareTeamsListUpdate(ctx context.Context, d *schema.ResourceDa patchTeamsList := cloudflare.PatchTeamsListParams{ID: d.Id()} setListItemDiff(&patchTeamsList, oldItems, newItems) - l, err := client.PatchTeamsList(ctx, identifier, patchTeamsList) + l, err := client.PatchTeamsList(ctx, identifier, patchTeamsList) if err != nil { return diag.FromErr(fmt.Errorf("error updating Teams List for account %q: %w", accountID, err)) @@ -136,7 +136,7 @@ func resourceCloudflareTeamsListDelete(ctx context.Context, d *schema.ResourceDa tflog.Debug(ctx, fmt.Sprintf("Deleting Cloudflare Teams List using ID: %s", appID)) - identifier := cloudflare.AccountIdentifier(accountID) + identifier := cloudflare.AccountIdentifier(accountID) err := client.DeleteTeamsList(ctx, identifier, appID) if err != nil { return diag.FromErr(fmt.Errorf("error deleting Teams List for account %q: %w", accountID, err))