From 13f4fbdee20f4e0cbe5c67a24b0e71e438acb1f8 Mon Sep 17 00:00:00 2001 From: Ryan Riddle <169712509+ryan-riddle-opal@users.noreply.github.com> Date: Tue, 28 Oct 2025 11:21:54 -0400 Subject: [PATCH] add pagination to bundles and delegations --- .speakeasy/gen.lock | 16 +- .speakeasy/workflow.lock | 11 +- README.md | 2 +- docs/data-sources/delegations.md | 2 - .../paginated_bundle_group_list.md | 2 - docs/data-sources/paginated_bundle_list.md | 6 +- .../paginated_bundle_resource_list.md | 2 - docs/index.md | 2 +- .../opal_delegations/data-source.tf | 1 - .../data-source.tf | 1 - .../opal_paginated_bundle_list/data-source.tf | 5 +- .../data-source.tf | 1 - examples/provider/provider.tf | 2 +- gen.yaml | 3 +- go.mod | 1 + go.sum | 2 + internal/provider/delegations_data_source.go | 30 ++- .../provider/delegations_data_source_sdk.go | 18 +- .../paginatedbundlegrouplist_data_source.go | 25 ++- ...aginatedbundlegrouplist_data_source_sdk.go | 18 +- .../paginatedbundlelist_data_source.go | 25 ++- .../paginatedbundlelist_data_source_sdk.go | 18 +- ...paginatedbundleresourcelist_data_source.go | 25 ++- ...natedbundleresourcelist_data_source_sdk.go | 18 +- internal/sdk/bundles.go | 210 ++++++++++++++++++ internal/sdk/delegations.go | 73 ++++++ internal/sdk/models/operations/denyrequest.go | 9 + .../sdk/models/operations/getbundlegroups.go | 2 + .../models/operations/getbundleresources.go | 2 + internal/sdk/models/operations/getbundles.go | 2 + .../sdk/models/operations/getdelegations.go | 2 + internal/sdk/opalapi.go | 6 +- openapi.yaml | 50 +++++ terraform_overlay.yaml | 48 ++++ 34 files changed, 518 insertions(+), 122 deletions(-) diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index b2eb456a..6bb4f055 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: b5c8bf75-06e1-47c8-b9ae-ce49ba56069d management: - docChecksum: 1366c58606ef39f06fd8da2f5cd0c577 + docChecksum: 45e1f288aa81f854581b825bfe323380 docVersion: "1.0" - speakeasyVersion: 1.639.1 - generationVersion: 2.730.0 - releaseVersion: 3.3.2 - configChecksum: baa23f67f8df8977e52c5911761aa6ea + speakeasyVersion: 1.642.1 + generationVersion: 2.731.4 + releaseVersion: 3.4.0 + configChecksum: 4f71ba5463e7f25051330975118aac14 repoURL: https://github.com/opalsecurity/terraform-provider-opal.git repoSubDirectory: . published: true @@ -23,10 +23,11 @@ features: inputOutputModels: 2.83.0 nameOverrides: 2.81.3 nullables: 0.0.0 + pagination: 2.83.3 retries: 2.81.4 serverIDs: 2.81.1 sets: 0.1.2 - unions: 2.82.0 + unions: 2.82.1 generatedFiles: - .gitattributes - USAGE.md @@ -1762,7 +1763,7 @@ examples: path: id: "83015915-58ae-4cce-b92d-608ff073ece1" requestBody: - application/json: {"comment": "Denied due to insufficient justification"} + application/json: {"comment": "Denied due to insufficient justification", "level": "REGULAR"} responses: "200": application/json: {"request": {"created_at": "2021-01-06T20:00:00Z", "duration_minutes": 1440, "id": "7c86c85d-0651-43e2-a748-d69d658418e8", "reason": "I need this resource.", "requester_id": "c86c85d-0651-43e2-a748-d69d658418e8", "reviewer_stages": [{"item_id": "f454d283-ca87-4a8a-bdbb-df212eca5353", "item_name": "", "stages": [{"operator": "AND", "reviewers": [{"id": "7c86c85d-0651-43e2-a748-d69d658418e8", "status": "PENDING"}], "stage": 1}, {"operator": "OR", "reviewers": [{"id": "8d86c85d-0651-43e2-a748-d69d658418e9", "status": "APPROVED"}], "stage": 2}]}], "status": "CANCELED", "target_group_id": "r86c85d-0651-43e2-a748-d69d658418e8", "target_user_id": "r86c85d-0651-43e2-a748-d69d658418e8", "updated_at": "2021-01-06T20:00:00Z"}} @@ -1776,4 +1777,3 @@ examples: application/json: {"comments": [{"comment": "This is a comment.", "created_at": "2021-01-06T20:00:00Z", "request_id": "4c86c85d-0651-43e2-a748-d69d658418e8", "user_id": "c86c85d-0651-43e2-a748-d69d658418e8"}]} examplesVersion: 1.0.2 generatedTests: {} -releaseNotes: "## Terraform SDK Changes Detected:\n* `Opal-API.groups.create_user()`: `response` **Changed**\n* `Opal-API.groups.get_user_groups()`: `response.results.[]` **Changed**\n* `Opal-API.groups.get_users()`: `response.results.[]` **Changed**\n* `Opal-API.groups.update_group_user()`: `response` **Changed**\n* `Opal-API.non-human-identities.get_nhis()`: `response.results.[].remote_info.oracle_fusion_role` **Added**\n* `Opal-API.resources.create()`: \n * `request.remote_info.oracle_fusion_role` **Added**\n * `response.remote_info.oracle_fusion_role` **Added**\n* `Opal-API.resources.get()`: \n * `request.resource_type_filter` **Changed**\n * `response.results.[].remote_info.oracle_fusion_role` **Added**\n* `Opal-API.resources.get_id()`: `response.remote_info.oracle_fusion_role` **Added**\n" diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 37192bcc..a790dae1 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,19 +1,18 @@ -speakeasyVersion: 1.639.1 +speakeasyVersion: 1.642.1 sources: opal-terraform-provider: sourceNamespace: opal-terraform-provider - sourceRevisionDigest: sha256:84a58be9cff672a0c002be69ed2562bc62b4767dfa4364dfbcb3c66f00a39aea - sourceBlobDigest: sha256:1a28f2306ca10e79c0f73ec1de76e705f9c404d5291a1e5a68a73f18a3970991 + sourceRevisionDigest: sha256:578b959ccab6b6c7378d3d67c2cdabbf890d27b6b2a8ab6f2a1eaee6ffb4860a + sourceBlobDigest: sha256:9a4da2bbf6f499be134a4c305a862536de675cc67994c6b3ef2f3dde085c6327 tags: - latest - - speakeasy-sdk-regen-1757722489 - "1.0" targets: terraform: source: opal-terraform-provider sourceNamespace: opal-terraform-provider - sourceRevisionDigest: sha256:84a58be9cff672a0c002be69ed2562bc62b4767dfa4364dfbcb3c66f00a39aea - sourceBlobDigest: sha256:1a28f2306ca10e79c0f73ec1de76e705f9c404d5291a1e5a68a73f18a3970991 + sourceRevisionDigest: sha256:578b959ccab6b6c7378d3d67c2cdabbf890d27b6b2a8ab6f2a1eaee6ffb4860a + sourceBlobDigest: sha256:9a4da2bbf6f499be134a4c305a862536de675cc67994c6b3ef2f3dde085c6327 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index b1166ebc..557347cd 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ terraform { required_providers { opal = { source = "opalsecurity/opal" - version = "3.3.2" + version = "3.4.0" } } } diff --git a/docs/data-sources/delegations.md b/docs/data-sources/delegations.md index 9e6ce65a..3e21a768 100644 --- a/docs/data-sources/delegations.md +++ b/docs/data-sources/delegations.md @@ -17,7 +17,6 @@ data "opal_delegations" "my_delegations" { cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" delegate_user_id = "29827fb8-f2dd-4e80-9576-28e31e9934ac" delegator_user_id = "29827fb8-f2dd-4e80-9576-28e31e9934ac" - page_size = 200 } ``` @@ -29,7 +28,6 @@ data "opal_delegations" "my_delegations" { - `cursor` (String) A cursor to indicate where to start fetching results. - `delegate_user_id` (String) The delegate user ID to filter delegations by the user being delegated to. - `delegator_user_id` (String) The delegator user ID to filter delegations by the user delegating their access review requests. -- `page_size` (Number) The maximum number of results to return per page. The default is 200. ### Read-Only diff --git a/docs/data-sources/paginated_bundle_group_list.md b/docs/data-sources/paginated_bundle_group_list.md index d5c59cf9..d411fd2e 100644 --- a/docs/data-sources/paginated_bundle_group_list.md +++ b/docs/data-sources/paginated_bundle_group_list.md @@ -16,7 +16,6 @@ PaginatedBundleGroupList DataSource data "opal_paginated_bundle_group_list" "my_paginatedbundlegrouplist" { bundle_id = "32acc112-21ff-4669-91c2-21e27683eaa1" cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 } ``` @@ -30,7 +29,6 @@ data "opal_paginated_bundle_group_list" "my_paginatedbundlegrouplist" { ### Optional - `cursor` (String) A cursor indicating where to start fetching items after a specific point. -- `page_size` (Number) The maximum number of groups to return from the beginning of the list. Default is 200, max is 1000. ### Read-Only diff --git a/docs/data-sources/paginated_bundle_list.md b/docs/data-sources/paginated_bundle_list.md index f6e2c2b8..feaa5937 100644 --- a/docs/data-sources/paginated_bundle_list.md +++ b/docs/data-sources/paginated_bundle_list.md @@ -14,9 +14,8 @@ PaginatedBundleList DataSource ```terraform data "opal_paginated_bundle_list" "my_paginatedbundlelist" { - contains = "Engineering" - cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 + contains = "Engineering" + cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" } ``` @@ -27,7 +26,6 @@ data "opal_paginated_bundle_list" "my_paginatedbundlelist" { - `contains` (String) A filter for the bundle name. - `cursor` (String) A cursor indicating where to start fetching items after a specific point. -- `page_size` (Number) The maximum number of bundles to return from the beginning of the list. Default is 200, max is 1000. ### Read-Only diff --git a/docs/data-sources/paginated_bundle_resource_list.md b/docs/data-sources/paginated_bundle_resource_list.md index ae16be91..8517d037 100644 --- a/docs/data-sources/paginated_bundle_resource_list.md +++ b/docs/data-sources/paginated_bundle_resource_list.md @@ -16,7 +16,6 @@ PaginatedBundleResourceList DataSource data "opal_paginated_bundle_resource_list" "my_paginatedbundleresourcelist" { bundle_id = "32acc112-21ff-4669-91c2-21e27683eaa1" cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 } ``` @@ -30,7 +29,6 @@ data "opal_paginated_bundle_resource_list" "my_paginatedbundleresourcelist" { ### Optional - `cursor` (String) A cursor indicating where to start fetching items after a specific point. -- `page_size` (Number) The maximum number of resources to return from the beginning of the list. Default is 200, max is 1000. ### Read-Only diff --git a/docs/index.md b/docs/index.md index d28700c7..bdd336ba 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,7 +16,7 @@ terraform { required_providers { opal = { source = "opalsecurity/opal" - version = "3.3.2" + version = "3.4.0" } } } diff --git a/examples/data-sources/opal_delegations/data-source.tf b/examples/data-sources/opal_delegations/data-source.tf index 9c8fbeef..4543f585 100644 --- a/examples/data-sources/opal_delegations/data-source.tf +++ b/examples/data-sources/opal_delegations/data-source.tf @@ -2,5 +2,4 @@ data "opal_delegations" "my_delegations" { cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" delegate_user_id = "29827fb8-f2dd-4e80-9576-28e31e9934ac" delegator_user_id = "29827fb8-f2dd-4e80-9576-28e31e9934ac" - page_size = 200 } \ No newline at end of file diff --git a/examples/data-sources/opal_paginated_bundle_group_list/data-source.tf b/examples/data-sources/opal_paginated_bundle_group_list/data-source.tf index 5b72fac6..cb2a634e 100644 --- a/examples/data-sources/opal_paginated_bundle_group_list/data-source.tf +++ b/examples/data-sources/opal_paginated_bundle_group_list/data-source.tf @@ -1,5 +1,4 @@ data "opal_paginated_bundle_group_list" "my_paginatedbundlegrouplist" { bundle_id = "32acc112-21ff-4669-91c2-21e27683eaa1" cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 } \ No newline at end of file diff --git a/examples/data-sources/opal_paginated_bundle_list/data-source.tf b/examples/data-sources/opal_paginated_bundle_list/data-source.tf index d319a1d4..ce5dfed0 100644 --- a/examples/data-sources/opal_paginated_bundle_list/data-source.tf +++ b/examples/data-sources/opal_paginated_bundle_list/data-source.tf @@ -1,5 +1,4 @@ data "opal_paginated_bundle_list" "my_paginatedbundlelist" { - contains = "Engineering" - cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 + contains = "Engineering" + cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" } \ No newline at end of file diff --git a/examples/data-sources/opal_paginated_bundle_resource_list/data-source.tf b/examples/data-sources/opal_paginated_bundle_resource_list/data-source.tf index ab86fb56..bbfb3c41 100644 --- a/examples/data-sources/opal_paginated_bundle_resource_list/data-source.tf +++ b/examples/data-sources/opal_paginated_bundle_resource_list/data-source.tf @@ -1,5 +1,4 @@ data "opal_paginated_bundle_resource_list" "my_paginatedbundleresourcelist" { bundle_id = "32acc112-21ff-4669-91c2-21e27683eaa1" cursor = "cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw" - page_size = 200 } \ No newline at end of file diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index dc3b4fee..b7dc2e96 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -2,7 +2,7 @@ terraform { required_providers { opal = { source = "opalsecurity/opal" - version = "3.3.2" + version = "3.4.0" } } } diff --git a/gen.yaml b/gen.yaml index 4c18a4b8..bf1d8874 100644 --- a/gen.yaml +++ b/gen.yaml @@ -22,7 +22,7 @@ generation: skipResponseBodyAssertions: false flattenGlobalSecurity: true terraform: - version: 3.3.2 + version: 3.4.0 additionalDataSources: [] additionalDependencies: github.com/hashicorp/terraform-plugin-testing: v1.13.2 @@ -49,3 +49,4 @@ terraform: inputModelSuffix: input outputModelSuffix: output packageName: opal + unionDeserializationStrategy: populated-fields diff --git a/go.mod b/go.mod index 6804ab75..144f4565 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.13.2 github.com/pkg/errors v0.9.1 + github.com/spyzhov/ajson v0.9.0 github.com/stretchr/testify v1.8.3 ) diff --git a/go.sum b/go.sum index 9d0952a5..19de4986 100644 --- a/go.sum +++ b/go.sum @@ -187,6 +187,8 @@ github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0= +github.com/spyzhov/ajson v0.9.0/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= diff --git a/internal/provider/delegations_data_source.go b/internal/provider/delegations_data_source.go index cf584f2e..f06e0bf7 100644 --- a/internal/provider/delegations_data_source.go +++ b/internal/provider/delegations_data_source.go @@ -5,10 +5,8 @@ package provider import ( "context" "fmt" - "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" tfTypes "github.com/opalsecurity/terraform-provider-opal/v3/internal/provider/types" @@ -35,7 +33,6 @@ type DelegationsDataSourceModel struct { DelegateUserID types.String `queryParam:"style=form,explode=true,name=delegate_user_id" tfsdk:"delegate_user_id"` DelegatorUserID types.String `queryParam:"style=form,explode=true,name=delegator_user_id" tfsdk:"delegator_user_id"` Next types.String `tfsdk:"next"` - PageSize types.Int64 `queryParam:"style=form,explode=true,name=page_size" tfsdk:"page_size"` Previous types.String `tfsdk:"previous"` Results []tfTypes.Delegation `tfsdk:"results"` TotalCount types.Int64 `tfsdk:"total_count"` @@ -68,13 +65,6 @@ func (r *DelegationsDataSource) Schema(ctx context.Context, req datasource.Schem Computed: true, Description: `The cursor with which to continue pagination if additional result pages exist.`, }, - "page_size": schema.Int64Attribute{ - Optional: true, - Description: `The maximum number of results to return per page. The default is 200.`, - Validators: []validator.Int64{ - int64validator.AtMost(1000), - }, - }, "previous": schema.StringAttribute{ Computed: true, Description: `The cursor used to obtain the current result page.`, @@ -196,6 +186,26 @@ func (r *DelegationsDataSource) Read(ctx context.Context, req datasource.ReadReq if resp.Diagnostics.HasError() { return } + for { + var err error + + res, err = res.Next() + + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("failed to retrieve next page of results: %v", err), debugResponse(res.RawResponse)) + return + } + + if res == nil { + break + } + + resp.Diagnostics.Append(data.RefreshFromSharedPaginatedDelegationsList(ctx, res.PaginatedDelegationsList)...) + + if resp.Diagnostics.HasError() { + return + } + } // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) diff --git a/internal/provider/delegations_data_source_sdk.go b/internal/provider/delegations_data_source_sdk.go index 13028ef9..0bc2fb0b 100644 --- a/internal/provider/delegations_data_source_sdk.go +++ b/internal/provider/delegations_data_source_sdk.go @@ -18,7 +18,9 @@ func (r *DelegationsDataSourceModel) RefreshFromSharedPaginatedDelegationsList(c if resp != nil { r.Next = types.StringPointerValue(resp.Next) r.Previous = types.StringPointerValue(resp.Previous) - r.Results = []tfTypes.Delegation{} + if r.Results == nil { + r.Results = []tfTypes.Delegation{} + } for _, resultsItem := range resp.Results { var results tfTypes.Delegation @@ -43,12 +45,6 @@ func (r *DelegationsDataSourceModel) RefreshFromSharedPaginatedDelegationsList(c func (r *DelegationsDataSourceModel) ToOperationsGetDelegationsRequest(ctx context.Context) (*operations.GetDelegationsRequest, diag.Diagnostics) { var diags diag.Diagnostics - cursor := new(string) - if !r.Cursor.IsUnknown() && !r.Cursor.IsNull() { - *cursor = r.Cursor.ValueString() - } else { - cursor = nil - } delegateUserID := new(string) if !r.DelegateUserID.IsUnknown() && !r.DelegateUserID.IsNull() { *delegateUserID = r.DelegateUserID.ValueString() @@ -61,17 +57,9 @@ func (r *DelegationsDataSourceModel) ToOperationsGetDelegationsRequest(ctx conte } else { delegatorUserID = nil } - pageSize := new(int64) - if !r.PageSize.IsUnknown() && !r.PageSize.IsNull() { - *pageSize = r.PageSize.ValueInt64() - } else { - pageSize = nil - } out := operations.GetDelegationsRequest{ - Cursor: cursor, DelegateUserID: delegateUserID, DelegatorUserID: delegatorUserID, - PageSize: pageSize, } return &out, diags diff --git a/internal/provider/paginatedbundlegrouplist_data_source.go b/internal/provider/paginatedbundlegrouplist_data_source.go index 82e0df4a..85b3d962 100644 --- a/internal/provider/paginatedbundlegrouplist_data_source.go +++ b/internal/provider/paginatedbundlegrouplist_data_source.go @@ -33,7 +33,6 @@ type PaginatedBundleGroupListDataSourceModel struct { BundleID types.String `tfsdk:"bundle_id"` Cursor types.String `queryParam:"style=form,explode=true,name=cursor" tfsdk:"cursor"` Next types.String `tfsdk:"next"` - PageSize types.Int64 `queryParam:"style=form,explode=true,name=page_size" tfsdk:"page_size"` Previous types.String `tfsdk:"previous"` TotalCount types.Int64 `tfsdk:"total_count"` } @@ -84,10 +83,6 @@ func (r *PaginatedBundleGroupListDataSource) Schema(ctx context.Context, req dat Computed: true, Description: `The cursor with which to continue pagination if additional result pages exist.`, }, - "page_size": schema.Int64Attribute{ - Optional: true, - Description: `The maximum number of groups to return from the beginning of the list. Default is 200, max is 1000.`, - }, "previous": schema.StringAttribute{ Computed: true, Description: `The cursor used to obtain the current result page.`, @@ -169,6 +164,26 @@ func (r *PaginatedBundleGroupListDataSource) Read(ctx context.Context, req datas if resp.Diagnostics.HasError() { return } + for { + var err error + + res, err = res.Next() + + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("failed to retrieve next page of results: %v", err), debugResponse(res.RawResponse)) + return + } + + if res == nil { + break + } + + resp.Diagnostics.Append(data.RefreshFromSharedPaginatedBundleGroupList(ctx, res.PaginatedBundleGroupList)...) + + if resp.Diagnostics.HasError() { + return + } + } // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) diff --git a/internal/provider/paginatedbundlegrouplist_data_source_sdk.go b/internal/provider/paginatedbundlegrouplist_data_source_sdk.go index 60fb3993..d32855aa 100644 --- a/internal/provider/paginatedbundlegrouplist_data_source_sdk.go +++ b/internal/provider/paginatedbundlegrouplist_data_source_sdk.go @@ -15,7 +15,9 @@ func (r *PaginatedBundleGroupListDataSourceModel) RefreshFromSharedPaginatedBund var diags diag.Diagnostics if resp != nil { - r.BundleGroups = []tfTypes.BundleGroup{} + if r.BundleGroups == nil { + r.BundleGroups = []tfTypes.BundleGroup{} + } for _, bundleGroupsItem := range resp.BundleGroups { var bundleGroups tfTypes.BundleGroup @@ -41,22 +43,8 @@ func (r *PaginatedBundleGroupListDataSourceModel) ToOperationsGetBundleGroupsReq var bundleID string bundleID = r.BundleID.ValueString() - cursor := new(string) - if !r.Cursor.IsUnknown() && !r.Cursor.IsNull() { - *cursor = r.Cursor.ValueString() - } else { - cursor = nil - } - pageSize := new(int64) - if !r.PageSize.IsUnknown() && !r.PageSize.IsNull() { - *pageSize = r.PageSize.ValueInt64() - } else { - pageSize = nil - } out := operations.GetBundleGroupsRequest{ BundleID: bundleID, - Cursor: cursor, - PageSize: pageSize, } return &out, diags diff --git a/internal/provider/paginatedbundlelist_data_source.go b/internal/provider/paginatedbundlelist_data_source.go index da53607b..e9c92574 100644 --- a/internal/provider/paginatedbundlelist_data_source.go +++ b/internal/provider/paginatedbundlelist_data_source.go @@ -33,7 +33,6 @@ type PaginatedBundleListDataSourceModel struct { Contains types.String `queryParam:"style=form,explode=true,name=contains" tfsdk:"contains"` Cursor types.String `queryParam:"style=form,explode=true,name=cursor" tfsdk:"cursor"` Next types.String `tfsdk:"next"` - PageSize types.Int64 `queryParam:"style=form,explode=true,name=page_size" tfsdk:"page_size"` Previous types.String `tfsdk:"previous"` TotalCount types.Int64 `tfsdk:"total_count"` } @@ -104,10 +103,6 @@ func (r *PaginatedBundleListDataSource) Schema(ctx context.Context, req datasour Computed: true, Description: `The cursor with which to continue pagination if additional result pages exist.`, }, - "page_size": schema.Int64Attribute{ - Optional: true, - Description: `The maximum number of bundles to return from the beginning of the list. Default is 200, max is 1000.`, - }, "previous": schema.StringAttribute{ Computed: true, Description: `The cursor used to obtain the current result page.`, @@ -189,6 +184,26 @@ func (r *PaginatedBundleListDataSource) Read(ctx context.Context, req datasource if resp.Diagnostics.HasError() { return } + for { + var err error + + res, err = res.Next() + + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("failed to retrieve next page of results: %v", err), debugResponse(res.RawResponse)) + return + } + + if res == nil { + break + } + + resp.Diagnostics.Append(data.RefreshFromSharedPaginatedBundleList(ctx, res.PaginatedBundleList)...) + + if resp.Diagnostics.HasError() { + return + } + } // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) diff --git a/internal/provider/paginatedbundlelist_data_source_sdk.go b/internal/provider/paginatedbundlelist_data_source_sdk.go index 53bc01ba..3be7117b 100644 --- a/internal/provider/paginatedbundlelist_data_source_sdk.go +++ b/internal/provider/paginatedbundlelist_data_source_sdk.go @@ -16,7 +16,9 @@ func (r *PaginatedBundleListDataSourceModel) RefreshFromSharedPaginatedBundleLis var diags diag.Diagnostics if resp != nil { - r.Bundles = []tfTypes.Bundle{} + if r.Bundles == nil { + r.Bundles = []tfTypes.Bundle{} + } for _, bundlesItem := range resp.Bundles { var bundles tfTypes.Bundle @@ -50,22 +52,8 @@ func (r *PaginatedBundleListDataSourceModel) ToOperationsGetBundlesRequest(ctx c } else { contains = nil } - cursor := new(string) - if !r.Cursor.IsUnknown() && !r.Cursor.IsNull() { - *cursor = r.Cursor.ValueString() - } else { - cursor = nil - } - pageSize := new(int64) - if !r.PageSize.IsUnknown() && !r.PageSize.IsNull() { - *pageSize = r.PageSize.ValueInt64() - } else { - pageSize = nil - } out := operations.GetBundlesRequest{ Contains: contains, - Cursor: cursor, - PageSize: pageSize, } return &out, diags diff --git a/internal/provider/paginatedbundleresourcelist_data_source.go b/internal/provider/paginatedbundleresourcelist_data_source.go index 2680e94a..c213a4db 100644 --- a/internal/provider/paginatedbundleresourcelist_data_source.go +++ b/internal/provider/paginatedbundleresourcelist_data_source.go @@ -33,7 +33,6 @@ type PaginatedBundleResourceListDataSourceModel struct { BundleResources []tfTypes.BundleResource `tfsdk:"bundle_resources"` Cursor types.String `queryParam:"style=form,explode=true,name=cursor" tfsdk:"cursor"` Next types.String `tfsdk:"next"` - PageSize types.Int64 `queryParam:"style=form,explode=true,name=page_size" tfsdk:"page_size"` Previous types.String `tfsdk:"previous"` TotalCount types.Int64 `tfsdk:"total_count"` } @@ -84,10 +83,6 @@ func (r *PaginatedBundleResourceListDataSource) Schema(ctx context.Context, req Computed: true, Description: `The cursor with which to continue pagination if additional result pages exist.`, }, - "page_size": schema.Int64Attribute{ - Optional: true, - Description: `The maximum number of resources to return from the beginning of the list. Default is 200, max is 1000.`, - }, "previous": schema.StringAttribute{ Computed: true, Description: `The cursor used to obtain the current result page.`, @@ -169,6 +164,26 @@ func (r *PaginatedBundleResourceListDataSource) Read(ctx context.Context, req da if resp.Diagnostics.HasError() { return } + for { + var err error + + res, err = res.Next() + + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("failed to retrieve next page of results: %v", err), debugResponse(res.RawResponse)) + return + } + + if res == nil { + break + } + + resp.Diagnostics.Append(data.RefreshFromSharedPaginatedBundleResourceList(ctx, res.PaginatedBundleResourceList)...) + + if resp.Diagnostics.HasError() { + return + } + } // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) diff --git a/internal/provider/paginatedbundleresourcelist_data_source_sdk.go b/internal/provider/paginatedbundleresourcelist_data_source_sdk.go index 2c2cdf7e..8fb48d48 100644 --- a/internal/provider/paginatedbundleresourcelist_data_source_sdk.go +++ b/internal/provider/paginatedbundleresourcelist_data_source_sdk.go @@ -15,7 +15,9 @@ func (r *PaginatedBundleResourceListDataSourceModel) RefreshFromSharedPaginatedB var diags diag.Diagnostics if resp != nil { - r.BundleResources = []tfTypes.BundleResource{} + if r.BundleResources == nil { + r.BundleResources = []tfTypes.BundleResource{} + } for _, bundleResourcesItem := range resp.BundleResources { var bundleResources tfTypes.BundleResource @@ -41,22 +43,8 @@ func (r *PaginatedBundleResourceListDataSourceModel) ToOperationsGetBundleResour var bundleID string bundleID = r.BundleID.ValueString() - cursor := new(string) - if !r.Cursor.IsUnknown() && !r.Cursor.IsNull() { - *cursor = r.Cursor.ValueString() - } else { - cursor = nil - } - pageSize := new(int64) - if !r.PageSize.IsUnknown() && !r.PageSize.IsNull() { - *pageSize = r.PageSize.ValueInt64() - } else { - pageSize = nil - } out := operations.GetBundleResourcesRequest{ BundleID: bundleID, - Cursor: cursor, - PageSize: pageSize, } return &out, diags diff --git a/internal/sdk/bundles.go b/internal/sdk/bundles.go index 52f7c06d..b68281eb 100644 --- a/internal/sdk/bundles.go +++ b/internal/sdk/bundles.go @@ -13,8 +13,11 @@ import ( "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/models/operations" "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/models/shared" "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/retry" + "github.com/spyzhov/ajson" "net/http" "net/url" + "strconv" + "strings" ) // Bundles - Operations related to bundles @@ -1191,6 +1194,75 @@ func (s *Bundles) GetBundleGroups(ctx context.Context, request operations.GetBun ContentType: httpRes.Header.Get("Content-Type"), RawResponse: httpRes, } + res.Next = func() (*operations.GetBundleGroupsResponse, error) { + rawBody, err := utils.ConsumeRawBody(httpRes) + if err != nil { + return nil, err + } + + b, err := ajson.Unmarshal(rawBody) + if err != nil { + return nil, err + } + nC, err := ajson.Eval(b, "$.next") + if err != nil { + return nil, err + } + var nCVal string + + if nC.IsNumeric() { + numVal, err := nC.GetNumeric() + if err != nil { + return nil, err + } + // GetNumeric returns as float64 so convert to the appropriate type. + nCVal = strconv.FormatFloat(numVal, 'f', 0, 64) + } else { + val, err := nC.Value() + if err != nil { + return nil, err + } + if val == nil { + return nil, nil + } + nCVal = val.(string) + if strings.TrimSpace(nCVal) == "" { + return nil, nil + } + } + r, err := ajson.Eval(b, "$.groups") + if err != nil { + return nil, err + } + if !r.IsArray() { + return nil, nil + } + arr, err := r.GetArray() + if err != nil { + return nil, err + } + if len(arr) == 0 { + return nil, nil + } + + l := 0 + if request.PageSize != nil { + l = int(*request.PageSize) + } + if len(arr) < l { + return nil, nil + } + + return s.GetBundleGroups( + ctx, + operations.GetBundleGroupsRequest{ + BundleID: request.BundleID, + Cursor: &nCVal, + PageSize: request.PageSize, + }, + opts..., + ) + } switch { case httpRes.StatusCode == 200: @@ -1393,6 +1465,75 @@ func (s *Bundles) GetBundleResources(ctx context.Context, request operations.Get ContentType: httpRes.Header.Get("Content-Type"), RawResponse: httpRes, } + res.Next = func() (*operations.GetBundleResourcesResponse, error) { + rawBody, err := utils.ConsumeRawBody(httpRes) + if err != nil { + return nil, err + } + + b, err := ajson.Unmarshal(rawBody) + if err != nil { + return nil, err + } + nC, err := ajson.Eval(b, "$.next") + if err != nil { + return nil, err + } + var nCVal string + + if nC.IsNumeric() { + numVal, err := nC.GetNumeric() + if err != nil { + return nil, err + } + // GetNumeric returns as float64 so convert to the appropriate type. + nCVal = strconv.FormatFloat(numVal, 'f', 0, 64) + } else { + val, err := nC.Value() + if err != nil { + return nil, err + } + if val == nil { + return nil, nil + } + nCVal = val.(string) + if strings.TrimSpace(nCVal) == "" { + return nil, nil + } + } + r, err := ajson.Eval(b, "$.bundle_resources") + if err != nil { + return nil, err + } + if !r.IsArray() { + return nil, nil + } + arr, err := r.GetArray() + if err != nil { + return nil, err + } + if len(arr) == 0 { + return nil, nil + } + + l := 0 + if request.PageSize != nil { + l = int(*request.PageSize) + } + if len(arr) < l { + return nil, nil + } + + return s.GetBundleResources( + ctx, + operations.GetBundleResourcesRequest{ + BundleID: request.BundleID, + Cursor: &nCVal, + PageSize: request.PageSize, + }, + opts..., + ) + } switch { case httpRes.StatusCode == 200: @@ -1794,6 +1935,75 @@ func (s *Bundles) GetBundles(ctx context.Context, request operations.GetBundlesR ContentType: httpRes.Header.Get("Content-Type"), RawResponse: httpRes, } + res.Next = func() (*operations.GetBundlesResponse, error) { + rawBody, err := utils.ConsumeRawBody(httpRes) + if err != nil { + return nil, err + } + + b, err := ajson.Unmarshal(rawBody) + if err != nil { + return nil, err + } + nC, err := ajson.Eval(b, "$.next") + if err != nil { + return nil, err + } + var nCVal string + + if nC.IsNumeric() { + numVal, err := nC.GetNumeric() + if err != nil { + return nil, err + } + // GetNumeric returns as float64 so convert to the appropriate type. + nCVal = strconv.FormatFloat(numVal, 'f', 0, 64) + } else { + val, err := nC.Value() + if err != nil { + return nil, err + } + if val == nil { + return nil, nil + } + nCVal = val.(string) + if strings.TrimSpace(nCVal) == "" { + return nil, nil + } + } + r, err := ajson.Eval(b, "$.bundles") + if err != nil { + return nil, err + } + if !r.IsArray() { + return nil, nil + } + arr, err := r.GetArray() + if err != nil { + return nil, err + } + if len(arr) == 0 { + return nil, nil + } + + l := 0 + if request.PageSize != nil { + l = int(*request.PageSize) + } + if len(arr) < l { + return nil, nil + } + + return s.GetBundles( + ctx, + operations.GetBundlesRequest{ + Contains: request.Contains, + Cursor: &nCVal, + PageSize: request.PageSize, + }, + opts..., + ) + } switch { case httpRes.StatusCode == 200: diff --git a/internal/sdk/delegations.go b/internal/sdk/delegations.go index 94cc97d0..b5c6768e 100644 --- a/internal/sdk/delegations.go +++ b/internal/sdk/delegations.go @@ -13,8 +13,11 @@ import ( "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/models/operations" "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/models/shared" "github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk/retry" + "github.com/spyzhov/ajson" "net/http" "net/url" + "strconv" + "strings" ) // Delegations - Operations related to request reviewer delegations @@ -782,6 +785,76 @@ func (s *Delegations) GetDelegations(ctx context.Context, request operations.Get ContentType: httpRes.Header.Get("Content-Type"), RawResponse: httpRes, } + res.Next = func() (*operations.GetDelegationsResponse, error) { + rawBody, err := utils.ConsumeRawBody(httpRes) + if err != nil { + return nil, err + } + + b, err := ajson.Unmarshal(rawBody) + if err != nil { + return nil, err + } + nC, err := ajson.Eval(b, "$.next") + if err != nil { + return nil, err + } + var nCVal string + + if nC.IsNumeric() { + numVal, err := nC.GetNumeric() + if err != nil { + return nil, err + } + // GetNumeric returns as float64 so convert to the appropriate type. + nCVal = strconv.FormatFloat(numVal, 'f', 0, 64) + } else { + val, err := nC.Value() + if err != nil { + return nil, err + } + if val == nil { + return nil, nil + } + nCVal = val.(string) + if strings.TrimSpace(nCVal) == "" { + return nil, nil + } + } + r, err := ajson.Eval(b, "$.results") + if err != nil { + return nil, err + } + if !r.IsArray() { + return nil, nil + } + arr, err := r.GetArray() + if err != nil { + return nil, err + } + if len(arr) == 0 { + return nil, nil + } + + l := 0 + if request.PageSize != nil { + l = int(*request.PageSize) + } + if len(arr) < l { + return nil, nil + } + + return s.GetDelegations( + ctx, + operations.GetDelegationsRequest{ + Cursor: &nCVal, + DelegateUserID: request.DelegateUserID, + DelegatorUserID: request.DelegatorUserID, + PageSize: request.PageSize, + }, + opts..., + ) + } switch { case httpRes.StatusCode == 200: diff --git a/internal/sdk/models/operations/denyrequest.go b/internal/sdk/models/operations/denyrequest.go index 6e07cffe..b0cda140 100644 --- a/internal/sdk/models/operations/denyrequest.go +++ b/internal/sdk/models/operations/denyrequest.go @@ -11,6 +11,8 @@ import ( type DenyRequestRequestBody struct { // Comment for the denial Comment string `json:"comment"` + // The decision level for the approval + Level *shared.RequestApprovalEnum `json:"level,omitempty"` } func (d *DenyRequestRequestBody) GetComment() string { @@ -20,6 +22,13 @@ func (d *DenyRequestRequestBody) GetComment() string { return d.Comment } +func (d *DenyRequestRequestBody) GetLevel() *shared.RequestApprovalEnum { + if d == nil { + return nil + } + return d.Level +} + type DenyRequestRequest struct { // Denial parameters RequestBody DenyRequestRequestBody `request:"mediaType=application/json"` diff --git a/internal/sdk/models/operations/getbundlegroups.go b/internal/sdk/models/operations/getbundlegroups.go index 2c335b45..fe982f8d 100644 --- a/internal/sdk/models/operations/getbundlegroups.go +++ b/internal/sdk/models/operations/getbundlegroups.go @@ -46,6 +46,8 @@ type GetBundleGroupsResponse struct { StatusCode int // Raw HTTP response; suitable for custom response parsing RawResponse *http.Response + + Next func() (*GetBundleGroupsResponse, error) } func (g *GetBundleGroupsResponse) GetContentType() string { diff --git a/internal/sdk/models/operations/getbundleresources.go b/internal/sdk/models/operations/getbundleresources.go index a063aa37..08c2614b 100644 --- a/internal/sdk/models/operations/getbundleresources.go +++ b/internal/sdk/models/operations/getbundleresources.go @@ -46,6 +46,8 @@ type GetBundleResourcesResponse struct { StatusCode int // Raw HTTP response; suitable for custom response parsing RawResponse *http.Response + + Next func() (*GetBundleResourcesResponse, error) } func (g *GetBundleResourcesResponse) GetContentType() string { diff --git a/internal/sdk/models/operations/getbundles.go b/internal/sdk/models/operations/getbundles.go index 9d8bc9f6..fab6fe5c 100644 --- a/internal/sdk/models/operations/getbundles.go +++ b/internal/sdk/models/operations/getbundles.go @@ -46,6 +46,8 @@ type GetBundlesResponse struct { StatusCode int // Raw HTTP response; suitable for custom response parsing RawResponse *http.Response + + Next func() (*GetBundlesResponse, error) } func (g *GetBundlesResponse) GetContentType() string { diff --git a/internal/sdk/models/operations/getdelegations.go b/internal/sdk/models/operations/getdelegations.go index 7b2c0df1..89c1e421 100644 --- a/internal/sdk/models/operations/getdelegations.go +++ b/internal/sdk/models/operations/getdelegations.go @@ -55,6 +55,8 @@ type GetDelegationsResponse struct { StatusCode int // Raw HTTP response; suitable for custom response parsing RawResponse *http.Response + + Next func() (*GetDelegationsResponse, error) } func (g *GetDelegationsResponse) GetContentType() string { diff --git a/internal/sdk/opalapi.go b/internal/sdk/opalapi.go index c54eb278..f7540015 100644 --- a/internal/sdk/opalapi.go +++ b/internal/sdk/opalapi.go @@ -2,7 +2,7 @@ package sdk -// Generated from OpenAPI doc version 1.0 and generator version 2.730.0 +// Generated from OpenAPI doc version 1.0 and generator version 2.731.4 import ( "context" @@ -169,9 +169,9 @@ func WithTimeout(timeout time.Duration) SDKOption { // New creates a new instance of the SDK with the provided options func New(opts ...SDKOption) *OpalAPI { sdk := &OpalAPI{ - SDKVersion: "3.3.2", + SDKVersion: "3.4.0", sdkConfiguration: config.SDKConfiguration{ - UserAgent: "speakeasy-sdk/terraform 3.3.2 2.730.0 1.0 github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk", + UserAgent: "speakeasy-sdk/terraform 3.4.0 2.731.4 1.0 github.com/opalsecurity/terraform-provider-opal/v3/internal/sdk", ServerList: ServerList, }, hooks: hooks.New(), diff --git a/openapi.yaml b/openapi.yaml index 25c4a177..4c590d17 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -173,6 +173,18 @@ paths: tags: - bundles x-speakeasy-entity-operation: PaginatedBundleList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.bundles post: description: Creates a bundle. operationId: createBundle @@ -321,6 +333,18 @@ paths: tags: - bundles x-speakeasy-entity-operation: PaginatedBundleResourceList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.bundle_resources post: description: Adds a resource to a bundle. operationId: addBundleResource @@ -448,6 +472,18 @@ paths: tags: - bundles x-speakeasy-entity-operation: PaginatedBundleGroupList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.groups post: description: Adds a group to a bundle. operationId: addBundleGroup @@ -2663,6 +2699,8 @@ paths: type: string description: "Comment for the denial" example: "Denied due to insufficient justification" + level: + $ref: "#/components/schemas/RequestApprovalEnum" required: - comment responses: @@ -4612,6 +4650,18 @@ paths: tags: - delegations x-speakeasy-entity-operation: Delegations#get + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.results post: description: Creates a new request reviewer delegation to delegate access review requests from one user to another. operationId: createDelegation diff --git a/terraform_overlay.yaml b/terraform_overlay.yaml index 87a6a2a5..dbf5c4fb 100644 --- a/terraform_overlay.yaml +++ b/terraform_overlay.yaml @@ -35,6 +35,18 @@ actions: - target: $["paths"]["/bundles"]["get"] update: x-speakeasy-entity-operation: PaginatedBundleList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.bundles - target: $["paths"]["/bundles"]["post"] update: x-speakeasy-entity-operation: Bundle#create @@ -50,6 +62,18 @@ actions: - target: $["paths"]["/bundles/{bundle_id}/resources"]["get"] update: x-speakeasy-entity-operation: PaginatedBundleResourceList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.bundle_resources - target: $["paths"]["/bundles/{bundle_id}/resources"]["post"] update: x-speakeasy-entity-operation: BundleResource#create @@ -59,6 +83,18 @@ actions: - target: $["paths"]["/bundles/{bundle_id}/groups"]["get"] update: x-speakeasy-entity-operation: PaginatedBundleGroupList#read + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.groups - target: $["paths"]["/bundles/{bundle_id}/groups"]["post"] update: x-speakeasy-entity-operation: BundleGroup#create @@ -485,6 +521,18 @@ actions: - target: $["paths"]["/delegations"]["get"] update: x-speakeasy-entity-operation: Delegations#get + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + - name: page_size + in: parameters + type: limit + outputs: + nextCursor: $.next + results: $.results - target: $["paths"]["/delegations"]["post"] update: x-speakeasy-entity-operation: Delegation#create