From 63e5fb26785c61272b4b8ebc9b231128f096a0ba Mon Sep 17 00:00:00 2001 From: matty271828 <65253959+matty271828@users.noreply.github.com> Date: Wed, 1 Nov 2023 08:15:07 +0000 Subject: [PATCH] [AV-65775] List APIs - Database Credentials & Buckets Pagination (#74) --- internal/api/bucket/bucket.go | 15 ---- internal/api/database_credential.go | 4 - internal/datasources/buckets.go | 23 +----- internal/datasources/database_credentials.go | 84 ++++---------------- 4 files changed, 17 insertions(+), 109 deletions(-) diff --git a/internal/api/bucket/bucket.go b/internal/api/bucket/bucket.go index 77d49111..6b30fda5 100644 --- a/internal/api/bucket/bucket.go +++ b/internal/api/bucket/bucket.go @@ -198,18 +198,3 @@ type PutBucketRequest struct { // TimeToLiveInSeconds specifies the time to live (TTL) value in seconds. TimeToLiveInSeconds int64 `json:"timeToLiveInSeconds"` } - -// GetBucketsResponse is the response received from Capella V4 Public API when asked to list all buckets for a cluster. -// -// In order to access this endpoint, the provided API key must have at least one of the following roles: -// -// Organization Owner -// Project Owner -// Project Manager -// Project Viewer -// Database Data Reader/Writer -// Database Data Reader -// To learn more, see https://docs.couchbase.com/cloud/organizations/organization-projects-overview.html -type GetBucketsResponse struct { - Data []GetBucketResponse `json:"data"` -} diff --git a/internal/api/database_credential.go b/internal/api/database_credential.go index 419d87c7..52ddeec0 100644 --- a/internal/api/database_credential.go +++ b/internal/api/database_credential.go @@ -103,7 +103,3 @@ type PutDatabaseCredentialRequest struct { // Access describes the access information of the database credential. Access []Access `json:"access"` } - -type GetDatabaseCredentialsResponse struct { - Data []GetDatabaseCredentialResponse `json:"data"` -} diff --git a/internal/datasources/buckets.go b/internal/datasources/buckets.go index 37596864..a0970036 100644 --- a/internal/datasources/buckets.go +++ b/internal/datasources/buckets.go @@ -2,9 +2,7 @@ package datasources import ( "context" - "encoding/json" "fmt" - "net/http" "terraform-provider-capella/internal/api/bucket" "terraform-provider-capella/internal/api" @@ -147,13 +145,8 @@ func (d *Buckets) Read(ctx context.Context, req datasource.ReadRequest, resp *da return } - response, err := d.Client.Execute( - fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s/buckets", d.HostURL, organizationId, projectId, clusterId), - http.MethodGet, - nil, - d.Token, - nil, - ) + url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s/buckets", d.HostURL, organizationId, projectId, clusterId) + response, err := api.GetPaginated[[]bucket.GetBucketResponse](ctx, d.Client, d.Token, url) switch err := err.(type) { case nil: case api.Error: @@ -175,18 +168,8 @@ func (d *Buckets) Read(ctx context.Context, req datasource.ReadRequest, resp *da return } - bucketResp := bucket.GetBucketsResponse{} - err = json.Unmarshal(response.Body, &bucketResp) - if err != nil { - resp.Diagnostics.AddError( - "Error listing buckets", - "Could not list buckets, unexpected error: "+err.Error(), - ) - return - } - // Map response body to model - for _, bucket := range bucketResp.Data { + for _, bucket := range response { bucketState := providerschema.OneBucket{ Id: types.StringValue(bucket.Id), Name: types.StringValue(bucket.Name), diff --git a/internal/datasources/database_credentials.go b/internal/datasources/database_credentials.go index 395019ef..eb958b88 100644 --- a/internal/datasources/database_credentials.go +++ b/internal/datasources/database_credentials.go @@ -2,9 +2,7 @@ package datasources import ( "context" - "encoding/json" "fmt" - "net/http" "terraform-provider-capella/internal/api" providerschema "terraform-provider-capella/internal/schema" @@ -40,54 +38,19 @@ func (d *DatabaseCredentials) Metadata(_ context.Context, req datasource.Metadat func (d *DatabaseCredentials) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "organization_id": schema.StringAttribute{ - Required: true, - }, - "project_id": schema.StringAttribute{ - Required: true, - }, - "cluster_id": schema.StringAttribute{ - Required: true, - }, + "organization_id": requiredStringAttribute, + "project_id": requiredStringAttribute, + "cluster_id": requiredStringAttribute, "data": schema.ListNestedAttribute{ Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "id": schema.StringAttribute{ - Computed: true, - }, - "name": schema.StringAttribute{ - Computed: true, - }, - "organization_id": schema.StringAttribute{ - Computed: true, - }, - "project_id": schema.StringAttribute{ - Computed: true, - }, - "cluster_id": schema.StringAttribute{ - Computed: true, - }, - "audit": schema.SingleNestedAttribute{ - Computed: true, - Attributes: map[string]schema.Attribute{ - "created_at": schema.StringAttribute{ - Computed: true, - }, - "created_by": schema.StringAttribute{ - Computed: true, - }, - "modified_at": schema.StringAttribute{ - Computed: true, - }, - "modified_by": schema.StringAttribute{ - Computed: true, - }, - "version": schema.Int64Attribute{ - Computed: true, - }, - }, - }, + "id": computedStringAttribute, + "name": computedStringAttribute, + "organization_id": computedStringAttribute, + "project_id": computedStringAttribute, + "cluster_id": computedStringAttribute, + "audit": computedAuditAttribute, "access": schema.ListNestedAttribute{ Optional: true, NestedObject: schema.NestedAttributeObject{ @@ -103,16 +66,12 @@ func (d *DatabaseCredentials) Schema(_ context.Context, _ datasource.SchemaReque Optional: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "name": schema.StringAttribute{ - Required: true, - }, + "name": requiredStringAttribute, "scopes": schema.ListNestedAttribute{ Optional: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "name": schema.StringAttribute{ - Required: true, - }, + "name": requiredStringAttribute, "collections": schema.ListAttribute{ Optional: true, ElementType: types.StringType, @@ -153,13 +112,8 @@ func (d *DatabaseCredentials) Read(ctx context.Context, req datasource.ReadReque return } - response, err := d.Client.Execute( - fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s/users", d.HostURL, organizationId, projectId, clusterId), - http.MethodGet, - nil, - d.Token, - nil, - ) + url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s/users", d.HostURL, organizationId, projectId, clusterId) + response, err := api.GetPaginated[[]api.GetDatabaseCredentialResponse](ctx, d.Client, d.Token, url) switch err := err.(type) { case nil: case api.Error: @@ -181,18 +135,8 @@ func (d *DatabaseCredentials) Read(ctx context.Context, req datasource.ReadReque return } - databaseCredentialResp := api.GetDatabaseCredentialsResponse{} - err = json.Unmarshal(response.Body, &databaseCredentialResp) - if err != nil { - resp.Diagnostics.AddError( - "Error listing database credentials", - "Could not list database credentials, unexpected error: "+err.Error(), - ) - return - } - // Map response body to model - for _, databaseCredential := range databaseCredentialResp.Data { + for _, databaseCredential := range response { databaseCredentialState := providerschema.DatabaseCredentialItem{ Id: types.StringValue(databaseCredential.Id.String()), Name: types.StringValue(databaseCredential.Name),