From baff725debdacae5462d975085395c88c7cc3c06 Mon Sep 17 00:00:00 2001 From: Dmitry Kisler Date: Sun, 20 Oct 2024 13:18:33 +0200 Subject: [PATCH] remove ListProjectsConsumption; enhance response for branch; remove enum values; update changelog. Signed-off-by: Dmitry Kisler --- CHANGELOG.md | 16 +++ mockhttp.go | 25 ++-- openAPIDefinition.json | 310 ++++++++--------------------------------- sdk.go | 124 +++-------------- sdk_test.go | 69 --------- 5 files changed, 106 insertions(+), 438 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c870c4..383b587 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.7.0] - 2024-10-20 + +The release incorporates the up-to-date [API contract](openAPIDefinition.json) as of 2024-10-20 11:15:00 GMT. + +### Added + +- Added the attributes to reflect when and who created, or revoked API keys: + - Added `CreatedBy` to `ApiKeyCreateResponse` and `ApiKeysListResponseItem`; + - Added `CreatedAt` and `CreatedBy` to `ApiKeyRevokeResponse`. + +- Added the attribute `StateChangedAt` to the type `Branch` to reflect when the "current_state" began. + +### Removed + +- **[BREAKING]** Removed the method to list projects consumption `ListProjectsConsumption`. + ## [v0.6.2] - 2024-10-08 The release incorporates the up-to-date [API contract](openAPIDefinition.json) as of 2024-10-08 00:11:00 GMT. diff --git a/mockhttp.go b/mockhttp.go index 6d829de..6ac132b 100644 --- a/mockhttp.go +++ b/mockhttp.go @@ -11,25 +11,18 @@ import ( var endpointResponseExamples = map[string]map[string]mockResponse{ "/api_keys": { "GET": mockResponse{ - Content: `[{"created_at":"2022-11-15T20:13:35Z","id":165432,"last_used_at":"2022-11-15T20:22:51Z","last_used_from_addr":"192.0.2.255","name":"mykey_1"},{"created_at":"2022-11-15T20:12:36Z","id":165433,"last_used_at":"2022-11-15T20:15:04Z","last_used_from_addr":"192.0.2.255","name":"mykey_2"}]`, + Content: `[{"created_at":"2022-11-15T20:13:35Z","created_by":"629982cc-de05-43db-ae16-28f2399c4910","id":165432,"last_used_at":"2022-11-15T20:22:51Z","last_used_from_addr":"192.0.2.255","name":"mykey_1"},{"created_at":"2022-11-15T20:12:36Z","created_by":"629982cc-de05-43db-ae16-28f2399c4910","id":165433,"last_used_at":"2022-11-15T20:15:04Z","last_used_from_addr":"192.0.2.255","name":"mykey_2"}]`, Code: 200, }, "POST": mockResponse{ - Content: `{"created_at":"2022-11-15T20:13:35Z","id":165434,"key":"9v1faketcjbl4sn1013keyd43n2a8qlfakeog8yvp40hx16keyjo1bpds4y2dfms3","name":"mykey_1"}`, + Content: `{"created_at":"2022-11-15T20:13:35Z","created_by":"629982cc-de05-43db-ae16-28f2399c4910","id":165434,"key":"9v1faketcjbl4sn1013keyd43n2a8qlfakeog8yvp40hx16keyjo1bpds4y2dfms3","name":"mykey_1"}`, Code: 200, }, }, "/api_keys/{key_id}": { "DELETE": mockResponse{ - Content: `{"id":165435,"last_used_at":"2022-11-15T20:15:04Z","last_used_from_addr":"192.0.2.255","name":"mykey","revoked":true}`, - Code: 200, - }, - }, - - "/consumption/projects": { - "GET": mockResponse{ - Content: `null`, + Content: `{"created_at":"2022-11-15T20:13:35Z","created_by":"629982cc-de05-43db-ae16-28f2399c4910","id":165435,"last_used_at":"2022-11-15T20:15:04Z","last_used_from_addr":"192.0.2.255","name":"mykey","revoked":true}`, Code: 200, }, }, @@ -191,7 +184,7 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ "/projects/{project_id}/branches": { "GET": mockResponse{ - 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}]}`, + 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,"state_changed_at":"2022-11-30T20:09:48Z","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,"state_changed_at":"2022-11-30T20:09:48Z","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,"state_changed_at":"2022-11-30T20:09:48Z","updated_at":"2022-11-30T17:36:57Z","written_data_bytes":100800}]}`, Code: 200, }, "POST": mockResponse{ @@ -266,15 +259,15 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ "/projects/{project_id}/branches/{branch_id}": { "DELETE": 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},"operations":[{"action":"suspend_compute","branch_id":"br-sweet-breeze-497520","created_at":"2022-12-01T19:53:05Z","endpoint_id":"ep-soft-violet-752733","failures_count":0,"id":"b6afbc21-2990-4a76-980b-b57d8c2948f2","project_id":"shiny-wind-028834","status":"running","total_duration_ms":100,"updated_at":"2022-12-01T19:53:05Z"},{"action":"delete_timeline","branch_id":"br-sweet-breeze-497520","created_at":"2022-12-01T19:53:05Z","failures_count":0,"id":"b6afbc21-2990-4a76-980b-b57d8c2948f2","project_id":"shiny-wind-028834","status":"scheduling","total_duration_ms":100,"updated_at":"2022-12-01T19:53:05Z"}]}`, + 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,"state_changed_at":"2022-11-30T20:09:48Z","updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800},"operations":[{"action":"suspend_compute","branch_id":"br-sweet-breeze-497520","created_at":"2022-12-01T19:53:05Z","endpoint_id":"ep-soft-violet-752733","failures_count":0,"id":"b6afbc21-2990-4a76-980b-b57d8c2948f2","project_id":"shiny-wind-028834","status":"running","total_duration_ms":100,"updated_at":"2022-12-01T19:53:05Z"},{"action":"delete_timeline","branch_id":"br-sweet-breeze-497520","created_at":"2022-12-01T19:53:05Z","failures_count":0,"id":"b6afbc21-2990-4a76-980b-b57d8c2948f2","project_id":"shiny-wind-028834","status":"scheduling","total_duration_ms":100,"updated_at":"2022-12-01T19:53:05Z"}]}`, Code: 200, }, "GET": mockResponse{ - 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}}`, + 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,"state_changed_at":"2022-11-30T20:09:48Z","updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800}}`, Code: 200, }, "PATCH": 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-icy-dream-250089","name":"mybranch","parent_id":"br-aged-salad-637688","parent_lsn":"0/1E19478","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100800},"operations":[]}`, + 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-icy-dream-250089","name":"mybranch","parent_id":"br-aged-salad-637688","parent_lsn":"0/1E19478","primary":true,"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":100800},"operations":[]}`, Code: 200, }, }, @@ -382,14 +375,14 @@ var endpointResponseExamples = map[string]map[string]mockResponse{ "/projects/{project_id}/branches/{branch_id}/set_as_default": { "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","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100},"operations":[]}`, + 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","primary":true,"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}/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","primary":true,"project_id":"shiny-wind-028834","protected":false,"updated_at":"2022-11-23T17:42:26Z","written_data_bytes":100},"operations":[]}`, + 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","primary":true,"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, }, }, diff --git a/openAPIDefinition.json b/openAPIDefinition.json index 2b88b02..981b772 100644 --- a/openAPIDefinition.json +++ b/openAPIDefinition.json @@ -85,6 +85,7 @@ "id": 165432, "name": "mykey_1", "created_at": "2022-11-15T20:13:35Z", + "created_by": "629982cc-de05-43db-ae16-28f2399c4910", "last_used_at": "2022-11-15T20:22:51Z", "last_used_from_addr": "192.0.2.255" }, @@ -92,6 +93,7 @@ "id": 165433, "name": "mykey_2", "created_at": "2022-11-15T20:12:36Z", + "created_by": "629982cc-de05-43db-ae16-28f2399c4910", "last_used_at": "2022-11-15T20:15:04Z", "last_used_from_addr": "192.0.2.255" } @@ -137,7 +139,8 @@ "id": 165434, "key": "9v1faketcjbl4sn1013keyd43n2a8qlfakeog8yvp40hx16keyjo1bpds4y2dfms3", "name": "mykey_1", - "created_at": "2022-11-15T20:13:35Z" + "created_at": "2022-11-15T20:13:35Z", + "created_by": "629982cc-de05-43db-ae16-28f2399c4910" } } } @@ -179,9 +182,11 @@ "example": { "id": 165435, "name": "mykey", - "revoked": true, + "created_at": "2022-11-15T20:13:35Z", + "created_by": "629982cc-de05-43db-ae16-28f2399c4910", "last_used_at": "2022-11-15T20:15:04Z", - "last_used_from_addr": "192.0.2.255" + "last_used_from_addr": "192.0.2.255", + "revoked": true } } } @@ -1076,6 +1081,7 @@ "project_id": "shiny-wind-028834", "name": "main", "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "logical_size": 28, "created_at": "2022-11-23T17:42:25Z", "updated_at": "2022-11-23T17:42:26Z", @@ -1096,6 +1102,7 @@ "parent_lsn": "0/1DE2850", "name": "dev2", "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "logical_size": 28, "created_at": "2022-11-30T19:09:48Z", "updated_at": "2022-11-30T19:09:49Z", @@ -1116,6 +1123,7 @@ "parent_lsn": "0/19623D8", "name": "dev1", "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "logical_size": 21, "created_at": "2022-11-30T17:36:57Z", "updated_at": "2022-11-30T17:36:57Z", @@ -1202,6 +1210,7 @@ "project_id": "shiny-wind-028834", "name": "main", "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "logical_size": 28, "created_at": "2022-11-23T17:42:25Z", "updated_at": "2022-11-23T17:42:26Z", @@ -1256,6 +1265,7 @@ "project_id": "shiny-wind-028834", "name": "main", "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "logical_size": 28, "created_at": "2022-11-23T17:42:25Z", "updated_at": "2022-11-23T17:42:26Z", @@ -1341,6 +1351,7 @@ "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", "data_transfer_bytes": 1000000, @@ -1540,6 +1551,7 @@ "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", "primary": true, @@ -1607,6 +1619,7 @@ "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", "primary": true, @@ -3430,96 +3443,6 @@ } } }, - "/consumption/projects": { - "get": { - "summary": "Get project consumption metrics", - "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" - ], - "operationId": "listProjectsConsumption", - "parameters": [ - { - "name": "cursor", - "description": "Specify the cursor value from the previous response to get the next batch of projects", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "description": "Specify a value from 1 to 1000 to limit number of projects in the response", - "in": "query", - "schema": { - "type": "integer", - "minimum": 1, - "default": 10, - "maximum": 1000 - } - }, - { - "name": "from", - "description": "Specify the start date-time for the consumption period.\nThe time value must be provided in ISO 8601 format.\nIf `from` or `to` is not specified, we return only current consumption period.\n", - "in": "query", - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "to", - "description": "Specify the end date-time period for the consumption period.\nThe time value must be provided in ISO 8601 format.\nIf `from` or `to` is not specified, only the current consumption period is returned.\n", - "in": "query", - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "org_id", - "description": "Specify the organization for which the project consumption metrics should be returned.\nIf this parameter is not provided, the endpoint will return the metrics for the authenticated\nuser's projects.\n", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Returned a list of project consumption metrics for the Neon account", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ProjectsConsumptionResponse" - }, - { - "$ref": "#/components/schemas/PaginationResponse" - } - ] - } - } - } - }, - "404": { - "description": "Account is not a member of the organization specified by `org_id`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GeneralError" - } - } - } - }, - "default": { - "$ref": "#/components/responses/GeneralError" - } - } - } - }, "/users/me": { "get": { "summary": "Get current user details", @@ -3777,11 +3700,7 @@ }, "Provisioner": { "type": "string", - "description": "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n", - "enum": [ - "k8s-pod", - "k8s-neonvm" - ] + "description": "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n\nProvisioner can be one of the following values:\n* k8s-pod\n* k8s-neonvm\n\nClients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.\n" }, "PaginationResponse": { "type": "object", @@ -3927,7 +3846,8 @@ "key", "id", "name", - "created_at" + "created_at", + "created_by" ], "properties": { "id": { @@ -3947,6 +3867,11 @@ "description": "A timestamp indicating when the API key was created", "type": "string", "format": "date-time" + }, + "created_by": { + "description": "ID of the user who created this API key", + "type": "string", + "format": "uuid" } } }, @@ -3955,8 +3880,10 @@ "required": [ "id", "name", - "revoked", - "last_used_from_addr" + "created_at", + "created_by", + "last_used_from_addr", + "revoked" ], "properties": { "id": { @@ -3968,9 +3895,15 @@ "description": "The user-specified API key name", "type": "string" }, - "revoked": { - "description": "A `true` or `false` value indicating whether the API key is revoked", - "type": "boolean" + "created_at": { + "description": "A timestamp indicating when the API key was created", + "type": "string", + "format": "date-time" + }, + "created_by": { + "description": "ID of the user who created this API key", + "type": "string", + "format": "uuid" }, "last_used_at": { "description": "A timestamp indicating when the API was last used", @@ -3981,16 +3914,21 @@ "last_used_from_addr": { "description": "The IP address from which the API key was last used", "type": "string" + }, + "revoked": { + "description": "A `true` or `false` value indicating whether the API key is revoked", + "type": "boolean" } } }, "ApiKeysListResponseItem": { "type": "object", "required": [ - "last_used_from_addr", "id", "name", - "created_at" + "created_at", + "created_by", + "last_used_from_addr" ], "properties": { "id": { @@ -4007,6 +3945,11 @@ "type": "string", "format": "date-time" }, + "created_by": { + "description": "ID of the user who created this API key", + "type": "string", + "format": "uuid" + }, "last_used_at": { "description": "A timestamp indicating when the API was last used", "type": "string", @@ -4844,141 +4787,6 @@ "monthly" ] }, - "ProjectsConsumptionResponse": { - "type": "object", - "required": [ - "projects", - "periods_in_response" - ], - "properties": { - "projects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectConsumption" - } - }, - "periods_in_response": { - "type": "integer", - "format": "int64" - } - } - }, - "ProjectConsumption": { - "type": "object", - "required": [ - "period_id", - "previous_period_id", - "project_id", - "active_time_seconds", - "compute_time_seconds", - "written_data_bytes", - "data_transfer_bytes", - "data_storage_bytes_hour", - "synthetic_storage_size", - "updated_at", - "period_start", - "period_end" - ], - "properties": { - "project_id": { - "description": "The project ID", - "type": "string" - }, - "period_id": { - "description": "The Id of the consumption period, used to reference the `previous_period_id` field.\n", - "type": "string", - "format": "uuid" - }, - "data_storage_bytes_hour": { - "description": "Bytes-Hour. The amount of storage the project consumed during the billing period. Expect some lag in the reported value.\nThe value is reset at the beginning of each billing period.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "data_storage_bytes_hour_updated_at": { - "description": "The timestamp of the last update of the `data_storage_bytes_hour` field.\n", - "type": "string", - "format": "date-time" - }, - "synthetic_storage_size": { - "description": "Bytes. The current space occupied by project in storage. Expect some lag in the reported value.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "synthetic_storage_size_updated_at": { - "description": "The timestamp of the last update of the `synthetic_storage_size` field.\n", - "type": "string", - "format": "date-time" - }, - "data_transfer_bytes": { - "description": "Bytes. The egress traffic from the Neon cloud to the client for the project over the billing period.\nIncludes egress traffic for deleted endpoints. Expect some lag in the reported value. The value is reset at the beginning of each billing period.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "data_transfer_bytes_updated_at": { - "description": "Timestamp of the last update of `data_transfer_bytes` field\n", - "type": "string", - "format": "date-time" - }, - "written_data_bytes": { - "description": "Bytes. The Amount of WAL that travelled through storage for given project for all branches.\nExpect some lag in the reported value. The value is reset at the beginning of each billing period.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "written_data_bytes_updated_at": { - "description": "The timestamp of the last update of `written_data_bytes` field.\n", - "type": "string", - "format": "date-time" - }, - "compute_time_seconds": { - "description": "Seconds. The number of CPU seconds used by the project's compute endpoints, including compute endpoints that have been deleted.\nExpect some lag in the reported value. The value is reset at the beginning of each billing period.\nExamples:\n1. An endpoint that uses 1 CPU for 1 second is equal to `compute_time=1`.\n2. An endpoint that uses 2 CPUs simultaneously for 1 second is equal to `compute_time=2`.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "compute_time_seconds_updated_at": { - "description": "The timestamp of the last update of `compute_time_seconds` field.\n", - "type": "string", - "format": "date-time" - }, - "active_time_seconds": { - "description": "Seconds. The amount of time that compute endpoints in this project have been active.\nExpect some lag in the reported value.\n\nThe value is reset at the beginning of each billing period.\n", - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "active_time_seconds_updated_at": { - "description": "The timestamp of the last update of the `active_time_seconds` field.\n", - "type": "string", - "format": "date-time" - }, - "updated_at": { - "description": "A timestamp indicating when the period was last updated.\n", - "type": "string", - "format": "date-time" - }, - "period_start": { - "description": "The start of the consumption period.\n", - "type": "string", - "format": "date-time" - }, - "period_end": { - "description": "The end of the consumption period.\n", - "type": "string", - "format": "date-time", - "nullable": true - }, - "previous_period_id": { - "description": "The `period_id` of the previous consumption period.\n", - "type": "string", - "format": "uuid", - "nullable": true - } - } - }, "ProjectLimits": { "type": "object", "required": [ @@ -5067,6 +4875,7 @@ "project_id", "name", "current_state", + "state_changed_at", "creation_source", "created_at", "updated_at", @@ -5111,6 +4920,11 @@ "pending_state": { "$ref": "#/components/schemas/BranchState" }, + "state_changed_at": { + "description": "A UTC timestamp indicating when the `current_state` began\n", + "type": "string", + "format": "date-time" + }, "logical_size": { "description": "The logical size of the branch, in bytes\n", "type": "integer", @@ -5193,6 +5007,7 @@ "name": "dev2", "protected": false, "current_state": "ready", + "state_changed_at": "2022-11-30T20:09:48Z", "creation_source": "console", "created_at": "2022-11-30T19:09:48Z", "updated_at": "2022-12-01T19:53:05Z", @@ -5201,13 +5016,8 @@ } }, "BranchState": { - "description": "The branch state", - "type": "string", - "enum": [ - "init", - "ready", - "archived" - ] + "description": "The branch\u2019s state, indicating if it is initializing, ready for use, or archived.\n * 'init' - the branch is being created but is not available for querying.\n * 'ready' - the branch is fully operational and ready for querying. Expect normal query response times.\n * 'archived' - the branch is stored in cost-effective archival storage. Expect slow query response times.\n", + "type": "string" }, "BranchCreateRequestEndpointOptions": { "type": "object", @@ -6689,7 +6499,9 @@ "format": "uuid" }, "image": { - "type": "string" + "type": "string", + "deprecated": true, + "description": "DEPRECATED. This field is ignored.\n" }, "first_name": { "type": "string" diff --git a/sdk.go b/sdk.go index 2bd1dbb..d83fb2d 100644 --- a/sdk.go +++ b/sdk.go @@ -654,39 +654,6 @@ func (c Client) ListProjects(cursor *string, limit *int, search *string, orgID * return v, nil } -// 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 - query string - ) - if cursor != nil { - queryElements = append(queryElements, "cursor="+*cursor) - } - if limit != nil { - queryElements = append(queryElements, "limit="+strconv.FormatInt(int64(*limit), 10)) - } - if from != nil { - queryElements = append(queryElements, "from="+from.Format(time.RFC3339)) - } - if to != nil { - queryElements = append(queryElements, "to="+to.Format(time.RFC3339)) - } - if orgID != nil { - queryElements = append(queryElements, "org_id="+*orgID) - } - if len(queryElements) > 0 { - query = "?" + strings.Join(queryElements, "&") - } - var v ListProjectsConsumptionRespObj - if err := c.requestHandler(c.baseURL+"/consumption/projects"+query, "GET", nil, &v); err != nil { - return ListProjectsConsumptionRespObj{}, err - } - return v, nil -} - // ListSharedProjects Retrieves a list of shared projects for the Neon account. // A project is the top-level object in the Neon object hierarchy. // For more information, see [Manage projects](https://neon.tech/docs/manage/projects/). @@ -942,6 +909,8 @@ type ApiKeyCreateRequest struct { type ApiKeyCreateResponse struct { // CreatedAt A timestamp indicating when the API key was created CreatedAt time.Time `json:"created_at"` + // CreatedBy ID of the user who created this API key + CreatedBy string `json:"created_by"` // ID The API key ID ID int64 `json:"id"` // Key The generated 64-bit token required to access the Neon API @@ -951,6 +920,10 @@ type ApiKeyCreateResponse struct { } type ApiKeyRevokeResponse struct { + // CreatedAt A timestamp indicating when the API key was created + CreatedAt time.Time `json:"created_at"` + // CreatedBy ID of the user who created this API key + CreatedBy string `json:"created_by"` // ID The API key ID ID int64 `json:"id"` // LastUsedAt A timestamp indicating when the API was last used @@ -966,6 +939,8 @@ type ApiKeyRevokeResponse struct { type ApiKeysListResponseItem struct { // CreatedAt A timestamp indicating when the API key was created CreatedAt time.Time `json:"created_at"` + // CreatedBy ID of the user who created this API key + CreatedBy string `json:"created_by"` // ID The API key ID ID int64 `json:"id"` // LastUsedAt A timestamp indicating when the API was last used @@ -1078,6 +1053,8 @@ type Branch struct { ProjectID string `json:"project_id"` // Protected Whether the branch is protected Protected bool `json:"protected"` + // StateChangedAt A UTC timestamp indicating when the `current_state` began + StateChangedAt time.Time `json:"state_changed_at"` // UpdatedAt A timestamp indicating when the branch was last updated UpdatedAt time.Time `json:"updated_at"` WrittenDataBytes int64 `json:"written_data_bytes"` @@ -1146,15 +1123,12 @@ type BranchSchemaResponse struct { Sql *string `json:"sql,omitempty"` } -// BranchState The branch state +// BranchState The branch’s state, indicating if it is initializing, ready for use, or archived. +// - 'init' - the branch is being created but is not available for querying. +// - 'ready' - the branch is fully operational and ready for querying. Expect normal query response times. +// - 'archived' - the branch is stored in cost-effective archival storage. Expect slow query response times. type BranchState string -const ( - BranchStateArchived BranchState = "archived" - BranchStateInit BranchState = "init" - BranchStateReady BranchState = "ready" -) - type BranchUpdateRequest struct { Branch BranchUpdateRequestBranch `json:"branch"` } @@ -1539,11 +1513,6 @@ type ListProjectBranchesRespObj struct { BranchesResponse } -type ListProjectsConsumptionRespObj struct { - PaginationResponse - ProjectsConsumptionResponse -} - type ListProjectsRespObj struct { PaginationResponse ProjectsApplicationsMapResponse @@ -1753,55 +1722,6 @@ type Project struct { WrittenDataBytes int64 `json:"written_data_bytes"` } -type ProjectConsumption struct { - // ActiveTimeSeconds Seconds. The amount of time that compute endpoints in this project have been active. - // Expect some lag in the reported value. - // - // The value is reset at the beginning of each billing period. - ActiveTimeSeconds int64 `json:"active_time_seconds"` - // ActiveTimeSecondsUpdatedAt The timestamp of the last update of the `active_time_seconds` field. - ActiveTimeSecondsUpdatedAt *time.Time `json:"active_time_seconds_updated_at,omitempty"` - // ComputeTimeSeconds Seconds. The number of CPU seconds used by the project's compute endpoints, including compute endpoints that have been deleted. - // Expect some lag in the reported value. The value is reset at the beginning of each billing period. - // Examples: - // 1. An endpoint that uses 1 CPU for 1 second is equal to `compute_time=1`. - // 2. An endpoint that uses 2 CPUs simultaneously for 1 second is equal to `compute_time=2`. - ComputeTimeSeconds int64 `json:"compute_time_seconds"` - // ComputeTimeSecondsUpdatedAt The timestamp of the last update of `compute_time_seconds` field. - ComputeTimeSecondsUpdatedAt *time.Time `json:"compute_time_seconds_updated_at,omitempty"` - // DataStorageBytesHour Bytes-Hour. The amount of storage the project consumed during the billing period. Expect some lag in the reported value. - // The value is reset at the beginning of each billing period. - DataStorageBytesHour int64 `json:"data_storage_bytes_hour"` - // DataStorageBytesHourUpdatedAt The timestamp of the last update of the `data_storage_bytes_hour` field. - DataStorageBytesHourUpdatedAt *time.Time `json:"data_storage_bytes_hour_updated_at,omitempty"` - // DataTransferBytes Bytes. The egress traffic from the Neon cloud to the client for the project over the billing period. - // Includes egress traffic for deleted endpoints. Expect some lag in the reported value. The value is reset at the beginning of each billing period. - DataTransferBytes int64 `json:"data_transfer_bytes"` - // DataTransferBytesUpdatedAt Timestamp of the last update of `data_transfer_bytes` field - DataTransferBytesUpdatedAt *time.Time `json:"data_transfer_bytes_updated_at,omitempty"` - // PeriodEnd The end of the consumption period. - PeriodEnd time.Time `json:"period_end"` - // PeriodID The Id of the consumption period, used to reference the `previous_period_id` field. - PeriodID string `json:"period_id"` - // PeriodStart The start of the consumption period. - PeriodStart time.Time `json:"period_start"` - // PreviousPeriodID The `period_id` of the previous consumption period. - PreviousPeriodID string `json:"previous_period_id"` - // ProjectID The project ID - ProjectID string `json:"project_id"` - // SyntheticStorageSize Bytes. The current space occupied by project in storage. Expect some lag in the reported value. - SyntheticStorageSize int64 `json:"synthetic_storage_size"` - // SyntheticStorageSizeUpdatedAt The timestamp of the last update of the `synthetic_storage_size` field. - SyntheticStorageSizeUpdatedAt *time.Time `json:"synthetic_storage_size_updated_at,omitempty"` - // UpdatedAt A timestamp indicating when the period was last updated. - UpdatedAt time.Time `json:"updated_at"` - // WrittenDataBytes Bytes. The Amount of WAL that travelled through storage for given project for all branches. - // Expect some lag in the reported value. The value is reset at the beginning of each billing period. - WrittenDataBytes int64 `json:"written_data_bytes"` - // WrittenDataBytesUpdatedAt The timestamp of the last update of `written_data_bytes` field. - WrittenDataBytesUpdatedAt *time.Time `json:"written_data_bytes_updated_at,omitempty"` -} - type ProjectCreateRequest struct { Project ProjectCreateRequestProject `json:"project"` } @@ -1964,24 +1884,20 @@ type ProjectsApplicationsMapResponse struct { type ProjectsApplicationsMapResponseApplications map[string]interface{} -type ProjectsConsumptionResponse struct { - PeriodsInResponse int64 `json:"periods_in_response"` - Projects []ProjectConsumption `json:"projects"` -} - type ProjectsResponse struct { Projects []ProjectListItem `json:"projects"` } // Provisioner The Neon compute provisioner. // Specify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling. +// +// Provisioner can be one of the following values: +// * k8s-pod +// * k8s-neonvm +// +// Clients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too. type Provisioner string -const ( - ProvisionerK8sNeonvm Provisioner = "k8s-neonvm" - ProvisionerK8sPod Provisioner = "k8s-pod" -) - type Role struct { // BranchID The ID of the branch to which the role belongs BranchID string `json:"branch_id"` diff --git a/sdk_test.go b/sdk_test.go index e01de70..2f55c2a 100644 --- a/sdk_test.go +++ b/sdk_test.go @@ -2391,75 +2391,6 @@ func Test_client_ListProjects(t *testing.T) { } } -func Test_client_ListProjectsConsumption(t *testing.T) { - deserializeResp := func(s string) ListProjectsConsumptionRespObj { - var v ListProjectsConsumptionRespObj - if err := json.Unmarshal([]byte(s), &v); err != nil { - panic(err) - } - return v - } - type args struct { - cursor *string - limit *int - from *time.Time - to *time.Time - orgID *string - } - tests := []struct { - name string - args args - apiKey string - want ListProjectsConsumptionRespObj - wantErr bool - }{ - { - name: "happy path", - args: args{ - cursor: createPointer("foo"), - limit: createPointer(1), - from: createPointer(time.Time{}), - to: createPointer(time.Time{}), - orgID: createPointer("foo"), - }, - apiKey: "foo", - want: deserializeResp(endpointResponseExamples["/consumption/projects"]["GET"].Content), - wantErr: false, - }, - { - name: "unhappy path", - args: args{ - cursor: createPointer("foo"), - limit: createPointer(1), - from: createPointer(time.Time{}), - to: createPointer(time.Time{}), - orgID: createPointer("foo"), - }, - apiKey: "invalidApiKey", - want: ListProjectsConsumptionRespObj{}, - 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.ListProjectsConsumption(tt.args.cursor, tt.args.limit, tt.args.from, tt.args.to, tt.args.orgID) - if (err != nil) != tt.wantErr { - t.Errorf("ListProjectsConsumption() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("ListProjectsConsumption() got = %v, want %v", got, tt.want) - } - }, - ) - } -} - func Test_client_ListSharedProjects(t *testing.T) { deserializeResp := func(s string) ListSharedProjectsRespObj { var v ListSharedProjectsRespObj