From e4742955b69397c52b85fcf3de5870e4e5d900f9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 02:24:25 +0100 Subject: [PATCH] feat: auto-updated SDK (#88) --- mockhttp.go | 15 ++-- openAPIDefinition.json | 131 ++++++++++++++++------------------ sdk.go | 38 ++++++---- sdk_test.go | 157 +++++++++++++++++++++++++++++------------ 4 files changed, 202 insertions(+), 139 deletions(-) diff --git a/mockhttp.go b/mockhttp.go index 736eea7..99e482f 100644 --- a/mockhttp.go +++ b/mockhttp.go @@ -67,10 +67,18 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ }, "/organizations/{org_id}/members/{member_id}": { + "DELETE": mockResponse{ + Content: `null`, + Code: 200, + }, "GET": mockResponse{ Content: `{"id":"d57833f2-d308-4ede-9d2e-468d9d013d1b","joined_at":"2024-02-23T17:42:25Z","org_id":"my-organization-morning-bread-81040908","role":"admin","user_id":"b107d689-6dd2-4c9a-8b9e-0b25e457cf56"}`, Code: 200, }, + "PATCH": mockResponse{ + Content: `null`, + Code: 200, + }, }, "/projects": { @@ -412,13 +420,6 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ }, }, - "/projects/{project_id}/branches/{branch_id}/set_as_primary": { - "POST": mockResponse{ - Content: `{"branch":{"active_time_seconds":1,"compute_time_seconds":1,"cpu_used_sec":1,"created_at":"2022-11-23T17:42:25Z","creation_source":"console","current_state":"ready","data_transfer_bytes":100,"default":true,"id":"br-icy-dream-250089","name":"mybranch","parent_id":"br-aged-salad-637688","parent_lsn":"0/1E19478","project_id":"shiny-wind-028834","protected":false,"state_changed_at":"2022-11-30T20:09:48Z","updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100},"operations":[]}`, - Code: 200, - }, - }, - "/projects/{project_id}/connection_uri": { "GET": mockResponse{ Content: `null`, diff --git a/openAPIDefinition.json b/openAPIDefinition.json index 9307fa7..f9a7fb6 100644 --- a/openAPIDefinition.json +++ b/openAPIDefinition.json @@ -1662,76 +1662,6 @@ } } }, - "/projects/{project_id}/branches/{branch_id}/set_as_primary": { - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "The Neon project ID", - "required": true, - "schema": { - "type": "string", - "pattern": "^[a-z0-9-]{1,60}$" - } - }, - { - "name": "branch_id", - "in": "path", - "description": "The branch ID", - "required": true, - "schema": { - "type": "string", - "pattern": "^[a-z0-9-]{1,60}$" - } - } - ], - "post": { - "tags": [ - "Branch" - ], - "summary": "Set branch as primary", - "deprecated": true, - "description": "DEPRECATED. Use `/set_as_default` endpoint.\nSets the specified branch as the project's primary branch.\nThe primary designation is automatically removed from the previous primary branch.\nYou can obtain a `project_id` by listing the projects for your Neon account.\nYou can obtain the `branch_id` by listing the project's branches.\nFor more information, see [Manage branches](https://neon.tech/docs/manage/branches/).\n", - "operationId": "setPrimaryProjectBranch", - "responses": { - "200": { - "description": "Updated the specified branch", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BranchOperations" - }, - "example": { - "branch": { - "cpu_used_sec": 1, - "active_time_seconds": 1, - "compute_time_seconds": 1, - "written_data_bytes": 100, - "data_transfer_bytes": 100, - "id": "br-icy-dream-250089", - "project_id": "shiny-wind-028834", - "parent_id": "br-aged-salad-637688", - "parent_lsn": "0/1E19478", - "name": "mybranch", - "current_state": "ready", - "state_changed_at": "2022-11-30T20:09:48Z", - "created_at": "2022-11-23T17:42:25Z", - "updated_at": "2022-11-23T17:42:26Z", - "default": true, - "protected": false, - "creation_source": "console" - }, - "operations": [] - } - } - } - }, - "default": { - "$ref": "#/components/responses/GeneralError" - } - } - } - }, "/projects/{project_id}/branches/{branch_id}/set_as_default": { "parameters": [ { @@ -3795,6 +3725,65 @@ "$ref": "#/components/responses/GeneralError" } } + }, + "patch": { + "summary": "Update the role for an organization member", + "description": "Only an admin can perform this action.\n", + "tags": [ + "Organizations" + ], + "operationId": "updateOrganizationMember", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationMemberUpdateRequest" + }, + "example": { + "role": "admin" + } + } + } + }, + "responses": { + "200": { + "description": "The updated organization member", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Member" + } + } + } + }, + "default": { + "$ref": "#/components/responses/GeneralError" + } + } + }, + "delete": { + "summary": "Remove member from the organization", + "description": "Remove member from the organization.\nOnly an admin of the organization can perform this action.\nIf another admin is being removed, it will not be allows in case it is the only admin left in the organization.\n", + "tags": [ + "Organizations" + ], + "operationId": "removeOrganizationMember", + "responses": { + "200": { + "description": "Removed organization member", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + }, + "default": { + "$ref": "#/components/responses/GeneralError" + } + } } }, "/organizations/{org_id}/invitations": { @@ -4017,7 +4006,7 @@ } } }, - "501": { + "422": { "description": "One or more of project ids provided is linked by Github or Vercel integration. Transferring integration projects is currently not supported", "content": { "application/json": { diff --git a/sdk.go b/sdk.go index 29a7bb1..8ae1942 100644 --- a/sdk.go +++ b/sdk.go @@ -780,6 +780,17 @@ func (c Client) ListSharedProjects(cursor *string, limit *int, search *string) ( return v, nil } +// RemoveOrganizationMember Remove member from the organization. +// Only an admin of the organization can perform this action. +// If another admin is being removed, it will not be allows in case it is the only admin left in the organization. +func (c Client) RemoveOrganizationMember(orgID string, memberID string) (EmptyResponse, error) { + var v EmptyResponse + if err := c.requestHandler(c.baseURL+"/organizations/"+orgID+"/members/"+memberID, "DELETE", nil, &v); err != nil { + return EmptyResponse{}, err + } + return v, nil +} + // ResetProjectBranchRolePassword Resets the password for the specified Postgres role. // Returns a new password and operations. The new password is ready to use when the last operation finishes. // The old password remains valid until last operation finishes. @@ -855,20 +866,6 @@ func (c Client) SetDefaultProjectBranch(projectID string, branchID string) (Bran return v, nil } -// SetPrimaryProjectBranch DEPRECATED. Use `/set_as_default` endpoint. -// Sets the specified branch as the project's primary branch. -// The primary designation is automatically removed from the previous primary branch. -// You can obtain a `project_id` by listing the projects for your Neon account. -// You can obtain the `branch_id` by listing the project's branches. -// For more information, see [Manage branches](https://neon.tech/docs/manage/branches/). -func (c Client) SetPrimaryProjectBranch(projectID string, branchID string) (BranchOperations, error) { - var v BranchOperations - if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches/"+branchID+"/set_as_primary", "POST", nil, &v); err != nil { - return BranchOperations{}, err - } - return v, nil -} - // StartProjectEndpoint Starts a compute endpoint. The compute endpoint is ready to use // after the last operation in chain finishes successfully. // You can obtain a `project_id` by listing the projects for your Neon account. @@ -905,6 +902,15 @@ func (c Client) TransferProjectsFromUserToOrg(cfg TransferProjectsToOrganization return v, nil } +// UpdateOrganizationMember Only an admin can perform this action. +func (c Client) UpdateOrganizationMember(orgID string, memberID string, cfg OrganizationMemberUpdateRequest) (Member, error) { + var v Member + if err := c.requestHandler(c.baseURL+"/organizations/"+orgID+"/members/"+memberID, "PATCH", cfg, &v); err != nil { + return Member{}, err + } + return v, nil +} + // UpdateProject Updates the specified project. // You can obtain a `project_id` by listing the projects for your Neon account. // Neon permits updating the project name only. @@ -1837,6 +1843,10 @@ type OrganizationInvitesCreateRequest struct { Invitations []OrganizationInviteCreateRequest `json:"invitations"` } +type OrganizationMemberUpdateRequest struct { + Role MemberRole `json:"role"` +} + type OrganizationMembersResponse struct { Members []MemberWithUser `json:"members"` } diff --git a/sdk_test.go b/sdk_test.go index 54c7ef5..8c3e812 100644 --- a/sdk_test.go +++ b/sdk_test.go @@ -2972,6 +2972,66 @@ func Test_client_ListSharedProjects(t *testing.T) { } } +func Test_client_RemoveOrganizationMember(t *testing.T) { + deserializeResp := func(s string) EmptyResponse { + var v EmptyResponse + if err := json.Unmarshal([]byte(s), &v); err != nil { + panic(err) + } + return v + } + type args struct { + orgID string + memberID string + } + tests := []struct { + name string + args args + apiKey string + want EmptyResponse + wantErr bool + }{ + { + name: "happy path", + args: args{ + orgID: "foo", + memberID: "foo", + }, + apiKey: "foo", + want: deserializeResp(endpointResponseExamples["/organizations/{org_id}/members/{member_id}"]["DELETE"].Content), + wantErr: false, + }, + { + name: "unhappy path", + args: args{ + orgID: "foo", + memberID: "foo", + }, + apiKey: "invalidApiKey", + want: EmptyResponse{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run( + tt.name, func(t *testing.T) { + c, err := NewClient(Config{tt.apiKey, NewMockHTTPClient()}) + if err != nil { + panic(err) + } + got, err := c.RemoveOrganizationMember(tt.args.orgID, tt.args.memberID) + if (err != nil) != tt.wantErr { + t.Errorf("RemoveOrganizationMember() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("RemoveOrganizationMember() got = %v, want %v", got, tt.want) + } + }, + ) + } +} + func Test_client_ResetProjectBranchRolePassword(t *testing.T) { deserializeResp := func(s string) RoleOperations { var v RoleOperations @@ -3275,43 +3335,43 @@ func Test_client_SetDefaultProjectBranch(t *testing.T) { } } -func Test_client_SetPrimaryProjectBranch(t *testing.T) { - deserializeResp := func(s string) BranchOperations { - var v BranchOperations +func Test_client_StartProjectEndpoint(t *testing.T) { + deserializeResp := func(s string) EndpointOperations { + var v EndpointOperations if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } return v } type args struct { - projectID string - branchID string + projectID string + endpointID string } tests := []struct { name string args args apiKey string - want BranchOperations + want EndpointOperations wantErr bool }{ { name: "happy path", args: args{ - projectID: "foo", - branchID: "foo", + projectID: "foo", + endpointID: "foo", }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/set_as_primary"]["POST"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}/endpoints/{endpoint_id}/start"]["POST"].Content), wantErr: false, }, { name: "unhappy path", args: args{ - projectID: "foo", - branchID: "foo", + projectID: "foo", + endpointID: "foo", }, apiKey: "invalidApiKey", - want: BranchOperations{}, + want: EndpointOperations{}, wantErr: true, }, } @@ -3322,20 +3382,20 @@ func Test_client_SetPrimaryProjectBranch(t *testing.T) { if err != nil { panic(err) } - got, err := c.SetPrimaryProjectBranch(tt.args.projectID, tt.args.branchID) + got, err := c.StartProjectEndpoint(tt.args.projectID, tt.args.endpointID) if (err != nil) != tt.wantErr { - t.Errorf("SetPrimaryProjectBranch() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("StartProjectEndpoint() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("SetPrimaryProjectBranch() got = %v, want %v", got, tt.want) + t.Errorf("StartProjectEndpoint() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_StartProjectEndpoint(t *testing.T) { +func Test_client_SuspendProjectEndpoint(t *testing.T) { deserializeResp := func(s string) EndpointOperations { var v EndpointOperations if err := json.Unmarshal([]byte(s), &v); err != nil { @@ -3361,7 +3421,7 @@ func Test_client_StartProjectEndpoint(t *testing.T) { endpointID: "foo", }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/endpoints/{endpoint_id}/start"]["POST"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}/endpoints/{endpoint_id}/suspend"]["POST"].Content), wantErr: false, }, { @@ -3382,56 +3442,53 @@ func Test_client_StartProjectEndpoint(t *testing.T) { if err != nil { panic(err) } - got, err := c.StartProjectEndpoint(tt.args.projectID, tt.args.endpointID) + got, err := c.SuspendProjectEndpoint(tt.args.projectID, tt.args.endpointID) if (err != nil) != tt.wantErr { - t.Errorf("StartProjectEndpoint() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("SuspendProjectEndpoint() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("StartProjectEndpoint() got = %v, want %v", got, tt.want) + t.Errorf("SuspendProjectEndpoint() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_SuspendProjectEndpoint(t *testing.T) { - deserializeResp := func(s string) EndpointOperations { - var v EndpointOperations +func Test_client_TransferProjectsFromUserToOrg(t *testing.T) { + deserializeResp := func(s string) EmptyResponse { + var v EmptyResponse if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } return v } type args struct { - projectID string - endpointID string + cfg TransferProjectsToOrganizationRequest } tests := []struct { name string args args apiKey string - want EndpointOperations + want EmptyResponse wantErr bool }{ { name: "happy path", args: args{ - projectID: "foo", - endpointID: "foo", + cfg: TransferProjectsToOrganizationRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/endpoints/{endpoint_id}/suspend"]["POST"].Content), + want: deserializeResp(endpointResponseExamples["/users/me/projects/transfer"]["POST"].Content), wantErr: false, }, { name: "unhappy path", args: args{ - projectID: "foo", - endpointID: "foo", + cfg: TransferProjectsToOrganizationRequest{}, }, apiKey: "invalidApiKey", - want: EndpointOperations{}, + want: EmptyResponse{}, wantErr: true, }, } @@ -3442,53 +3499,59 @@ func Test_client_SuspendProjectEndpoint(t *testing.T) { if err != nil { panic(err) } - got, err := c.SuspendProjectEndpoint(tt.args.projectID, tt.args.endpointID) + got, err := c.TransferProjectsFromUserToOrg(tt.args.cfg) if (err != nil) != tt.wantErr { - t.Errorf("SuspendProjectEndpoint() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("TransferProjectsFromUserToOrg() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("SuspendProjectEndpoint() got = %v, want %v", got, tt.want) + t.Errorf("TransferProjectsFromUserToOrg() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_TransferProjectsFromUserToOrg(t *testing.T) { - deserializeResp := func(s string) EmptyResponse { - var v EmptyResponse +func Test_client_UpdateOrganizationMember(t *testing.T) { + deserializeResp := func(s string) Member { + var v Member if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } return v } type args struct { - cfg TransferProjectsToOrganizationRequest + orgID string + memberID string + cfg OrganizationMemberUpdateRequest } tests := []struct { name string args args apiKey string - want EmptyResponse + want Member wantErr bool }{ { name: "happy path", args: args{ - cfg: TransferProjectsToOrganizationRequest{}, + orgID: "foo", + memberID: "foo", + cfg: OrganizationMemberUpdateRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/users/me/projects/transfer"]["POST"].Content), + want: deserializeResp(endpointResponseExamples["/organizations/{org_id}/members/{member_id}"]["PATCH"].Content), wantErr: false, }, { name: "unhappy path", args: args{ - cfg: TransferProjectsToOrganizationRequest{}, + orgID: "foo", + memberID: "foo", + cfg: OrganizationMemberUpdateRequest{}, }, apiKey: "invalidApiKey", - want: EmptyResponse{}, + want: Member{}, wantErr: true, }, } @@ -3499,13 +3562,13 @@ func Test_client_TransferProjectsFromUserToOrg(t *testing.T) { if err != nil { panic(err) } - got, err := c.TransferProjectsFromUserToOrg(tt.args.cfg) + got, err := c.UpdateOrganizationMember(tt.args.orgID, tt.args.memberID, tt.args.cfg) if (err != nil) != tt.wantErr { - t.Errorf("TransferProjectsFromUserToOrg() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("UpdateOrganizationMember() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("TransferProjectsFromUserToOrg() got = %v, want %v", got, tt.want) + t.Errorf("UpdateOrganizationMember() got = %v, want %v", got, tt.want) } }, )