From 1e1991b5e974f68c0000712aefde20797d252c63 Mon Sep 17 00:00:00 2001 From: Dmitry Kisler Date: Sat, 28 Sep 2024 22:37:46 +0200 Subject: [PATCH] update SDK version Signed-off-by: Dmitry Kisler --- mockhttp.go | 20 +- openAPIDefinition.json | 619 ++++++++++++++++++++++++++++++++++++++--- sdk.go | 241 +++++++++++----- sdk_test.go | 184 +++++++----- 4 files changed, 881 insertions(+), 183 deletions(-) diff --git a/mockhttp.go b/mockhttp.go index cff14ae..d695ebd 100644 --- a/mockhttp.go +++ b/mockhttp.go @@ -191,7 +191,7 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ "/projects/{project_id}/branches": { "GET": mockResponse{ - Content: `{"branches":[{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-23T17:42:25Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-aged-salad-637688","logical_size":28,"name":"main","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800},{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-30T19:09:48Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-sweet-breeze-497520","logical_size":28,"name":"dev2","parent_id":"br-aged-salad-637688","parent_lsn":"0/1DE2850","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-30T19:09:49Z","written_data_bytes":100800},{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-30T17:36:57Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-raspy-hill-832856","logical_size":21,"name":"dev1","parent_id":"br-aged-salad-637688","parent_lsn":"0/19623D8","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-30T17:36:57Z","written_data_bytes":100800}]}`, + Content: `{"annotations":{"br-aged-salad-637688":{"created_at":"2022-11-23T17:42:25Z","object":{"id":"br-aged-salad-637688","type":"console/branch"},"updated_at":"2022-11-23T17:42:26Z","value":{"vercel-commit-ref":"test"}}},"branches":[{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-23T17:42:25Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-aged-salad-637688","logical_size":28,"name":"main","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800},{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-30T19:09:48Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-sweet-breeze-497520","logical_size":28,"name":"dev2","parent_id":"br-aged-salad-637688","parent_lsn":"0/1DE2850","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-30T19:09:49Z","written_data_bytes":100800},{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-30T17:36:57Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-raspy-hill-832856","logical_size":21,"name":"dev1","parent_id":"br-aged-salad-637688","parent_lsn":"0/19623D8","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-30T17:36:57Z","written_data_bytes":100800}]}`, Code: 200, }, "POST": mockResponse{ @@ -270,7 +270,7 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ Code: 200, }, "GET": mockResponse{ - Content: `{"branch":{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-23T17:42:25Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-aged-salad-637688","logical_size":28,"name":"main","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800}}`, + Content: `{"annotation":{"created_at":"2022-11-23T17:42:25Z","object":{"id":"br-aged-salad-637688","type":"console/branch"},"updated_at":"2022-11-23T17:42:26Z","value":{"vercel-commit-ref":"test"}},"branch":{"active_time_seconds":100,"compute_time_seconds":100,"cpu_used_sec":100,"created_at":"2022-11-23T17:42:25Z","creation_source":"console","current_state":"ready","data_transfer_bytes":1000000,"default":true,"id":"br-aged-salad-637688","logical_size":28,"name":"main","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800}}`, Code: 200, }, "PATCH": mockResponse{ @@ -537,6 +537,13 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ Code: 200, }, }, + + "/users/me/projects/transfer": { + "POST": mockResponse{ + Content: `null`, + Code: 200, + }, + }, } // NewMockHTTPClient initiates a mock fo the HTTP client required for the SDK client. @@ -615,14 +622,19 @@ type objPath struct { func parsePath(s string) objPath { switch s { // pass through - case "/user/me", - "/consumption_history/account", + case "/consumption_history/account", "/consumption_history/projects": return objPath{ path: s, } } + if strings.HasPrefix(s, "/user/me/") { + return objPath{ + path: s, + } + } + s = strings.TrimPrefix(s, "/") o := "" var notFoundReq bool diff --git a/openAPIDefinition.json b/openAPIDefinition.json index a7b24ac..2a1d2da 100644 --- a/openAPIDefinition.json +++ b/openAPIDefinition.json @@ -22,6 +22,9 @@ }, { "CookieAuth": [] + }, + { + "TokenCookieAuth": [] } ], "tags": [ @@ -360,7 +363,7 @@ }, "post": { "summary": "Create a project", - "description": "Creates a Neon project.\nA project is the top-level object in the Neon object hierarchy.\nPlan limits define how many projects you can create.\nNeon's Free plan permits one project per Neon account.\nFor more information, see [Manage projects](https://neon.tech/docs/manage/projects/).\n\nYou can specify a region and Postgres version in the request body.\nNeon currently supports PostgreSQL 14, 15, and 16.\nFor supported regions and `region_id` values, see [Regions](https://neon.tech/docs/introduction/regions/).\n", + "description": "Creates a Neon project.\nA project is the top-level object in the Neon object hierarchy.\nPlan limits define how many projects you can create.\nNeon's Free plan permits one project per Neon account.\nFor more information, see [Manage projects](https://neon.tech/docs/manage/projects/).\n\nYou can specify a region and Postgres version in the request body.\nNeon currently supports PostgreSQL 14, 15 and 16. version 17 is coming soon.\nFor supported regions and `region_id` values, see [Regions](https://neon.tech/docs/introduction/regions/).\n", "tags": [ "Project" ], @@ -987,7 +990,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BranchCreateRequest" + "allOf": [ + { + "$ref": "#/components/schemas/BranchCreateRequest" + }, + { + "$ref": "#/components/schemas/AnnotationCreateValueRequest" + } + ] }, "examples": { "branch_only": { @@ -1040,7 +1050,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BranchesResponse" + "allOf": [ + { + "$ref": "#/components/schemas/BranchesResponse" + }, + { + "$ref": "#/components/schemas/AnnotationsMapResponse" + } + ] }, "example": { "branches": [ @@ -1102,7 +1119,20 @@ "protected": false, "creation_source": "console" } - ] + ], + "annotations": { + "br-aged-salad-637688": { + "object": { + "type": "console/branch", + "id": "br-aged-salad-637688" + }, + "value": { + "vercel-commit-ref": "test" + }, + "created_at": "2022-11-23T17:42:25Z", + "updated_at": "2022-11-23T17:42:26Z" + } + } } } } @@ -1147,7 +1177,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BranchResponse" + "allOf": [ + { + "$ref": "#/components/schemas/BranchResponse" + }, + { + "$ref": "#/components/schemas/AnnotationResponse" + } + ] }, "example": { "branch": { @@ -1167,6 +1204,17 @@ "default": true, "protected": false, "creation_source": "console" + }, + "annotation": { + "object": { + "type": "console/branch", + "id": "br-aged-salad-637688" + }, + "value": { + "vercel-commit-ref": "test" + }, + "created_at": "2022-11-23T17:42:25Z", + "updated_at": "2022-11-23T17:42:26Z" } } } @@ -1388,15 +1436,6 @@ "type": "string" } }, - { - "name": "role", - "in": "query", - "description": "The role on whose behalf the schema is retrieved", - "required": true, - "schema": { - "type": "string" - } - }, { "name": "db_name", "in": "query", @@ -3121,7 +3160,7 @@ "/consumption_history/account": { "get": { "summary": "Get account consumption metrics", - "description": "Retrieves consumption metrics for Scale plan accounts. History begins at the time of upgrade.\nAvailable for Scale plan users only.\n", + "description": "Retrieves consumption metrics for Scale and Business plan accounts. History begins at the time of upgrade.\nAvailable for Scale and Business plan users only.\n", "tags": [ "Consumption" ], @@ -3185,7 +3224,7 @@ } }, "403": { - "description": "This endpoint is not available. It is only supported with Scale plan accounts.", + "description": "This endpoint is not available. It is only supported for Scale and Business plan accounts.", "content": { "application/json": { "schema": { @@ -3233,7 +3272,7 @@ "/consumption_history/projects": { "get": { "summary": "Get consumption metrics for each project", - "description": "Retrieves consumption metrics for Scale plan projects. History begins at the time of upgrade.\nAvailable for Scale plan users only.\n", + "description": "Retrieves consumption metrics for Scale and Business plan projects. History begins at the time of upgrade.\nAvailable for Scale and Business plan users only.\nIssuing a call to this API does not wake a project's compute endpoint.\n", "tags": [ "Consumption" ], @@ -3336,7 +3375,7 @@ } }, "403": { - "description": "This endpoint is not available. It is only supported with Scale plan accounts.", + "description": "This endpoint is not available. It is only supported with Scale and Business plan accounts.", "content": { "application/json": { "schema": { @@ -3384,7 +3423,8 @@ "/consumption/projects": { "get": { "summary": "Get project consumption metrics", - "description": "Retrieves consumption metrics for each project for the current billing period.\nFor usage information, see [Retrieving metrics for all projects](https://neon.tech/docs/guides/partner-billing#retrieving-metrics-for-all-projects).\n", + "deprecated": true, + "description": "Retrieves consumption metrics for each project for the current billing period.\nFor usage information, see [Retrieving metrics for all projects](https://neon.tech/docs/guides/partner-billing#retrieving-metrics-for-all-projects).\nIssuing a call to this API does not wake a project's compute endpoint.\n", "tags": [ "Consumption" ], @@ -3500,6 +3540,9 @@ "summary": "Get current user organizations list", "description": "Retrieves information about the current Neon user's organizations\n", "operationId": "getCurrentUserOrganizations", + "tags": [ + "Users" + ], "responses": { "200": { "description": "Returned information about the current user organizations\n", @@ -3516,6 +3559,68 @@ } } } + }, + "/users/me/projects/transfer": { + "post": { + "summary": "Transfer projects from your personal account to a specified destination account", + "description": "Transfers selected projects, identified by their IDs, from your personal account to a specified organization.\nThis API is only available for early access users.\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferProjectsToOrganizationRequest" + } + } + } + }, + "tags": [ + "Users" + ], + "operationId": "transferProjectsFromUserToOrg", + "responses": { + "200": { + "description": "Projects successfully transferred from personal account to organization", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + }, + "406": { + "description": "Transfer failed - the organization has too many projects or its plan is incompatible with the source account. Reduce projects or upgrade the organization.", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/LimitsUnsatisfiedResponse" + }, + { + "$ref": "#/components/schemas/GeneralError" + } + ] + } + } + } + }, + "501": { + "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": { + "schema": { + "$ref": "#/components/schemas/ProjectsWithIntegrationResponse" + } + } + } + }, + "default": { + "$ref": "#/components/responses/GeneralError" + } + } + } } }, "components": { @@ -3629,6 +3734,11 @@ "type": "apiKey", "in": "cookie", "name": "zenith" + }, + "TokenCookieAuth": { + "type": "apiKey", + "in": "cookie", + "name": "keycloak_token" } }, "schemas": { @@ -3638,6 +3748,19 @@ "type": "boolean" } }, + "FeatureFlags": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] + } + }, "ComputeUnit": { "type": "number", "minimum": 0.25 @@ -3680,6 +3803,102 @@ "description": "Empty response.", "properties": {} }, + "AddProjectJWKSRequest": { + "description": "Add a new JWKS to a specific endpoint of a project", + "type": "object", + "required": [ + "jwks_url", + "provider_name" + ], + "properties": { + "jwks_url": { + "description": "The URL that lists the JWKS", + "type": "string" + }, + "provider_name": { + "description": "The name of the authentication provider (e.g., Clerk, Stytch, Auth0)", + "type": "string" + }, + "branch_id": { + "description": "Branch ID", + "type": "string" + }, + "jwt_audience": { + "description": "The name of the required JWT Audience to be used", + "type": "string" + }, + "role_names": { + "description": "The roles the JWKS should be mapped to", + "type": "array", + "maxItems": 10, + "items": { + "type": "string" + } + } + } + }, + "JWKS": { + "type": "object", + "required": [ + "id", + "project_id", + "jwks_url", + "provider_name", + "created_at", + "updated_at" + ], + "properties": { + "id": { + "description": "JWKS ID", + "type": "string" + }, + "project_id": { + "description": "Project ID", + "type": "string" + }, + "branch_id": { + "description": "Branch ID", + "type": "string" + }, + "jwks_url": { + "description": "The URL that lists the JWKS", + "type": "string" + }, + "provider_name": { + "description": "The name of the authentication provider (e.g., Clerk, Stytch, Auth0)", + "type": "string" + }, + "created_at": { + "description": "The date and time when the JWKS was created", + "type": "string", + "format": "date-time" + }, + "updated_at": { + "description": "The date and time when the JWKS was last modified", + "type": "string", + "format": "date-time" + }, + "jwt_audience": { + "description": "The name of the required JWT Audience to be used", + "type": "string" + } + } + }, + "ProjectJWKSResponse": { + "description": "The list of configured JWKS definitions for a project", + "type": "object", + "required": [ + "jwks" + ], + "properties": { + "jwks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/JWKS" + } + } + } + }, "ApiKeyCreateRequest": { "type": "object", "required": [ @@ -3928,7 +4147,8 @@ "disable_maintenance", "apply_storage_config", "prepare_secondary_pageserver", - "switch_pageserver" + "switch_pageserver", + "detach_parent_branch" ] }, "OperationStatus": { @@ -4202,7 +4422,7 @@ "type": "string" }, "history_retention_seconds": { - "description": "The number of seconds to retain point-in-time restore (PITR) backup history for this project.\n", + "description": "The number of seconds to retain the shared history for all branches in this project. The default for all plans is 1 day (86400 seconds).\n", "type": "integer", "format": "int32" }, @@ -4293,15 +4513,15 @@ "type": "object", "properties": { "name": { - "description": "The branch name. If not specified, the default branch name will be used.\n", + "description": "The default branch name. If not specified, the default branch name, `main`, will be used.\n", "type": "string" }, "role_name": { - "description": "The role name. If not specified, the default role name will be used.\n", + "description": "The role name. If not specified, the default role name, `{database_name}_owner`, will be used.\n", "type": "string" }, "database_name": { - "description": "The database name. If not specified, the default database name will be used.\n", + "description": "The database name. If not specified, the default database name, `neondb`, will be used.\n", "type": "string" } } @@ -4334,7 +4554,7 @@ "type": "boolean" }, "history_retention_seconds": { - "description": "The number of seconds to retain the point-in-time restore (PITR) backup history for this project.\nThe default is 604800 seconds (7 days).\n", + "description": "The number of seconds to retain the shared history for all branches in this project.\nThe default is 1 day (86400 seconds).\n", "type": "integer", "format": "int32", "minimum": 0, @@ -4368,7 +4588,7 @@ "$ref": "#/components/schemas/DefaultEndpointSettings" }, "history_retention_seconds": { - "description": "The number of seconds to retain the point-in-time restore (PITR) backup history for this project.\nThe default is 604800 seconds (7 days).\n", + "description": "The number of seconds to retain the shared history for all branches in this project.\nThe default is 1 day (604800 seconds).\n", "type": "integer", "format": "int32", "minimum": 0, @@ -4927,6 +5147,20 @@ "description": "A timestamp indicating when the branch was last reset\n", "type": "string", "format": "date-time" + }, + "created_by": { + "description": "The resolved user model that contains details of the user/org/integration/api_key used for branch creation. This field is filled only in listing/get/create/get/update/delete methods, if it is empty when calling other handlers, it does not mean that it is empty in the system.\n", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the user." + }, + "image": { + "type": "string", + "description": "The URL to the user's avatar image." + } + } } }, "example": { @@ -5300,7 +5534,7 @@ ] }, "EndpointType": { - "description": "The compute endpoint type. Either `read_write` or `read_only`.\nThe `read_only` compute endpoint type is not yet supported.\n", + "description": "The compute endpoint type. Either `read_write` or `read_only`.\n", "type": "string", "enum": [ "read_only", @@ -5337,7 +5571,8 @@ "type": "boolean" }, "primary_branch_only": { - "description": "If true, the list will be applied only to the default branch.", + "deprecated": true, + "description": "DEPRECATED: Use `protected_branches_only`.\nIf true, the list will be applied only to the default branch.\n", "type": "boolean" } } @@ -5579,6 +5814,41 @@ } } }, + "NotificationMetricType": { + "type": "string", + "description": "The metric type for a given notification\n", + "enum": [ + "database_size", + "connections", + "cpu", + "ram", + "compute_over_limit" + ] + }, + "NotificationCategoryType": { + "type": "string", + "description": "The category type for a given notification\n", + "enum": [ + "usage", + "performance" + ] + }, + "NotificationType": { + "type": "string", + "description": "The type of the notification\n", + "enum": [ + "info", + "warning" + ] + }, + "NotificationActionType": { + "type": "string", + "description": "The action type for a given notification\n", + "enum": [ + "upgrade_plan", + "upgrade_cu" + ] + }, "Role": { "type": "object", "required": [ @@ -5654,6 +5924,17 @@ } } }, + "JWKSResponse": { + "type": "object", + "required": [ + "jwks" + ], + "properties": { + "jwks": { + "$ref": "#/components/schemas/JWKS" + } + } + }, "RolesResponse": { "type": "object", "required": [ @@ -5736,6 +6017,7 @@ "required": [ "payment_source", "subscription_type", + "payment_method", "quota_reset_at_last", "name", "email", @@ -5753,6 +6035,9 @@ "subscription_type": { "$ref": "#/components/schemas/BillingSubscriptionType" }, + "payment_method": { + "$ref": "#/components/schemas/BillingPaymentMethod" + }, "quota_reset_at_last": { "description": "The last time the quota was reset. Defaults to the date-time the account is created.\n", "type": "string", @@ -5817,7 +6102,23 @@ "aws_marketplace", "free_v2", "launch", - "scale" + "scale", + "business" + ] + }, + "BillingPaymentMethod": { + "type": "string", + "description": "Indicates whether and how an account makes payments.\n", + "enum": [ + "UNKNOWN", + "none", + "stripe", + "direct_payment", + "aws_mp", + "vercel_mp", + "staff", + "trial", + "sponsorship" ] }, "Database": { @@ -6018,19 +6319,11 @@ "MemberUserInfo": { "type": "object", "required": [ - "email", - "name", - "last_name" + "email" ], "properties": { "email": { "type": "string" - }, - "name": { - "type": "string" - }, - "last_name": { - "type": "string" } } }, @@ -6055,8 +6348,10 @@ "id", "name", "handle", + "plan", "created_at", - "updated_at" + "updated_at", + "managed_by" ], "properties": { "id": { @@ -6068,11 +6363,18 @@ "handle": { "type": "string" }, + "plan": { + "type": "string" + }, "created_at": { "description": "A timestamp indicting when the organization was created\n", "type": "string", "format": "date-time" }, + "managed_by": { + "description": "Organizations created via the Console or the API are managed by `console`.\nOrganizations created by other methods can't be deleted via the Console or the API.\n", + "type": "string" + }, "updated_at": { "description": "A timestamp indicating when the organization was updated\n", "type": "string", @@ -6507,6 +6809,27 @@ } } }, + "TransferProjectsToOrganizationRequest": { + "type": "object", + "required": [ + "org_id", + "project_ids" + ], + "properties": { + "org_id": { + "type": "string" + }, + "project_ids": { + "type": "array", + "minItems": 1, + "maxItems": 400, + "items": { + "type": "string" + }, + "description": "The list of projects ids to transfer. Maximum of 400 project ids" + } + } + }, "VerifyUserPasswordRequest": { "type": "object", "required": [ @@ -6525,7 +6848,9 @@ "github", "google", "hasura", - "keycloak" + "microsoft", + "keycloak", + "test" ] }, "EndpointSettingsData": { @@ -6617,10 +6942,10 @@ } }, "PgVersion": { - "description": "The major Postgres version number. Currently supported versions are `14`, `15`, and `16`.", + "description": "The major Postgres version number. Currently supported versions are `14`, `15`, and `16`. version `17` is coming soon.", "type": "integer", "minimum": 14, - "maximum": 16, + "maximum": 17, "default": 16 }, "HealthCheck": { @@ -6657,6 +6982,106 @@ } } }, + "LimitsUnsatisfiedResponse": { + "type": "object", + "required": [ + "limits" + ], + "properties": { + "limits": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name", + "expected", + "actual" + ], + "properties": { + "name": { + "type": "string" + }, + "expected": { + "type": "string" + }, + "actual": { + "type": "string" + } + } + } + } + }, + "example": { + "limits": [ + { + "name": "projects_count", + "actual": "2", + "expected": "1" + }, + { + "name": "subscription_type", + "actual": "launch", + "expected": "scale" + } + ] + } + }, + "ProjectsWithIntegrationResponse": { + "type": "object", + "required": [ + "projects" + ], + "properties": { + "projects": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "integration" + ], + "properties": { + "id": { + "type": "string" + }, + "integration": { + "type": "string" + } + } + } + } + }, + "example": { + "projects": [ + { + "id": "round-frog-53611540", + "integration": "github" + }, + { + "id": "long-leaf-72329067", + "integration": "vercel" + }, + { + "id": "shrill-bush-06966719", + "integration": "outerbase" + } + ] + } + }, + "UserDeletionConditionName": { + "type": "string", + "enum": [ + "project_count", + "org_admin_membership_count", + "subscription_type" + ] + }, + "OrgDeletionConditionName": { + "type": "string", + "enum": [ + "project_count" + ] + }, "GeneralError": { "type": "object", "description": "General Error", @@ -6717,6 +7142,16 @@ } ] }, + "JWKSCreationOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/JWKSResponse" + }, + { + "$ref": "#/components/schemas/OperationsResponse" + } + ] + }, "SupportTicketSeverity": { "type": "string", "enum": [ @@ -6725,6 +7160,106 @@ "high", "critical" ] + }, + "AnnotationData": { + "type": "object", + "x-tags": [ + "Branch" + ], + "required": [ + "object", + "value" + ], + "properties": { + "object": { + "$ref": "#/components/schemas/AnnotationObjectData" + }, + "value": { + "$ref": "#/components/schemas/AnnotationValueData" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "AnnotationValueData": { + "type": "object", + "description": "Annotation properties.", + "x-tags": [ + "Branch" + ], + "maxProperties": 50, + "additionalProperties": { + "type": "string", + "example": { + "github-commit-ref": "github-branch-name" + } + } + }, + "AnnotationObjectData": { + "type": "object", + "x-tags": [ + "Branch" + ], + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + } + } + }, + "AnnotationCreateValueRequest": { + "type": "object", + "x-tags": [ + "Branch" + ], + "properties": { + "annotation_value": { + "$ref": "#/components/schemas/AnnotationValueData" + } + } + }, + "AnnotationResponse": { + "type": "object", + "x-tags": [ + "Branch" + ], + "required": [ + "annotation" + ], + "properties": { + "annotation": { + "$ref": "#/components/schemas/AnnotationData" + } + } + }, + "AnnotationsMapResponse": { + "type": "object", + "x-tags": [ + "Branch" + ], + "required": [ + "annotations" + ], + "properties": { + "annotations": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AnnotationData" + } + } + } } } } diff --git a/sdk.go b/sdk.go index 7e14367..f976199 100644 --- a/sdk.go +++ b/sdk.go @@ -191,7 +191,7 @@ func (c Client) ListProjects(cursor *string, limit *int, search *string, orgID * // Neon's Free plan permits one project per Neon account. // For more information, see [Manage projects](https://neon.tech/docs/manage/projects/). // You can specify a region and Postgres version in the request body. -// Neon currently supports PostgreSQL 14, 15, and 16. +// Neon currently supports PostgreSQL 14, 15 and 16. version 17 is coming soon. // For supported regions and `region_id` values, see [Regions](https://neon.tech/docs/introduction/regions/). func (c Client) CreateProject(cfg ProjectCreateRequest) (CreatedProject, error) { var v CreatedProject @@ -228,6 +228,18 @@ func (c Client) ListSharedProjects(cursor *string, limit *int, search *string) ( return v, nil } +// DeleteProject Deletes the specified project. +// You can obtain a `project_id` by listing the projects for your Neon account. +// Deleting a project is a permanent action. +// Deleting a project also deletes endpoints, branches, databases, and users that belong to the project. +func (c Client) DeleteProject(projectID string) (ProjectResponse, error) { + var v ProjectResponse + if err := c.requestHandler(c.baseURL+"/projects/"+projectID, "DELETE", nil, &v); err != nil { + return ProjectResponse{}, err + } + return v, nil +} + // GetProject Retrieves information about the specified project. // A project is the top-level object in the Neon object hierarchy. // You can obtain a `project_id` by listing the projects for your Neon account. @@ -250,18 +262,6 @@ func (c Client) UpdateProject(projectID string, cfg ProjectUpdateRequest) (Updat return v, nil } -// DeleteProject Deletes the specified project. -// You can obtain a `project_id` by listing the projects for your Neon account. -// Deleting a project is a permanent action. -// Deleting a project also deletes endpoints, branches, databases, and users that belong to the project. -func (c Client) DeleteProject(projectID string) (ProjectResponse, error) { - var v ProjectResponse - if err := c.requestHandler(c.baseURL+"/projects/"+projectID, "DELETE", nil, &v); err != nil { - return ProjectResponse{}, err - } - return v, nil -} - // ListProjectOperations Retrieves a list of operations for the specified Neon project. // You can obtain a `project_id` by listing the projects for your Neon account. // The number of operations returned can be large. @@ -357,10 +357,10 @@ func (c Client) GetConnectionURI(projectID string, branchID *string, endpointID // A project may contain child branches that were branched from `main` or from another branch. // A parent branch is identified by the `parent_id` value, which is the `id` of the parent branch. // For related information, see [Manage branches](https://neon.tech/docs/manage/branches/). -func (c Client) ListProjectBranches(projectID string) (BranchesResponse, error) { - var v BranchesResponse +func (c Client) ListProjectBranches(projectID string) (ListProjectBranchesRespObj, error) { + var v ListProjectBranchesRespObj if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches", "GET", nil, &v); err != nil { - return BranchesResponse{}, err + return ListProjectBranchesRespObj{}, err } return v, nil } @@ -372,7 +372,7 @@ func (c Client) ListProjectBranches(projectID string) (BranchesResponse, error) // There is a maximum of one read-write endpoint per branch. // A branch can have multiple read-only endpoints. // For related information, see [Manage branches](https://neon.tech/docs/manage/branches/). -func (c Client) CreateProjectBranch(projectID string, cfg *BranchCreateRequest) (CreatedBranch, error) { +func (c Client) CreateProjectBranch(projectID string, cfg *CreateProjectBranchReqObj) (CreatedBranch, error) { var v CreatedBranch if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches", "POST", cfg, &v); err != nil { return CreatedBranch{}, err @@ -406,10 +406,10 @@ func (c Client) DeleteProjectBranch(projectID string, branchID string) (BranchOp // A project can contain one or more branches. // A parent branch is identified by a `parent_id` value, which is the `id` of the parent branch. // For related information, see [Manage branches](https://neon.tech/docs/manage/branches/). -func (c Client) GetProjectBranch(projectID string, branchID string) (BranchResponse, error) { - var v BranchResponse +func (c Client) GetProjectBranch(projectID string, branchID string) (GetProjectBranchRespObj, error) { + var v GetProjectBranchRespObj if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches/"+branchID, "GET", nil, &v); err != nil { - return BranchResponse{}, err + return GetProjectBranchRespObj{}, err } return v, nil } @@ -436,12 +436,11 @@ func (c Client) RestoreProjectBranch(projectID string, branchID string, cfg Bran } // GetProjectBranchSchema Retrieves the schema from the specified database. The `lsn` and `timestamp` values cannot be specified at the same time. If both are omitted, the database schema is retrieved from database's head . -func (c Client) GetProjectBranchSchema(projectID string, branchID string, role string, dbName string, lsn *string, timestamp *time.Time) (BranchSchemaResponse, error) { +func (c Client) GetProjectBranchSchema(projectID string, branchID string, dbName string, lsn *string, timestamp *time.Time) (BranchSchemaResponse, error) { var ( queryElements []string query string ) - queryElements = append(queryElements, "role="+role) queryElements = append(queryElements, "db_name="+dbName) if lsn != nil { queryElements = append(queryElements, "lsn="+*lsn) @@ -525,6 +524,18 @@ func (c Client) CreateProjectBranchDatabase(projectID string, branchID string, c return v, nil } +// GetProjectBranchDatabase Retrieves information about the specified database. +// You can obtain a `project_id` by listing the projects for your Neon account. +// You can obtain the `branch_id` and `database_name` by listing the branch's databases. +// For related information, see [Manage databases](https://neon.tech/docs/manage/databases/). +func (c Client) GetProjectBranchDatabase(projectID string, branchID string, databaseName string) (DatabaseResponse, error) { + var v DatabaseResponse + if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches/"+branchID+"/databases/"+databaseName, "GET", nil, &v); err != nil { + return DatabaseResponse{}, err + } + return v, nil +} + // UpdateProjectBranchDatabase Updates the specified database in the branch. // You can obtain a `project_id` by listing the projects for your Neon account. // You can obtain the `branch_id` and `database_name` by listing the branch's databases. @@ -549,18 +560,6 @@ func (c Client) DeleteProjectBranchDatabase(projectID string, branchID string, d return v, nil } -// GetProjectBranchDatabase Retrieves information about the specified database. -// You can obtain a `project_id` by listing the projects for your Neon account. -// You can obtain the `branch_id` and `database_name` by listing the branch's databases. -// For related information, see [Manage databases](https://neon.tech/docs/manage/databases/). -func (c Client) GetProjectBranchDatabase(projectID string, branchID string, databaseName string) (DatabaseResponse, error) { - var v DatabaseResponse - if err := c.requestHandler(c.baseURL+"/projects/"+projectID+"/branches/"+branchID+"/databases/"+databaseName, "GET", nil, &v); err != nil { - return DatabaseResponse{}, err - } - return v, nil -} - // ListProjectBranchRoles Retrieves a list of Postgres roles from the specified 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. @@ -761,8 +760,8 @@ func (c Client) RestartProjectEndpoint(projectID string, endpointID string) (End return v, nil } -// GetConsumptionHistoryPerAccount Retrieves consumption metrics for Scale plan accounts. History begins at the time of upgrade. -// Available for Scale plan users only. +// GetConsumptionHistoryPerAccount Retrieves consumption metrics for Scale and Business plan accounts. History begins at the time of upgrade. +// Available for Scale and Business plan users only. func (c Client) GetConsumptionHistoryPerAccount(from time.Time, to time.Time, granularity ConsumptionHistoryGranularity, orgID *string, includeV1Metrics *bool) (ConsumptionHistoryPerAccountResponse, error) { var ( queryElements []string @@ -792,8 +791,9 @@ func (c Client) GetConsumptionHistoryPerAccount(from time.Time, to time.Time, gr return v, nil } -// GetConsumptionHistoryPerProject Retrieves consumption metrics for Scale plan projects. History begins at the time of upgrade. -// Available for Scale plan users only. +// GetConsumptionHistoryPerProject Retrieves consumption metrics for Scale and Business plan projects. History begins at the time of upgrade. +// Available for Scale and Business plan users only. +// Issuing a call to this API does not wake a project's compute endpoint. func (c Client) GetConsumptionHistoryPerProject(cursor *string, limit *int, projectIDs []string, from time.Time, to time.Time, granularity ConsumptionHistoryGranularity, orgID *string, includeV1Metrics *bool) (GetConsumptionHistoryPerProjectRespObj, error) { var ( queryElements []string @@ -834,6 +834,7 @@ func (c Client) GetConsumptionHistoryPerProject(cursor *string, limit *int, proj // ListProjectsConsumption Retrieves consumption metrics for each project for the current billing period. // For usage information, see [Retrieving metrics for all projects](https://neon.tech/docs/guides/partner-billing#retrieving-metrics-for-all-projects). +// Issuing a call to this API does not wake a project's compute endpoint. func (c Client) ListProjectsConsumption(cursor *string, limit *int, from *time.Time, to *time.Time, orgID *string) (ListProjectsConsumptionRespObj, error) { var ( queryElements []string @@ -882,18 +883,58 @@ func (c Client) GetCurrentUserOrganizations() (OrganizationsResponse, error) { return v, nil } +// TransferProjectsFromUserToOrg Transfers selected projects, identified by their IDs, from your personal account to a specified organization. +// This API is only available for early access users. +func (c Client) TransferProjectsFromUserToOrg(cfg TransferProjectsToOrganizationRequest) (EmptyResponse, error) { + var v EmptyResponse + if err := c.requestHandler(c.baseURL+"/users/me/projects/transfer", "POST", cfg, &v); err != nil { + return EmptyResponse{}, err + } + return v, nil +} + // AllowedIps A list of IP addresses that are allowed to connect to the compute endpoint. // If the list is empty or not set, all IP addresses are allowed. // If protected_branches_only is true, the list will be applied only to protected branches. type AllowedIps struct { // Ips A list of IP addresses that are allowed to connect to the endpoint. Ips *[]string `json:"ips,omitempty"` - // PrimaryBranchOnly If true, the list will be applied only to the default branch. + // PrimaryBranchOnly DEPRECATED: Use `protected_branches_only`. + // If true, the list will be applied only to the default branch. PrimaryBranchOnly *bool `json:"primary_branch_only,omitempty"` // ProtectedBranchesOnly If true, the list will be applied only to protected branches. ProtectedBranchesOnly *bool `json:"protected_branches_only,omitempty"` } +type AnnotationCreateValueRequest struct { + AnnotationValue *AnnotationValueData `json:"annotation_value,omitempty"` +} + +type AnnotationData struct { + CreatedAt *time.Time `json:"created_at,omitempty"` + Object AnnotationObjectData `json:"object"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Value AnnotationValueData `json:"value"` +} + +type AnnotationObjectData struct { + ID string `json:"id"` + Type string `json:"type"` +} + +type AnnotationResponse struct { + Annotation AnnotationData `json:"annotation"` +} + +// AnnotationValueData Annotation properties. +type AnnotationValueData map[string]interface{} + +type AnnotationsMapResponse struct { + Annotations AnnotationsMapResponseAnnotations `json:"annotations"` +} + +type AnnotationsMapResponseAnnotations map[string]interface{} + type ApiKeyCreateRequest struct { // KeyName A user-specified API key name. This value is required when creating an API key. KeyName string `json:"key_name"` @@ -956,8 +997,9 @@ type BillingAccount struct { // Name The full name of the individual or entity that owns the billing account. This name appears on invoices. Name string `json:"name"` // OrbPortalURL Orb user portal url - OrbPortalURL *string `json:"orb_portal_url,omitempty"` - PaymentSource PaymentSource `json:"payment_source"` + OrbPortalURL *string `json:"orb_portal_url,omitempty"` + PaymentMethod BillingPaymentMethod `json:"payment_method"` + PaymentSource PaymentSource `json:"payment_source"` // QuotaResetAtLast The last time the quota was reset. Defaults to the date-time the account is created. QuotaResetAtLast time.Time `json:"quota_reset_at_last"` SubscriptionType BillingSubscriptionType `json:"subscription_type"` @@ -967,17 +1009,33 @@ type BillingAccount struct { TaxIDType *string `json:"tax_id_type,omitempty"` } +// BillingPaymentMethod Indicates whether and how an account makes payments. +type BillingPaymentMethod string + +const ( + BillingPaymentMethodVercelMp BillingPaymentMethod = "vercel_mp" + BillingPaymentMethodSponsorship BillingPaymentMethod = "sponsorship" + BillingPaymentMethodStripe BillingPaymentMethod = "stripe" + BillingPaymentMethodDirectPayment BillingPaymentMethod = "direct_payment" + BillingPaymentMethodAwsMp BillingPaymentMethod = "aws_mp" + BillingPaymentMethodStaff BillingPaymentMethod = "staff" + BillingPaymentMethodTrial BillingPaymentMethod = "trial" + BillingPaymentMethodUNKNOWN BillingPaymentMethod = "UNKNOWN" + BillingPaymentMethodNone BillingPaymentMethod = "none" +) + // BillingSubscriptionType Type of subscription to Neon Cloud. // Notice that for users without billing account this will be "UNKNOWN" type BillingSubscriptionType string const ( + BillingSubscriptionTypeFreeV2 BillingSubscriptionType = "free_v2" + BillingSubscriptionTypeLaunch BillingSubscriptionType = "launch" BillingSubscriptionTypeScale BillingSubscriptionType = "scale" + BillingSubscriptionTypeBusiness BillingSubscriptionType = "business" BillingSubscriptionTypeUNKNOWN BillingSubscriptionType = "UNKNOWN" BillingSubscriptionTypeDirectSales BillingSubscriptionType = "direct_sales" BillingSubscriptionTypeAwsMarketplace BillingSubscriptionType = "aws_marketplace" - BillingSubscriptionTypeFreeV2 BillingSubscriptionType = "free_v2" - BillingSubscriptionTypeLaunch BillingSubscriptionType = "launch" ) type Branch struct { @@ -990,7 +1048,8 @@ type Branch struct { // 2. A branch that uses 2 CPUs simultaneously for 1 second is equal to `cpu_used_sec=2`. CpuUsedSec int64 `json:"cpu_used_sec"` // CreatedAt A timestamp indicating when the branch was created - CreatedAt time.Time `json:"created_at"` + CreatedAt time.Time `json:"created_at"` + CreatedBy *BranchCreatedBy `json:"created_by,omitempty"` // CreationSource The branch creation source CreationSource string `json:"creation_source"` CurrentState BranchState `json:"current_state"` @@ -1051,6 +1110,14 @@ type BranchCreateRequestEndpointOptions struct { Type EndpointType `json:"type"` } +// BranchCreatedBy The resolved user model that contains details of the user/org/integration/api_key used for branch creation. This field is filled only in listing/get/create/get/update/delete methods, if it is empty when calling other handlers, it does not mean that it is empty in the system. +type BranchCreatedBy struct { + // Image The URL to the user's avatar image. + Image *string `json:"image,omitempty"` + // Name The name of the user. + Name *string `json:"name,omitempty"` +} + type BranchOperations struct { BranchResponse OperationsResponse @@ -1171,6 +1238,11 @@ type ConsumptionHistoryPerTimeframe struct { WrittenDataBytes int `json:"written_data_bytes"` } +type CreateProjectBranchReqObj struct { + AnnotationCreateValueRequest + BranchCreateRequest +} + type CreatedBranch struct { BranchResponse ConnectionURIsOptionalResponse @@ -1275,6 +1347,9 @@ type DefaultEndpointSettings struct { SuspendTimeoutSeconds *SuspendTimeoutSeconds `json:"suspend_timeout_seconds,omitempty"` } +// EmptyResponse Empty response. +type EmptyResponse map[string]interface{} + type Endpoint struct { AutoscalingLimitMaxCu ComputeUnit `json:"autoscaling_limit_max_cu"` AutoscalingLimitMinCu ComputeUnit `json:"autoscaling_limit_min_cu"` @@ -1379,7 +1454,6 @@ const ( ) // EndpointType The compute endpoint type. Either `read_write` or `read_only`. -// The `read_only` compute endpoint type is not yet supported. type EndpointType string const ( @@ -1421,6 +1495,11 @@ type GetConsumptionHistoryPerProjectRespObj struct { PaginationResponse } +type GetProjectBranchRespObj struct { + AnnotationResponse + BranchResponse +} + type GrantPermissionToProjectRequest struct { Email string `json:"email"` } @@ -1429,10 +1508,12 @@ type GrantPermissionToProjectRequest struct { type IdentityProviderId string const ( - IdentityProviderIdGithub IdentityProviderId = "github" - IdentityProviderIdGoogle IdentityProviderId = "google" - IdentityProviderIdHasura IdentityProviderId = "hasura" - IdentityProviderIdKeycloak IdentityProviderId = "keycloak" + IdentityProviderIdGithub IdentityProviderId = "github" + IdentityProviderIdGoogle IdentityProviderId = "google" + IdentityProviderIdHasura IdentityProviderId = "hasura" + IdentityProviderIdMicrosoft IdentityProviderId = "microsoft" + IdentityProviderIdKeycloak IdentityProviderId = "keycloak" + IdentityProviderIdTest IdentityProviderId = "test" ) type ListOperations struct { @@ -1440,6 +1521,11 @@ type ListOperations struct { PaginationResponse } +type ListProjectBranchesRespObj struct { + AnnotationsMapResponse + BranchesResponse +} + type ListProjectsConsumptionRespObj struct { PaginationResponse ProjectsConsumptionResponse @@ -1484,23 +1570,24 @@ type Operation struct { type OperationAction string const ( + OperationActionStartCompute OperationAction = "start_compute" + OperationActionTenantAttach OperationAction = "tenant_attach" + OperationActionTenantReattach OperationAction = "tenant_reattach" + OperationActionApplyStorageConfig OperationAction = "apply_storage_config" + OperationActionCheckAvailability OperationAction = "check_availability" + OperationActionReplaceSafekeeper OperationAction = "replace_safekeeper" + OperationActionSwitchPageserver OperationAction = "switch_pageserver" + OperationActionCreateCompute OperationAction = "create_compute" + OperationActionCreateTimeline OperationAction = "create_timeline" OperationActionSuspendCompute OperationAction = "suspend_compute" + OperationActionCreateBranch OperationAction = "create_branch" + OperationActionDisableMaintenance OperationAction = "disable_maintenance" + OperationActionApplyConfig OperationAction = "apply_config" OperationActionDeleteTimeline OperationAction = "delete_timeline" OperationActionTenantIgnore OperationAction = "tenant_ignore" OperationActionTenantDetach OperationAction = "tenant_detach" - OperationActionDisableMaintenance OperationAction = "disable_maintenance" - OperationActionCreateCompute OperationAction = "create_compute" - OperationActionApplyConfig OperationAction = "apply_config" - OperationActionCreateBranch OperationAction = "create_branch" - OperationActionTenantReattach OperationAction = "tenant_reattach" - OperationActionReplaceSafekeeper OperationAction = "replace_safekeeper" - OperationActionCreateTimeline OperationAction = "create_timeline" - OperationActionApplyStorageConfig OperationAction = "apply_storage_config" - OperationActionSwitchPageserver OperationAction = "switch_pageserver" - OperationActionStartCompute OperationAction = "start_compute" - OperationActionCheckAvailability OperationAction = "check_availability" - OperationActionTenantAttach OperationAction = "tenant_attach" OperationActionPrepareSecondaryPageserver OperationAction = "prepare_secondary_pageserver" + OperationActionDetachParentBranch OperationAction = "detach_parent_branch" ) type OperationResponse struct { @@ -1530,7 +1617,11 @@ type Organization struct { CreatedAt time.Time `json:"created_at"` Handle string `json:"handle"` ID string `json:"id"` - Name string `json:"name"` + // ManagedBy Organizations created via the Console or the API are managed by `console`. + // Organizations created by other methods can't be deleted via the Console or the API. + ManagedBy string `json:"managed_by"` + Name string `json:"name"` + Plan string `json:"plan"` // UpdatedAt A timestamp indicating when the organization was updated UpdatedAt time.Time `json:"updated_at"` } @@ -1570,7 +1661,7 @@ type PaymentSourceBankCard struct { // PgSettingsData A raw representation of Postgres settings type PgSettingsData map[string]interface{} -// PgVersion The major Postgres version number. Currently supported versions are `14`, `15`, and `16`. +// PgVersion The major Postgres version number. Currently supported versions are `14`, `15`, and `16`. version `17` is coming soon. type PgVersion int // PgbouncerSettingsData A raw representation of PgBouncer settings @@ -1612,7 +1703,7 @@ type Project struct { // Includes deleted endpoints. The value has some lag. The value is reset at the beginning of each billing period. DataTransferBytes int64 `json:"data_transfer_bytes"` DefaultEndpointSettings *DefaultEndpointSettings `json:"default_endpoint_settings,omitempty"` - // HistoryRetentionSeconds The number of seconds to retain point-in-time restore (PITR) backup history for this project. + // HistoryRetentionSeconds The number of seconds to retain the shared history for all branches in this project. The default for all plans is 1 day (86400 seconds). HistoryRetentionSeconds int32 `json:"history_retention_seconds"` // ID The project ID ID string `json:"id"` @@ -1704,8 +1795,8 @@ type ProjectCreateRequestProject struct { AutoscalingLimitMinCu *ComputeUnit `json:"autoscaling_limit_min_cu,omitempty"` Branch *ProjectCreateRequestProjectBranch `json:"branch,omitempty"` DefaultEndpointSettings *DefaultEndpointSettings `json:"default_endpoint_settings,omitempty"` - // HistoryRetentionSeconds The number of seconds to retain the point-in-time restore (PITR) backup history for this project. - // The default is 604800 seconds (7 days). + // HistoryRetentionSeconds The number of seconds to retain the shared history for all branches in this project. + // The default is 1 day (86400 seconds). HistoryRetentionSeconds *int32 `json:"history_retention_seconds,omitempty"` // Name The project name Name *string `json:"name,omitempty"` @@ -1722,11 +1813,11 @@ type ProjectCreateRequestProject struct { } type ProjectCreateRequestProjectBranch struct { - // DatabaseName The database name. If not specified, the default database name will be used. + // DatabaseName The database name. If not specified, the default database name, `neondb`, will be used. DatabaseName *string `json:"database_name,omitempty"` - // Name The branch name. If not specified, the default branch name will be used. + // Name The default branch name. If not specified, the default branch name, `main`, will be used. Name *string `json:"name,omitempty"` - // RoleName The role name. If not specified, the default role name will be used. + // RoleName The role name. If not specified, the default role name, `{database_name}_owner`, will be used. RoleName *string `json:"role_name,omitempty"` } @@ -1841,8 +1932,8 @@ type ProjectUpdateRequest struct { type ProjectUpdateRequestProject struct { DefaultEndpointSettings *DefaultEndpointSettings `json:"default_endpoint_settings,omitempty"` - // HistoryRetentionSeconds The number of seconds to retain the point-in-time restore (PITR) backup history for this project. - // The default is 604800 seconds (7 days). + // HistoryRetentionSeconds The number of seconds to retain the shared history for all branches in this project. + // The default is 1 day (604800 seconds). HistoryRetentionSeconds *int32 `json:"history_retention_seconds,omitempty"` // Name The project name Name *string `json:"name,omitempty"` @@ -1863,8 +1954,8 @@ type ProjectsResponse struct { type Provisioner string const ( - ProvisionerK8sNeonvm Provisioner = "k8s-neonvm" ProvisionerK8sPod Provisioner = "k8s-pod" + ProvisionerK8sNeonvm Provisioner = "k8s-neonvm" ) type Role struct { @@ -1917,6 +2008,12 @@ type RolesResponse struct { // [Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration). type SuspendTimeoutSeconds int64 +type TransferProjectsToOrganizationRequest struct { + OrgID string `json:"org_id"` + // ProjectIDs The list of projects ids to transfer. Maximum of 400 project ids + ProjectIDs []string `json:"project_ids"` +} + type UpdateProjectRespObj struct { OperationsResponse ProjectResponse diff --git a/sdk_test.go b/sdk_test.go index 5bc3759..079ded5 100644 --- a/sdk_test.go +++ b/sdk_test.go @@ -857,7 +857,7 @@ func Test_client_ListSharedProjects(t *testing.T) { } } -func Test_client_GetProject(t *testing.T) { +func Test_client_DeleteProject(t *testing.T) { deserializeResp := func(s string) ProjectResponse { var v ProjectResponse if err := json.Unmarshal([]byte(s), &v); err != nil { @@ -881,7 +881,7 @@ func Test_client_GetProject(t *testing.T) { projectID: "foo", }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["GET"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["DELETE"].Content), wantErr: false, }, { @@ -901,22 +901,22 @@ func Test_client_GetProject(t *testing.T) { if err != nil { panic(err) } - got, err := c.GetProject(tt.args.projectID) + got, err := c.DeleteProject(tt.args.projectID) if (err != nil) != tt.wantErr { - t.Errorf("GetProject() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("DeleteProject() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetProject() got = %v, want %v", got, tt.want) + t.Errorf("DeleteProject() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_UpdateProject(t *testing.T) { - deserializeResp := func(s string) UpdateProjectRespObj { - var v UpdateProjectRespObj +func Test_client_GetProject(t *testing.T) { + deserializeResp := func(s string) ProjectResponse { + var v ProjectResponse if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -924,33 +924,30 @@ func Test_client_UpdateProject(t *testing.T) { } type args struct { projectID string - cfg ProjectUpdateRequest } tests := []struct { name string args args apiKey string - want UpdateProjectRespObj + want ProjectResponse wantErr bool }{ { name: "happy path", args: args{ projectID: "foo", - cfg: ProjectUpdateRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["PATCH"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["GET"].Content), wantErr: false, }, { name: "unhappy path", args: args{ projectID: "foo", - cfg: ProjectUpdateRequest{}, }, apiKey: "invalidApiKey", - want: UpdateProjectRespObj{}, + want: ProjectResponse{}, wantErr: true, }, } @@ -961,22 +958,22 @@ func Test_client_UpdateProject(t *testing.T) { if err != nil { panic(err) } - got, err := c.UpdateProject(tt.args.projectID, tt.args.cfg) + got, err := c.GetProject(tt.args.projectID) if (err != nil) != tt.wantErr { - t.Errorf("UpdateProject() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetProject() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("UpdateProject() got = %v, want %v", got, tt.want) + t.Errorf("GetProject() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_DeleteProject(t *testing.T) { - deserializeResp := func(s string) ProjectResponse { - var v ProjectResponse +func Test_client_UpdateProject(t *testing.T) { + deserializeResp := func(s string) UpdateProjectRespObj { + var v UpdateProjectRespObj if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -984,30 +981,33 @@ func Test_client_DeleteProject(t *testing.T) { } type args struct { projectID string + cfg ProjectUpdateRequest } tests := []struct { name string args args apiKey string - want ProjectResponse + want UpdateProjectRespObj wantErr bool }{ { name: "happy path", args: args{ projectID: "foo", + cfg: ProjectUpdateRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["DELETE"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}"]["PATCH"].Content), wantErr: false, }, { name: "unhappy path", args: args{ projectID: "foo", + cfg: ProjectUpdateRequest{}, }, apiKey: "invalidApiKey", - want: ProjectResponse{}, + want: UpdateProjectRespObj{}, wantErr: true, }, } @@ -1018,13 +1018,13 @@ func Test_client_DeleteProject(t *testing.T) { if err != nil { panic(err) } - got, err := c.DeleteProject(tt.args.projectID) + got, err := c.UpdateProject(tt.args.projectID, tt.args.cfg) if (err != nil) != tt.wantErr { - t.Errorf("DeleteProject() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("UpdateProject() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("DeleteProject() got = %v, want %v", got, tt.want) + t.Errorf("UpdateProject() got = %v, want %v", got, tt.want) } }, ) @@ -1167,8 +1167,8 @@ func Test_client_GetConnectionURI(t *testing.T) { } func Test_client_ListProjectBranches(t *testing.T) { - deserializeResp := func(s string) BranchesResponse { - var v BranchesResponse + deserializeResp := func(s string) ListProjectBranchesRespObj { + var v ListProjectBranchesRespObj if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -1181,7 +1181,7 @@ func Test_client_ListProjectBranches(t *testing.T) { name string args args apiKey string - want BranchesResponse + want ListProjectBranchesRespObj wantErr bool }{ { @@ -1199,7 +1199,7 @@ func Test_client_ListProjectBranches(t *testing.T) { projectID: "foo", }, apiKey: "invalidApiKey", - want: BranchesResponse{}, + want: ListProjectBranchesRespObj{}, wantErr: true, }, } @@ -1233,7 +1233,7 @@ func Test_client_CreateProjectBranch(t *testing.T) { } type args struct { projectID string - cfg *BranchCreateRequest + cfg *CreateProjectBranchReqObj } tests := []struct { name string @@ -1344,8 +1344,8 @@ func Test_client_DeleteProjectBranch(t *testing.T) { } func Test_client_GetProjectBranch(t *testing.T) { - deserializeResp := func(s string) BranchResponse { - var v BranchResponse + deserializeResp := func(s string) GetProjectBranchRespObj { + var v GetProjectBranchRespObj if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -1359,7 +1359,7 @@ func Test_client_GetProjectBranch(t *testing.T) { name string args args apiKey string - want BranchResponse + want GetProjectBranchRespObj wantErr bool }{ { @@ -1379,7 +1379,7 @@ func Test_client_GetProjectBranch(t *testing.T) { branchID: "foo", }, apiKey: "invalidApiKey", - want: BranchResponse{}, + want: GetProjectBranchRespObj{}, wantErr: true, }, } @@ -1540,7 +1540,6 @@ func Test_client_GetProjectBranchSchema(t *testing.T) { type args struct { projectID string branchID string - role string dbName string lsn *string timestamp *time.Time @@ -1557,7 +1556,6 @@ func Test_client_GetProjectBranchSchema(t *testing.T) { args: args{ projectID: "foo", branchID: "foo", - role: "foo", dbName: "foo", lsn: createPointer("foo"), timestamp: createPointer(time.Time{}), @@ -1571,7 +1569,6 @@ func Test_client_GetProjectBranchSchema(t *testing.T) { args: args{ projectID: "foo", branchID: "foo", - role: "foo", dbName: "foo", lsn: createPointer("foo"), timestamp: createPointer(time.Time{}), @@ -1588,7 +1585,7 @@ func Test_client_GetProjectBranchSchema(t *testing.T) { if err != nil { panic(err) } - got, err := c.GetProjectBranchSchema(tt.args.projectID, tt.args.branchID, tt.args.role, tt.args.dbName, tt.args.lsn, tt.args.timestamp) + got, err := c.GetProjectBranchSchema(tt.args.projectID, tt.args.branchID, tt.args.dbName, tt.args.lsn, tt.args.timestamp) if (err != nil) != tt.wantErr { t.Errorf("GetProjectBranchSchema() error = %v, wantErr %v", err, tt.wantErr) return @@ -1904,9 +1901,9 @@ func Test_client_CreateProjectBranchDatabase(t *testing.T) { } } -func Test_client_UpdateProjectBranchDatabase(t *testing.T) { - deserializeResp := func(s string) DatabaseOperations { - var v DatabaseOperations +func Test_client_GetProjectBranchDatabase(t *testing.T) { + deserializeResp := func(s string) DatabaseResponse { + var v DatabaseResponse if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -1916,13 +1913,12 @@ func Test_client_UpdateProjectBranchDatabase(t *testing.T) { projectID string branchID string databaseName string - cfg DatabaseUpdateRequest } tests := []struct { name string args args apiKey string - want DatabaseOperations + want DatabaseResponse wantErr bool }{ { @@ -1931,10 +1927,9 @@ func Test_client_UpdateProjectBranchDatabase(t *testing.T) { projectID: "foo", branchID: "foo", databaseName: "foo", - cfg: DatabaseUpdateRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["PATCH"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["GET"].Content), wantErr: false, }, { @@ -1943,10 +1938,9 @@ func Test_client_UpdateProjectBranchDatabase(t *testing.T) { projectID: "foo", branchID: "foo", databaseName: "foo", - cfg: DatabaseUpdateRequest{}, }, apiKey: "invalidApiKey", - want: DatabaseOperations{}, + want: DatabaseResponse{}, wantErr: true, }, } @@ -1957,20 +1951,20 @@ func Test_client_UpdateProjectBranchDatabase(t *testing.T) { if err != nil { panic(err) } - got, err := c.UpdateProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName, tt.args.cfg) + got, err := c.GetProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName) if (err != nil) != tt.wantErr { - t.Errorf("UpdateProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("UpdateProjectBranchDatabase() got = %v, want %v", got, tt.want) + t.Errorf("GetProjectBranchDatabase() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_DeleteProjectBranchDatabase(t *testing.T) { +func Test_client_UpdateProjectBranchDatabase(t *testing.T) { deserializeResp := func(s string) DatabaseOperations { var v DatabaseOperations if err := json.Unmarshal([]byte(s), &v); err != nil { @@ -1982,6 +1976,7 @@ func Test_client_DeleteProjectBranchDatabase(t *testing.T) { projectID string branchID string databaseName string + cfg DatabaseUpdateRequest } tests := []struct { name string @@ -1996,9 +1991,10 @@ func Test_client_DeleteProjectBranchDatabase(t *testing.T) { projectID: "foo", branchID: "foo", databaseName: "foo", + cfg: DatabaseUpdateRequest{}, }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["DELETE"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["PATCH"].Content), wantErr: false, }, { @@ -2007,6 +2003,7 @@ func Test_client_DeleteProjectBranchDatabase(t *testing.T) { projectID: "foo", branchID: "foo", databaseName: "foo", + cfg: DatabaseUpdateRequest{}, }, apiKey: "invalidApiKey", want: DatabaseOperations{}, @@ -2020,22 +2017,22 @@ func Test_client_DeleteProjectBranchDatabase(t *testing.T) { if err != nil { panic(err) } - got, err := c.DeleteProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName) + got, err := c.UpdateProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName, tt.args.cfg) if (err != nil) != tt.wantErr { - t.Errorf("DeleteProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("UpdateProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("DeleteProjectBranchDatabase() got = %v, want %v", got, tt.want) + t.Errorf("UpdateProjectBranchDatabase() got = %v, want %v", got, tt.want) } }, ) } } -func Test_client_GetProjectBranchDatabase(t *testing.T) { - deserializeResp := func(s string) DatabaseResponse { - var v DatabaseResponse +func Test_client_DeleteProjectBranchDatabase(t *testing.T) { + deserializeResp := func(s string) DatabaseOperations { + var v DatabaseOperations if err := json.Unmarshal([]byte(s), &v); err != nil { panic(err) } @@ -2050,7 +2047,7 @@ func Test_client_GetProjectBranchDatabase(t *testing.T) { name string args args apiKey string - want DatabaseResponse + want DatabaseOperations wantErr bool }{ { @@ -2061,7 +2058,7 @@ func Test_client_GetProjectBranchDatabase(t *testing.T) { databaseName: "foo", }, apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["GET"].Content), + want: deserializeResp(endpointResponseExamples["/projects/{project_id}/branches/{branch_id}/databases/{database_name}"]["DELETE"].Content), wantErr: false, }, { @@ -2072,7 +2069,7 @@ func Test_client_GetProjectBranchDatabase(t *testing.T) { databaseName: "foo", }, apiKey: "invalidApiKey", - want: DatabaseResponse{}, + want: DatabaseOperations{}, wantErr: true, }, } @@ -2083,13 +2080,13 @@ func Test_client_GetProjectBranchDatabase(t *testing.T) { if err != nil { panic(err) } - got, err := c.GetProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName) + got, err := c.DeleteProjectBranchDatabase(tt.args.projectID, tt.args.branchID, tt.args.databaseName) if (err != nil) != tt.wantErr { - t.Errorf("GetProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("DeleteProjectBranchDatabase() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetProjectBranchDatabase() got = %v, want %v", got, tt.want) + t.Errorf("DeleteProjectBranchDatabase() got = %v, want %v", got, tt.want) } }, ) @@ -3261,6 +3258,63 @@ func Test_client_GetCurrentUserOrganizations(t *testing.T) { } } +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 { + cfg TransferProjectsToOrganizationRequest + } + tests := []struct { + name string + args args + apiKey string + want EmptyResponse + wantErr bool + }{ + { + name: "happy path", + args: args{ + cfg: TransferProjectsToOrganizationRequest{}, + }, + apiKey: "foo", + want: deserializeResp(endpointResponseExamples["/users/me/projects/transfer"]["POST"].Content), + wantErr: false, + }, + { + name: "unhappy path", + args: args{ + cfg: TransferProjectsToOrganizationRequest{}, + }, + 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.TransferProjectsFromUserToOrg(tt.args.cfg) + if (err != nil) != tt.wantErr { + t.Errorf("TransferProjectsFromUserToOrg() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("TransferProjectsFromUserToOrg() got = %v, want %v", got, tt.want) + } + }, + ) + } +} + func TestTypes(t *testing.T) { // GIVEN // the types are defined correctly