From 989ed43325a3c47fa32d4655c1b47c4b19e84a6f Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Tue, 16 Jan 2024 16:32:44 -0500 Subject: [PATCH] Refactor imports and remove unused code --- Makefile | 2 +- README.md | 40 + neon_client/__init__.py | 2 +- neon_client/client.py | 193 +++ neon_client/http_client.py | 2 +- neon_client/models.py | 1452 ++++++++++++++++++++ neon_client/openapi_models.py | 1846 -------------------------- neon_client/openapi_models_custom.py | 0 neon_client/resources.py | 108 +- neon_client/v2_client.py | 90 -- 10 files changed, 1734 insertions(+), 2001 deletions(-) create mode 100644 README.md create mode 100644 neon_client/client.py create mode 100644 neon_client/models.py delete mode 100644 neon_client/openapi_models.py delete mode 100644 neon_client/openapi_models_custom.py delete mode 100644 neon_client/v2_client.py diff --git a/Makefile b/Makefile index 466630b..bbda6ff 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ gen-model: fetch-v2-schema --allow-population-by-field-name \ --use-title-as-name \ --reuse-model \ - --field-constraints \ + # --field-constraints \ --disable-appending-item-suffix \ --allow-extra-fields \ --use-annotated \ diff --git a/README.md b/README.md new file mode 100644 index 0000000..c8b0055 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# neon_client: an api wrapper for neon.tech v2 api + + + +## Future Installation + +```bash +$ pip install neon-client +``` + +**Please Note**: this repository is a work in progress. The package is not yet available on PyPi. The above command will not work. + +## Usage + +```pycon +>>> from neon_client import NeonClient + +>>> neon = NeonClient(api_key='your_api_key') + +>>> # Get all the projects +>>> projects = neon.projects() + + +>>> # Get a specific project +>>> project = neon.project(project_id='your_project_id') + +>>> # Get all the databases +>>> databases = neon.databases() + +>>> # Get a specific database +>>> database = neon.database(database_id='your_database_id') + +>>> # Get all the branches for a given database. +>>> branches = neon.branches(database_id='your_database_id') + +>>> # Get a specific branch +>>> branch = neon.branch(database_id='your_database_id', branch_id='your_branch_id') + + +``` diff --git a/neon_client/__init__.py b/neon_client/__init__.py index fcfd5f6..c87c53f 100644 --- a/neon_client/__init__.py +++ b/neon_client/__init__.py @@ -1 +1 @@ -from .v2_client import NeonClient +from .client import NeonClient diff --git a/neon_client/client.py b/neon_client/client.py new file mode 100644 index 0000000..6ea7be0 --- /dev/null +++ b/neon_client/client.py @@ -0,0 +1,193 @@ +from .http_client import Neon_API_V2 +from .resources import ResourceCollection + +from . import models + + +class BaseNeonItem: + def install_neon_client(self, neon): + self.neon = neon + + def __repr__(self): + return str(self) + + +class NeonUser(BaseNeonItem, models.CurrentUserAuthAccount): + @classmethod + def from_get_response(cls, r): + """Create a NeonUser from an API response.""" + + # TODO: is this the right way to do this? + me = r.auth_accounts[0] + + return cls.model_validate(me.model_dump()) + + def __str__(self): + return f"" + + +class NeonProject(BaseNeonItem, models.ProjectListItem): + """A Neon project.""" + + @classmethod + def from_list_response(cls, r): + """Create a list of NeonProjects from an API response.""" + + def gen(): + for project in r.projects: + p = cls.model_validate(project.model_dump()) + + yield p + + return [g for g in gen()] + + @classmethod + def from_get_response(cls, r): + """Create a NeonProject from an API response.""" + + return cls.model_validate(r.model_dump()) + + def __str__(self): + return f"" + + def delete(self): + """Delete this project.""" + + return bool(self.neon.resources.projects.delete(self.id)) + + +class ItemView: + """A view into a single item.""" + + def __init__(self, item, key_id=None, neon=None): + self.neon = neon + self._item = item + self._key_id = key_id + + @property + def item(self): + if self._key_id: + return getattr(self._item, self._key_id) + + return self._item + + def __getattr__(self, name): + return getattr(self.item, name) + + def __setattr__(self, name, value): + if name == "_item": + return super().__setattr__(name, value) + + return setattr(self.item, name, value) + + def __str__(self): + return str(self.item) + + def __repr__(self): + return repr(self.item) + + def __eq__(self, other): + return self.item == other + + def __ne__(self, other): + return self.item != other + + +class CollectionView: + """A view into a collection of items.""" + + def __init__( + self, + collection, + key_ids=None, + collection_id=None, + neon=None, + ): + self.neon = neon + self.pagination = None + + if not key_ids: + key_ids = [] + + self._key_ids = key_ids + if collection_id: + self._collection = getattr(collection, collection_id) + self.pagination = collection.pagination + else: + self._collection = collection + + def __iter__(self): + return iter(self._collection) + + def __getitem__(self, key): + for k in self._key_ids: + for item in self._collection: + if str(getattr(item, k)) == str(key): + return item + + return self._collection[key] + + def __len__(self): + return len(self._collection) + + def __repr__(self): + return repr(self._collection) + + def __str__(self): + return str(self._collection) + + def __contains__(self, item): + return item in self._collection + + def __eq__(self, other): + return self._collection == other + + def __ne__(self, other): + return self._collection != other + + +class NeonClient: + def __init__(self, api_key: str, **kwargs): + self.api = Neon_API_V2(api_key, **kwargs) + self.resources = ResourceCollection(self.api) + + def me(self): + return self.resources.users.get_current_user_info() + + def api_keys(self): + return CollectionView(self.resources.api_keys.get_list(), key_ids=["id"]) + + def projects(self, **kwargs): + return CollectionView( + self.resources.projects.get_list(**kwargs), + key_ids=["id", "name"], + collection_id="projects", + ) + + def project(self, project_id: str, **kwargs): + return self.resources.projects.get(project_id, **kwargs) + + def project_create(self, **kwargs): + return self.resources.projects.create(**kwargs) + + def project_delete(self, project_id: str, **kwargs): + return self.resources.projects.delete(project_id, **kwargs) + + def databases(self, project_id: str, branch_id: str, **kwargs): + return CollectionView( + self.resources.databases.get_list(project_id, branch_id, **kwargs), + key_ids=["id"], + collection_id="databases", + ) + + def database(self, project_id: str, database_id: str, **kwargs): + return self.resources.databases.get(project_id, database_id, **kwargs) + + def branches(self, project_id: str, **kwargs): + return CollectionView( + self.resources.branches.get_list(project_id, **kwargs), + key_ids=["id", "name"], + ) + + def branch(self, project_id: str, branch_id: str): + return self.resources.branches.get(project_id, branch_id) diff --git a/neon_client/http_client.py b/neon_client/http_client.py index 2f0d1ec..ccfbea4 100644 --- a/neon_client/http_client.py +++ b/neon_client/http_client.py @@ -2,7 +2,7 @@ from typing import List import requests from pydantic import BaseModel -from .openapi_models import * +from .models import * from .exceptions import NeonClientException from .__version__ import __version__ diff --git a/neon_client/models.py b/neon_client/models.py new file mode 100644 index 0000000..517721e --- /dev/null +++ b/neon_client/models.py @@ -0,0 +1,1452 @@ +# generated by datamodel-codegen: +# filename: v2.json +# timestamp: 2024-01-16T18:05:01+00:00 +# version: 0.25.2 + +from __future__ import annotations + +from enum import Enum +from uuid import UUID + +from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel + + +class Provisioner(Enum): + """ + The Neon compute provisioner. + Specify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling. + + """ + + k8s_pod = "k8s-pod" + k8s_neonvm = "k8s-neonvm" + + +class Pagination(BaseModel): + """ + Cursor based pagination is used. The user must pass the cursor as is to the backend. + For more information about cursor based pagination, see + https://learn.microsoft.com/en-us/ef/core/querying/pagination#keyset-pagination + + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + cursor: str = Field(..., min_length=1) + + +class EmptyResponse(BaseModel): + """ + Empty response. + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + + +class ApiKeyCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + key_name: str = Field( + ..., + description="A user-specified API key name. This value is required when creating an API key.", + ) + + +class ApiKeyCreateResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: int = Field(..., description="The API key ID") + key: str = Field( + ..., description="The generated 64-bit token required to access the Neon API" + ) + name: str = Field(..., description="The user-specified API key name") + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the API key was created" + ) + + +class ApiKeyRevokeResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: int = Field(..., description="The API key ID") + name: str = Field(..., description="The user-specified API key name") + revoked: bool = Field( + ..., + description="A `true` or `false` value indicating whether the API key is revoked", + ) + last_used_at: AwareDatetime | None = Field( + None, description="A timestamp indicating when the API was last used" + ) + last_used_from_addr: str = Field( + ..., description="The IP address from which the API key was last used" + ) + + +class ApiKeysListResponseItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: int = Field(..., description="The API key ID") + name: str = Field(..., description="The user-specified API key name") + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the API key was created" + ) + last_used_at: AwareDatetime | None = Field( + None, description="A timestamp indicating when the API was last used" + ) + last_used_from_addr: str = Field( + ..., description="The IP address from which the API key was last used" + ) + + +class OperationAction(Enum): + """ + The action performed by the operation + """ + + create_compute = "create_compute" + create_timeline = "create_timeline" + start_compute = "start_compute" + suspend_compute = "suspend_compute" + apply_config = "apply_config" + check_availability = "check_availability" + delete_timeline = "delete_timeline" + create_branch = "create_branch" + tenant_ignore = "tenant_ignore" + tenant_attach = "tenant_attach" + tenant_detach = "tenant_detach" + tenant_reattach = "tenant_reattach" + replace_safekeeper = "replace_safekeeper" + disable_maintenance = "disable_maintenance" + apply_storage_config = "apply_storage_config" + + +class OperationStatus(Enum): + """ + The status of the operation + """ + + running = "running" + finished = "finished" + failed = "failed" + scheduling = "scheduling" + + +class Branch(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str | None = Field( + None, + description="The branch name. If not specified, the default branch name will be used.\n", + ) + role_name: str | None = Field( + None, + description="The role name. If not specified, the default role name will be used.\n", + ) + database_name: str | None = Field( + None, + description="The database name. If not specified, the default database name will be used.\n", + ) + + +class ProjectConsumption(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project_id: str = Field(..., description="The project ID") + period_id: UUID = Field( + ..., + description="The Id of the consumption period, used to reference the `previous_period_id` field.\n", + ) + data_storage_bytes_hour: int = Field( + ..., + 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", + ge=0, + ) + data_storage_bytes_hour_updated_at: AwareDatetime | None = Field( + None, + description="The timestamp of the last update of the `data_storage_bytes_hour` field.\n", + ) + synthetic_storage_size: int = Field( + ..., + description="Bytes. The current space occupied by project in storage. Expect some lag in the reported value.\n", + ge=0, + ) + synthetic_storage_size_updated_at: AwareDatetime | None = Field( + None, + description="The timestamp of the last update of the `synthetic_storage_size` field.\n", + ) + data_transfer_bytes: int = Field( + ..., + 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", + ge=0, + ) + data_transfer_bytes_updated_at: AwareDatetime | None = Field( + None, + description="Timestamp of the last update of `data_transfer_bytes` field\n", + ) + written_data_bytes: int = Field( + ..., + 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", + ge=0, + ) + written_data_bytes_updated_at: AwareDatetime | None = Field( + None, + description="The timestamp of the last update of `written_data_bytes` field.\n", + ) + compute_time_seconds: int = Field( + ..., + 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", + ge=0, + ) + compute_time_seconds_updated_at: AwareDatetime | None = Field( + None, + description="The timestamp of the last update of `compute_time_seconds` field.\n", + ) + active_time_seconds: int = Field( + ..., + 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", + ge=0, + ) + active_time_seconds_updated_at: AwareDatetime | None = Field( + None, + description="The timestamp of the last update of the `active_time_seconds` field.\n", + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the period was last updated.\n" + ) + period_start: AwareDatetime = Field( + ..., description="The start of the consumption period.\n" + ) + period_end: AwareDatetime = Field( + ..., description="The end of the consumption period.\n" + ) + previous_period_id: UUID = Field( + ..., description="The `period_id` of the previous consumption period.\n" + ) + + +class Limits(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + active_time: int + max_projects: int + max_branches: int + max_autoscaling_cu: float + cpu_seconds: int + max_active_endpoints: int + max_read_only_endpoints: int + max_allowed_ips: int + + +class ProjectLimits(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + limits: Limits + + +class BranchState(Enum): + """ + The branch state + """ + + init = "init" + ready = "ready" + + +class Branch2(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + parent_id: str | None = Field( + None, + description="The `branch_id` of the parent branch. If omitted or empty, the branch will be created from the project's primary branch.\n", + ) + name: str | None = Field(None, description="The branch name\n") + parent_lsn: str | None = Field( + None, + description="A Log Sequence Number (LSN) on the parent branch. The branch will be created with data from this LSN.\n", + ) + parent_timestamp: AwareDatetime | None = Field( + None, + description="A timestamp identifying a point in time on the parent branch. The branch will be created with data starting from this point in time.\n", + ) + + +class Branch3(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str | None = None + + +class BranchUpdateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branch: Branch3 + + +class ConnectionParameters(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + database: str = Field(..., description="Database name.\n") + password: str = Field(..., description="Password for the role.\n") + role: str = Field(..., description="Role name.\n") + host: str = Field(..., description="Host name.\n") + pooler_host: str = Field(..., description="Pooler host name.\n") + + +class ConnectionDetails(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + connection_uri: str = Field( + ..., + description="Connection URI is same as specified in https://www.postgresql.org/docs/current/libpq-connect.html#id-1.7.3.8.3.6\nIt is a ready to use string for psql or for DATABASE_URL environment variable.\n", + ) + connection_parameters: ConnectionParameters + + +class EndpointState(Enum): + """ + The state of the compute endpoint + + """ + + init = "init" + active = "active" + idle = "idle" + + +class EndpointType(Enum): + """ + The compute endpoint type. Either `read_write` or `read_only`. + The `read_only` compute endpoint type is not yet supported. + + """ + + read_only = "read_only" + read_write = "read_write" + + +class EndpointPoolerMode(Enum): + """ + The connection pooler mode. Neon supports PgBouncer in `transaction` mode only. + + """ + + transaction = "transaction" + + +class AllowedIps(BaseModel): + """ + A list of IP addresses that are allowed to connect to the endpoint. + If the list is empty, all IP addresses are allowed. + If primary_branch_only is true, the list will be applied only to the primary branch. + + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + ips: list[str] = Field( + ..., + description="A list of IP addresses that are allowed to connect to the endpoint.", + ) + primary_branch_only: bool = Field( + ..., description="If true, the list will be applied only to the primary branch." + ) + + +class ConnectionURIsResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + connection_uris: list[ConnectionDetails] + + +class ConnectionURIsOptionalResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + connection_uris: list[ConnectionDetails] | None = None + + +class EndpointPasswordlessSessionAuthRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + session_id: str + + +class Duration(RootModel[int]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: int = Field( + ..., + description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years.", + ) + + +class StatementData(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + fields: list[str] | None = None + rows: list[list[str]] | None = None + truncated: bool + + +class ExplainData(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + query_plan: str = Field(..., alias="QUERY PLAN") + + +class Role(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branch_id: str = Field( + ..., description="The ID of the branch to which the role belongs\n" + ) + name: str = Field(..., description="The role name\n") + password: str | None = Field(None, description="The role password\n") + protected: bool | None = Field( + None, description="Whether or not the role is system-protected\n" + ) + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the role was created\n" + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the role was last updated\n" + ) + + +class Role1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str = Field( + ..., description="The role name. Cannot exceed 63 bytes in length.\n" + ) + + +class RoleCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + role: Role1 + + +class RoleResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + role: Role + + +class RolesResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + roles: list[Role] + + +class RolePasswordResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + password: str = Field(..., description="The role password\n") + + +class Brand(Enum): + """ + Brand of credit card. + + """ + + amex = "amex" + diners = "diners" + discover = "discover" + jcb = "jcb" + mastercard = "mastercard" + unionpay = "unionpay" + unknown = "unknown" + visa = "visa" + + +class PaymentSourceBankCard(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + last4: str = Field(..., description="Last 4 digits of the card.\n") + brand: Brand | None = Field(None, description="Brand of credit card.\n") + exp_month: int | None = Field(None, description="Credit card expiration month\n") + exp_year: int | None = Field(None, description="Credit card expiration year\n") + + +class PaymentSource(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + type: str = Field(..., description='Type of payment source. E.g. "card".\n') + card: PaymentSourceBankCard | None = None + + +class BillingAccount1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + email: str | None = Field( + None, + description="Billing email, to receive emails related to invoices and subscriptions.\n", + ) + + +class BillingAccountUpdateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + billing_account: BillingAccount1 + + +class BillingSubscriptionType(Enum): + """ + Type of subscription to Neon Cloud. + Notice that for users without billing account this will be "UNKNOWN" + + """ + + unknown = "UNKNOWN" + free = "free" + pro = "pro" + direct_sales = "direct_sales" + aws_marketplace = "aws_marketplace" + + +class Database(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: int = Field(..., description="The database ID\n") + branch_id: str = Field( + ..., description="The ID of the branch to which the database belongs\n" + ) + name: str = Field(..., description="The database name\n") + owner_name: str = Field( + ..., description="The name of role that owns the database\n" + ) + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the database was created\n" + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the database was last updated\n" + ) + + +class Database1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str = Field(..., description="The name of the datbase\n") + owner_name: str = Field( + ..., description="The name of the role that owns the database\n" + ) + + +class DatabaseCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + database: Database1 + + +class Database2(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str | None = Field(None, description="The name of the database\n") + owner_name: str | None = Field( + None, description="The name of the role that owns the database\n" + ) + + +class DatabaseUpdateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + database: Database2 + + +class DatabaseResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + database: Database + + +class DatabasesResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + databases: list[Database] + + +class CurrentUserAuthAccount(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + email: str + image: str + login: str + name: str + provider: str + + +class UpdateUserInfoRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + email: str + id: UUID + image: str | None = None + first_name: str | None = None + last_name: str | None = None + + +class ProjectQuota(BaseModel): + """ + Per-project consumption quota. If the quota is exceeded, all active computes + are automatically suspended and it will not be possible to start them with + an API method call or incoming proxy connections. The only exception is + `logical_size_bytes`, which is applied on per-branch basis, i.e., only the + compute on the branch that exceeds the `logical_size` quota will be suspended. + + Quotas are enforced based on per-project consumption metrics with the same names, + which are reset at the end of each billing period (the first day of the month). + Logical size is also an exception in this case, as it represents the total size + of data stored in a branch, so it is not reset. + + A zero or empty quota value means 'unlimited'. + + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + active_time_seconds: int | None = Field( + None, + description="The total amount of wall-clock time allowed to be spent by the project's compute endpoints.\n", + ge=0, + ) + compute_time_seconds: int | None = Field( + None, + description="The total amount of CPU seconds allowed to be spent by the project's compute endpoints.\n", + ge=0, + ) + written_data_bytes: int | None = Field( + None, + description="Total amount of data written to all of a project's branches.\n", + ge=0, + ) + data_transfer_bytes: int | None = Field( + None, + description="Total amount of data transferred from all of a project's branches using the proxy.\n", + ge=0, + ) + logical_size_bytes: int | None = Field( + None, description="Limit on the logical size of every project's branch.\n", ge=0 + ) + + +class HealthCheck(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + status: str = Field(..., description="Service status") + + +class ProjectOwnerData(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + email: str + branches_limit: int + subscription_type: BillingSubscriptionType + + +class SupportTicketSeverity(Enum): + low = "low" + normal = "normal" + high = "high" + critical = "critical" + + +class PaginationResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + pagination: Pagination | None = None + + +class Operation(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: UUID = Field(..., description="The operation ID") + project_id: str = Field(..., description="The Neon project ID") + branch_id: str | None = Field(None, description="The branch ID") + endpoint_id: str | None = Field(None, description="The endpoint ID") + action: OperationAction + status: OperationStatus + error: str | None = Field(None, description="The error that occured") + failures_count: int = Field( + ..., description="The number of times the operation failed" + ) + retry_at: AwareDatetime | None = Field( + None, description="A timestamp indicating when the operation was last retried" + ) + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the operation was created" + ) + updated_at: AwareDatetime = Field( + ..., + description="A timestamp indicating when the operation status was last updated", + ) + total_duration_ms: int = Field( + ..., description="The total duration of the operation in milliseconds" + ) + + +class OperationResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + operation: Operation + + +class OperationsResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + operations: list[Operation] + + +class ProjectSettingsData(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + quota: ProjectQuota | None = None + allowed_ips: AllowedIps | None = None + enable_logical_replication: bool | None = Field( + None, + description="Sets wal_level=logical for all compute endpoints in this project.\nAll active endpoints will be suspended.\nOnce enabled, logical replication cannot be disabled.\n", + ) + + +class ProjectsConsumptionResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + projects: list[ProjectConsumption] + periods_in_response: int + + +class Branch1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: str = Field( + ..., + description="The branch ID. This value is generated when a branch is created. A `branch_id` value has a `br` prefix. For example: `br-small-term-683261`.\n", + ) + project_id: str = Field( + ..., description="The ID of the project to which the branch belongs\n" + ) + parent_id: str | None = Field( + None, description="The `branch_id` of the parent branch\n" + ) + parent_lsn: str | None = Field( + None, + description="The Log Sequence Number (LSN) on the parent branch from which this branch was created\n", + ) + parent_timestamp: AwareDatetime | None = Field( + None, + description="The point in time on the parent branch from which this branch was created\n", + ) + name: str = Field(..., description="The branch name\n") + current_state: BranchState + pending_state: BranchState | None = None + logical_size: int | None = Field( + None, description="The logical size of the branch, in bytes\n" + ) + creation_source: str = Field(..., description="The branch creation source\n") + primary: bool = Field( + ..., description="Whether the branch is the project's primary branch\n" + ) + cpu_used_sec: int = Field( + ..., + description="CPU seconds used by all the endpoints of the branch, including deleted ones.\nThis value is reset at the beginning of each billing period.\nExamples:\n1. A branch that uses 1 CPU for 1 second is equal to `cpu_used_sec=1`.\n2. A branch that uses 2 CPUs simultaneously for 1 second is equal to `cpu_used_sec=2`.\n", + ) + compute_time_seconds: int + active_time_seconds: int + written_data_bytes: int + data_transfer_bytes: int + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the branch was created\n" + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the branch was last updated\n" + ) + last_reset_at: AwareDatetime | None = Field( + None, description="A timestamp indicating when the branch was last reset\n" + ) + + +class BranchCreateRequestEndpointOptions(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + type: EndpointType + autoscaling_limit_min_cu: float | None = Field( + None, + description="The minimum number of Compute Units. The minimum value is `0.25`.\n See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\n for more information.\n", + # ge=0.25, + ) + autoscaling_limit_max_cu: float | None = Field( + None, + description="The maximum number of Compute Units.\n See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\n for more information.\n", + # ge=0.25, + ) + provisioner: Provisioner | None = None + suspend_timeout_seconds: int | None = Field( + None, + description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", + ge=-1, + le=604800, + ) + + +class BranchCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + endpoints: list[BranchCreateRequestEndpointOptions] | None = None + branch: Branch2 | None = None + + +class BranchResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branch: Branch1 + + +class BranchesResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branches: list[Branch1] + + +class StatementResult(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + data: StatementData | None = None + error: str | None = None + explain_data: list[ExplainData] | None = None + query: str + + +class BillingAccount(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + payment_source: PaymentSource + subscription_type: BillingSubscriptionType + quota_reset_at_last: AwareDatetime = Field( + ..., + description="The last time the quota was reset. Defaults to the date-time the account is created.\n", + ) + email: str = Field( + ..., + description="Billing email, to receive emails related to invoices and subscriptions.\n", + ) + address_city: str = Field(..., description="Billing address city.\n") + address_country: str = Field(..., description="Billing address country.\n") + address_line1: str = Field(..., description="Billing address line 1.\n") + address_line2: str = Field(..., description="Billing address line 2.\n") + address_postal_code: str = Field(..., description="Billing address postal code.\n") + address_state: str = Field(..., description="Billing address state or region.\n") + orb_portal_url: str | None = Field(None, description="Orb user portal url\n") + + +class BillingAccountResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + billing_account: BillingAccount + + +class CurrentUserInfoResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + active_seconds_limit: int = Field( + ..., + description="Control plane observes active endpoints of a user this amount of wall-clock time.\n", + ) + billing_account: BillingAccount + auth_accounts: list[CurrentUserAuthAccount] + email: str + id: str + image: str + login: str + name: str + last_name: str + projects_limit: int + branches_limit: int + max_autoscaling_limit: float = Field(..., ge=0.25) + compute_seconds_limit: int | None = None + plan: str + + +class EndpointSettingsData(BaseModel): + """ + A collection of settings for a compute endpoint + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + pg_settings: dict[str, str] | None = None + pgbouncer_settings: dict[str, str] | None = None + + +class DefaultEndpointSettings(BaseModel): + """ + A collection of settings for a Neon endpoint + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + pg_settings: dict[str, str] | None = None + pgbouncer_settings: dict[str, str] | None = None + autoscaling_limit_min_cu: float | None = Field( + None, + description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + autoscaling_limit_max_cu: float | None = Field( + None, + description="The maximum number of Compute Units. See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + suspend_timeout_seconds: int | None = Field( + None, + description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", + ge=-1, + le=604800, + ) + + +class GeneralError(BaseModel): + """ + General Error + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + code: str + message: str = Field(..., description="Error message") + + +class BranchOperations(BranchResponse, OperationsResponse): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + +class DatabaseOperations(DatabaseResponse, OperationsResponse): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + +class RoleOperations(RoleResponse, OperationsResponse): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + +class ProjectListItem(BaseModel): + """ + Essential data about the project. Full data is available at the getProject endpoint. + + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + id: str = Field(..., description="The project ID\n") + platform_id: str = Field( + ..., + description="The cloud platform identifier. Currently, only AWS is supported, for which the identifier is `aws`.\n", + ) + region_id: str = Field(..., description="The region identifier\n") + name: str = Field(..., description="The project name\n") + provisioner: Provisioner + default_endpoint_settings: DefaultEndpointSettings | None = None + settings: ProjectSettingsData | None = None + pg_version: int = Field( + ..., + description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", + ge=14, + le=16, + ) + proxy_host: str = Field( + ..., + description="The proxy host for the project. This value combines the `region_id`, the `platform_id`, and the Neon domain (`neon.tech`).\n", + ) + branch_logical_size_limit: int = Field( + ..., description="The logical size limit for a branch. The value is in MiB.\n" + ) + branch_logical_size_limit_bytes: int = Field( + ..., description="The logical size limit for a branch. The value is in B.\n" + ) + store_passwords: bool = Field( + ..., + description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n", + ) + active_time: int = Field( + ..., + description="Control plane observed endpoints of this project being active this amount of wall-clock time.\n", + ge=0, + ) + cpu_used_sec: int = Field( + ..., description="DEPRECATED. Use data from the getProject endpoint instead.\n" + ) + maintenance_starts_at: AwareDatetime | None = Field( + None, + description="A timestamp indicating when project maintenance begins. If set, the project is placed into maintenance mode at this time.\n", + ) + creation_source: str = Field(..., description="The project creation source\n") + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the project was created\n" + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the project was last updated\n" + ) + synthetic_storage_size: int | None = Field( + None, + description="The current space occupied by the project in storage, in bytes. Synthetic storage size combines the logical data size and Write-Ahead Log (WAL) size for all branches in a project.\n", + ) + quota_reset_at: AwareDatetime | None = Field( + None, + description="DEPRECATED. Use `consumption_period_end` from the getProject endpoint instead.\nA timestamp indicating when the project quota resets\n", + ) + owner_id: str + compute_last_active_at: AwareDatetime | None = Field( + None, + description="The most recent time when any endpoint of this project was active.\n\nOmitted when observed no actitivy for endpoints of this project.\n", + ) + + +class Project(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + data_storage_bytes_hour: int = Field( + ..., + description="Bytes-Hour. Project consumed that much storage hourly during the billing period. The value has some lag.\nThe value is reset at the beginning of each billing period.\n", + ge=0, + ) + data_transfer_bytes: int = Field( + ..., + description="Bytes. Egress traffic from the Neon cloud to the client for given project over the billing period.\nIncludes deleted endpoints. The value has some lag. The value is reset at the beginning of each billing period.\n", + ge=0, + ) + written_data_bytes: int = Field( + ..., + description="Bytes. Amount of WAL that travelled through storage for given project across all branches.\nThe value has some lag. The value is reset at the beginning of each billing period.\n", + ge=0, + ) + compute_time_seconds: int = Field( + ..., + description="Seconds. The number of CPU seconds used by the project's compute endpoints, including compute endpoints that have been deleted.\nThe value has some lag. 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", + ge=0, + ) + active_time_seconds: int = Field( + ..., + description="Seconds. Control plane observed endpoints of this project being active this amount of wall-clock time.\nThe value has some lag.\nThe value is reset at the beginning of each billing period.\n", + ge=0, + ) + cpu_used_sec: int = Field( + ..., description="DEPRECATED, use compute_time instead.\n" + ) + id: str = Field(..., description="The project ID\n") + platform_id: str = Field( + ..., + description="The cloud platform identifier. Currently, only AWS is supported, for which the identifier is `aws`.\n", + ) + region_id: str = Field(..., description="The region identifier\n") + name: str = Field(..., description="The project name\n") + provisioner: Provisioner + default_endpoint_settings: DefaultEndpointSettings | None = None + settings: ProjectSettingsData | None = None + pg_version: int = Field( + ..., + description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", + ge=14, + le=16, + ) + proxy_host: str = Field( + ..., + description="The proxy host for the project. This value combines the `region_id`, the `platform_id`, and the Neon domain (`neon.tech`).\n", + ) + branch_logical_size_limit: int = Field( + ..., description="The logical size limit for a branch. The value is in MiB.\n" + ) + branch_logical_size_limit_bytes: int = Field( + ..., description="The logical size limit for a branch. The value is in B.\n" + ) + store_passwords: bool = Field( + ..., + description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n", + ) + maintenance_starts_at: AwareDatetime | None = Field( + None, + description="A timestamp indicating when project maintenance begins. If set, the project is placed into maintenance mode at this time.\n", + ) + creation_source: str = Field(..., description="The project creation source\n") + history_retention_seconds: int = Field( + ..., + description="The number of seconds to retain point-in-time restore (PITR) backup history for this project.\n", + ) + created_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the project was created\n" + ) + updated_at: AwareDatetime = Field( + ..., description="A timestamp indicating when the project was last updated\n" + ) + synthetic_storage_size: int | None = Field( + None, + description="The current space occupied by the project in storage, in bytes. Synthetic storage size combines the logical data size and Write-Ahead Log (WAL) size for all branches in a project.\n", + ) + consumption_period_start: AwareDatetime = Field( + ..., + description="A date-time indicating when Neon Cloud started measuring consumption for current consumption period.\n", + ) + consumption_period_end: AwareDatetime = Field( + ..., + description="A date-time indicating when Neon Cloud plans to stop measuring consumption for current consumption period.\n", + ) + quota_reset_at: AwareDatetime | None = Field( + None, + description="DEPRECATED. Use `consumption_period_end` from the getProject endpoint instead.\nA timestamp indicating when the project quota resets.\n", + ) + owner_id: str + owner: ProjectOwnerData | None = None + compute_last_active_at: AwareDatetime | None = Field( + None, + description="The most recent time when any endpoint of this project was active.\n\nOmitted when observed no actitivy for endpoints of this project.\n", + ) + + +class Project1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + settings: ProjectSettingsData | None = None + name: str | None = Field(None, description="The project name") + branch: Branch | None = None + autoscaling_limit_min_cu: float | None = Field( + None, + description="DEPRECATED, use default_endpoint_settings.autoscaling_limit_min_cu instead.\n\nThe minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + autoscaling_limit_max_cu: float | None = Field( + None, + description="DEPRECATED, use default_endpoint_settings.autoscaling_limit_max_cu instead.\n\nThe maximum number of Compute Units. See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + provisioner: Provisioner | None = None + region_id: str | None = Field( + None, + description="The region identifier. Refer to our [Regions](https://neon.tech/docs/introduction/regions) documentation for supported regions. Values are specified in this format: `aws-us-east-1`\n", + ) + default_endpoint_settings: DefaultEndpointSettings | None = None + pg_version: int | None = Field( + None, + description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", + ge=14, + le=16, + ) + store_passwords: bool | None = Field( + None, + description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n", + ) + history_retention_seconds: int | None = Field( + None, + 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", + ge=0, + le=2592000, + ) + + +class ProjectCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project: Project1 + + +class Project2(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + settings: ProjectSettingsData | None = None + name: str | None = Field(None, description="The project name") + default_endpoint_settings: DefaultEndpointSettings | None = None + history_retention_seconds: int | None = Field( + None, + 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", + ge=0, + le=2592000, + ) + + +class ProjectUpdateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project: Project2 + + +class ProjectResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project: Project + + +class ProjectsResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + projects: list[ProjectListItem] + + +class Endpoint(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + host: str = Field( + ..., + description="The hostname of the compute endpoint. This is the hostname specified when connecting to a Neon database.\n", + ) + id: str = Field( + ..., + description="The compute endpoint ID. Compute endpoint IDs have an `ep-` prefix. For example: `ep-little-smoke-851426`\n", + ) + project_id: str = Field( + ..., description="The ID of the project to which the compute endpoint belongs\n" + ) + branch_id: str = Field( + ..., + description="The ID of the branch that the compute endpoint is associated with\n", + ) + autoscaling_limit_min_cu: float = Field( + ..., + description="The minimum number of Compute Units\n", + # ge=0.25 + ) + autoscaling_limit_max_cu: float = Field( + ..., description="The maximum number of Compute Units\n", ge=0.25 + ) + region_id: str = Field(..., description="The region identifier\n") + type: EndpointType + current_state: EndpointState + pending_state: EndpointState | None = None + settings: EndpointSettingsData + pooler_enabled: bool = Field( + ..., + description="Whether connection pooling is enabled for the compute endpoint\n", + ) + pooler_mode: EndpointPoolerMode + disabled: bool = Field( + ..., + description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n", + ) + passwordless_access: bool = Field( + ..., + description="Whether to permit passwordless access to the compute endpoint\n", + ) + last_active: AwareDatetime | None = Field( + None, + description="A timestamp indicating when the compute endpoint was last active\n", + ) + creation_source: str = Field( + ..., description="The compute endpoint creation source\n" + ) + created_at: AwareDatetime = Field( + ..., + description="A timestamp indicating when the compute endpoint was created\n", + ) + updated_at: AwareDatetime = Field( + ..., + description="A timestamp indicating when the compute endpoint was last updated\n", + ) + proxy_host: str = Field( + ..., description='DEPRECATED. Use the "host" property instead.\n' + ) + suspend_timeout_seconds: int = Field( + ..., + description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", + ge=-1, + le=604800, + ) + provisioner: Provisioner + + +class Endpoint1(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branch_id: str = Field( + ..., + description="The ID of the branch the compute endpoint will be associated with\n", + ) + region_id: str | None = Field( + None, + description="The region where the compute endpoint will be created. Only the project's `region_id` is permitted.\n", + ) + type: EndpointType + settings: EndpointSettingsData | None = None + autoscaling_limit_min_cu: float | None = Field( + None, + description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + autoscaling_limit_max_cu: float | None = Field( + None, + description="The maximum number of Compute Units.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + provisioner: Provisioner | None = None + pooler_enabled: bool | None = Field( + None, + description="Whether to enable connection pooling for the compute endpoint\n", + ) + pooler_mode: EndpointPoolerMode | None = None + disabled: bool | None = Field( + None, + description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n", + ) + passwordless_access: bool | None = Field( + None, + description="NOT YET IMPLEMENTED. Whether to permit passwordless access to the compute endpoint.\n", + ) + suspend_timeout_seconds: int | None = Field( + None, + description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", + ge=-1, + le=604800, + ) + + +class EndpointCreateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + endpoint: Endpoint1 + + +class Endpoint2(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + branch_id: str | None = Field( + None, + description="The destination branch ID. The destination branch must not have an exsiting read-write endpoint.\n", + ) + autoscaling_limit_min_cu: float | None = Field( + None, + description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + autoscaling_limit_max_cu: float | None = Field( + None, + description="The maximum number of Compute Units.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", + # ge=0.25, + ) + provisioner: Provisioner | None = None + settings: EndpointSettingsData | None = None + pooler_enabled: bool | None = Field( + None, + description="Whether to enable connection pooling for the compute endpoint\n", + ) + pooler_mode: EndpointPoolerMode | None = None + disabled: bool | None = Field( + None, + description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n", + ) + passwordless_access: bool | None = Field( + None, + description="NOT YET IMPLEMENTED. Whether to permit passwordless access to the compute endpoint.\n", + ) + suspend_timeout_seconds: int | None = Field( + None, + description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", + ge=-1, + le=604800, + ) + + +class EndpointUpdateRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + endpoint: Endpoint2 + + +class EndpointResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + endpoint: Endpoint + + +class EndpointsResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + endpoints: list[Endpoint] + + +class EndpointOperations(EndpointResponse, OperationsResponse): + pass + model_config = ConfigDict( + populate_by_name=True, + ) diff --git a/neon_client/openapi_models.py b/neon_client/openapi_models.py deleted file mode 100644 index 3bfc846..0000000 --- a/neon_client/openapi_models.py +++ /dev/null @@ -1,1846 +0,0 @@ -# generated by datamodel-codegen: -# filename: v2.json -# timestamp: 2024-01-14T23:49:21+00:00 -# version: 0.25.2 - -from __future__ import annotations - -from enum import Enum -from typing import Annotated -from uuid import UUID - -from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel - - -class Provisioner(Enum): - """ - The Neon compute provisioner. - Specify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling. - - """ - - K8S_POD = "k8s-pod" - K8S_NEONVM = "k8s-neonvm" - - -class Pagination(BaseModel): - """ - Cursor based pagination is used. The user must pass the cursor as is to the backend. - For more information about cursor based pagination, see - https://learn.microsoft.com/en-us/ef/core/querying/pagination#keyset-pagination - - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - cursor: Annotated[str, Field(min_length=1)] - - -class EmptyResponse(BaseModel): - """ - Empty response. - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - - -class ApiKeyCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - key_name: Annotated[ - str, - Field( - description="A user-specified API key name. This value is required when creating an API key." - ), - ] - - -class ApiKeyCreateResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[int, Field(description="The API key ID")] - key: Annotated[ - str, - Field(description="The generated 64-bit token required to access the Neon API"), - ] - name: Annotated[str, Field(description="The user-specified API key name")] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the API key was created"), - ] - - -class ApiKeyRevokeResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[int, Field(description="The API key ID")] - name: Annotated[str, Field(description="The user-specified API key name")] - revoked: Annotated[ - bool, - Field( - description="A `true` or `false` value indicating whether the API key is revoked" - ), - ] - last_used_at: Annotated[ - AwareDatetime | None, - Field(None, description="A timestamp indicating when the API was last used"), - ] - last_used_from_addr: Annotated[ - str, Field(description="The IP address from which the API key was last used") - ] - - -class ApiKeysListResponseItem(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[int, Field(description="The API key ID")] - name: Annotated[str, Field(description="The user-specified API key name")] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the API key was created"), - ] - last_used_at: Annotated[ - AwareDatetime | None, - Field(None, description="A timestamp indicating when the API was last used"), - ] - last_used_from_addr: Annotated[ - str, Field(description="The IP address from which the API key was last used") - ] - - -class OperationAction(Enum): - """ - The action performed by the operation - """ - - CREATE_COMPUTE = "create_compute" - CREATE_TIMELINE = "create_timeline" - START_COMPUTE = "start_compute" - SUSPEND_COMPUTE = "suspend_compute" - APPLY_CONFIG = "apply_config" - CHECK_AVAILABILITY = "check_availability" - DELETE_TIMELINE = "delete_timeline" - CREATE_BRANCH = "create_branch" - TENANT_IGNORE = "tenant_ignore" - TENANT_ATTACH = "tenant_attach" - TENANT_DETACH = "tenant_detach" - TENANT_REATTACH = "tenant_reattach" - REPLACE_SAFEKEEPER = "replace_safekeeper" - DISABLE_MAINTENANCE = "disable_maintenance" - APPLY_STORAGE_CONFIG = "apply_storage_config" - - -class OperationStatus(Enum): - """ - The status of the operation - """ - - RUNNING = "running" - FINISHED = "finished" - FAILED = "failed" - SCHEDULING = "scheduling" - - -class Branch(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - name: Annotated[ - str | None, - Field( - None, - description="The branch name. If not specified, the default branch name will be used.\n", - ), - ] - role_name: Annotated[ - str | None, - Field( - None, - description="The role name. If not specified, the default role name will be used.\n", - ), - ] - database_name: Annotated[ - str | None, - Field( - None, - description="The database name. If not specified, the default database name will be used.\n", - ), - ] - - -class ProjectConsumption(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - project_id: Annotated[str, Field(description="The project ID")] - period_id: Annotated[ - UUID, - Field( - description="The Id of the consumption period, used to reference the `previous_period_id` field.\n" - ), - ] - data_storage_bytes_hour: Annotated[ - int, - Field( - 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", - ge=0, - ), - ] - data_storage_bytes_hour_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The timestamp of the last update of the `data_storage_bytes_hour` field.\n", - ), - ] - synthetic_storage_size: Annotated[ - int, - Field( - description="Bytes. The current space occupied by project in storage. Expect some lag in the reported value.\n", - ge=0, - ), - ] - synthetic_storage_size_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The timestamp of the last update of the `synthetic_storage_size` field.\n", - ), - ] - data_transfer_bytes: Annotated[ - int, - Field( - 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", - ge=0, - ), - ] - data_transfer_bytes_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="Timestamp of the last update of `data_transfer_bytes` field\n", - ), - ] - written_data_bytes: Annotated[ - int, - Field( - 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", - ge=0, - ), - ] - written_data_bytes_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The timestamp of the last update of `written_data_bytes` field.\n", - ), - ] - compute_time_seconds: Annotated[ - int, - Field( - 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", - ge=0, - ), - ] - compute_time_seconds_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The timestamp of the last update of `compute_time_seconds` field.\n", - ), - ] - active_time_seconds: Annotated[ - int, - Field( - 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", - ge=0, - ), - ] - active_time_seconds_updated_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The timestamp of the last update of the `active_time_seconds` field.\n", - ), - ] - updated_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the period was last updated.\n"), - ] - period_start: Annotated[ - AwareDatetime, Field(description="The start of the consumption period.\n") - ] - period_end: Annotated[ - AwareDatetime, Field(description="The end of the consumption period.\n") - ] - previous_period_id: Annotated[ - UUID, Field(description="The `period_id` of the previous consumption period.\n") - ] - - -class Limits(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - active_time: int - max_projects: int - max_branches: int - max_autoscaling_cu: float - cpu_seconds: int - max_active_endpoints: int - max_read_only_endpoints: int - max_allowed_ips: int - - -class ProjectLimits(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - limits: Limits - - -class BranchState(Enum): - """ - The branch state - """ - - INIT = "init" - READY = "ready" - - -class Branch2(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - parent_id: Annotated[ - str | None, - Field( - None, - description="The `branch_id` of the parent branch. If omitted or empty, the branch will be created from the project's primary branch.\n", - ), - ] - name: Annotated[str | None, Field(None, description="The branch name\n")] - parent_lsn: Annotated[ - str | None, - Field( - None, - description="A Log Sequence Number (LSN) on the parent branch. The branch will be created with data from this LSN.\n", - ), - ] - parent_timestamp: Annotated[ - AwareDatetime | None, - Field( - None, - description="A timestamp identifying a point in time on the parent branch. The branch will be created with data starting from this point in time.\n", - ), - ] - - -class Branch3(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - name: str | None = None - - -class BranchUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - branch: Branch3 - - -class ConnectionParameters(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - database: Annotated[str, Field(description="Database name.\n")] - password: Annotated[str, Field(description="Password for the role.\n")] - role: Annotated[str, Field(description="Role name.\n")] - host: Annotated[str, Field(description="Host name.\n")] - pooler_host: Annotated[str, Field(description="Pooler host name.\n")] - - -class ConnectionDetails(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - connection_uri: Annotated[ - str, - Field( - description="Connection URI is same as specified in https://www.postgresql.org/docs/current/libpq-connect.html#id-1.7.3.8.3.6\nIt is a ready to use string for psql or for DATABASE_URL environment variable.\n" - ), - ] - connection_parameters: ConnectionParameters - - -class EndpointState(Enum): - """ - The state of the compute endpoint - - """ - - INIT = "init" - ACTIVE = "active" - IDLE = "idle" - - -class EndpointType(Enum): - """ - The compute endpoint type. Either `read_write` or `read_only`. - The `read_only` compute endpoint type is not yet supported. - - """ - - READ_ONLY = "read_only" - READ_WRITE = "read_write" - - -class EndpointPoolerMode(Enum): - """ - The connection pooler mode. Neon supports PgBouncer in `transaction` mode only. - - """ - - TRANSACTION = "transaction" - - -class AllowedIps(BaseModel): - """ - A list of IP addresses that are allowed to connect to the endpoint. - If the list is empty, all IP addresses are allowed. - If primary_branch_only is true, the list will be applied only to the primary branch. - - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - ips: Annotated[ - list[str], - Field( - description="A list of IP addresses that are allowed to connect to the endpoint." - ), - ] - primary_branch_only: Annotated[ - bool, - Field( - description="If true, the list will be applied only to the primary branch." - ), - ] - - -class ConnectionURIsResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - connection_uris: list[ConnectionDetails] - - -class ConnectionURIsOptionalResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - connection_uris: list[ConnectionDetails] | None = None - - -class EndpointPasswordlessSessionAuthRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - session_id: str - - -class Duration(RootModel[int]): - model_config = ConfigDict( - populate_by_name=True, - ) - root: Annotated[ - int, - Field( - description="A Duration represents the elapsed time between two instants\nas an int64 nanosecond count. The representation limits the\nlargest representable duration to approximately 290 years." - ), - ] - - -class StatementData(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - fields: list[str] | None = None - rows: list[list[str]] | None = None - truncated: bool - - -class ExplainData(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - query_plan: Annotated[str, Field(alias="QUERY PLAN")] - - -class Role(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - branch_id: Annotated[ - str, Field(description="The ID of the branch to which the role belongs\n") - ] - name: Annotated[str, Field(description="The role name\n")] - password: Annotated[str | None, Field(None, description="The role password\n")] - protected: Annotated[ - bool | None, - Field(None, description="Whether or not the role is system-protected\n"), - ] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the role was created\n"), - ] - updated_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the role was last updated\n"), - ] - - -class Role1(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - name: Annotated[ - str, Field(description="The role name. Cannot exceed 63 bytes in length.\n") - ] - - -class RoleCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - role: Role1 - - -class RoleResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - role: Role - - -class RolesResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - roles: list[Role] - - -class RolePasswordResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - password: Annotated[str, Field(description="The role password\n")] - - -class Brand(Enum): - """ - Brand of credit card. - - """ - - AMEX = "amex" - DINERS = "diners" - DISCOVER = "discover" - JCB = "jcb" - MASTERCARD = "mastercard" - UNIONPAY = "unionpay" - UNKNOWN = "unknown" - VISA = "visa" - - -class PaymentSourceBankCard(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - last4: Annotated[str, Field(description="Last 4 digits of the card.\n")] - brand: Annotated[Brand | None, Field(None, description="Brand of credit card.\n")] - exp_month: Annotated[ - int | None, Field(None, description="Credit card expiration month\n") - ] - exp_year: Annotated[ - int | None, Field(None, description="Credit card expiration year\n") - ] - - -class PaymentSource(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - type: Annotated[str, Field(description='Type of payment source. E.g. "card".\n')] - card: PaymentSourceBankCard | None = None - - -class BillingAccount1(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - email: Annotated[ - str | None, - Field( - None, - description="Billing email, to receive emails related to invoices and subscriptions.\n", - ), - ] - - -class BillingAccountUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - billing_account: BillingAccount1 - - -class BillingSubscriptionType(Enum): - """ - Type of subscription to Neon Cloud. - Notice that for users without billing account this will be "UNKNOWN" - - """ - - UNKNOWN = "UNKNOWN" - FREE = "free" - PRO = "pro" - DIRECT_SALES = "direct_sales" - AWS_MARKETPLACE = "aws_marketplace" - - -class Database(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[int, Field(description="The database ID\n")] - branch_id: Annotated[ - str, Field(description="The ID of the branch to which the database belongs\n") - ] - name: Annotated[str, Field(description="The database name\n")] - owner_name: Annotated[ - str, Field(description="The name of role that owns the database\n") - ] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the database was created\n"), - ] - updated_at: Annotated[ - AwareDatetime, - Field( - description="A timestamp indicating when the database was last updated\n" - ), - ] - - -class Database1(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - name: Annotated[str, Field(description="The name of the datbase\n")] - owner_name: Annotated[ - str, Field(description="The name of the role that owns the database\n") - ] - - -class DatabaseCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - database: Database1 - - -class Database2(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - name: Annotated[str | None, Field(None, description="The name of the database\n")] - owner_name: Annotated[ - str | None, - Field(None, description="The name of the role that owns the database\n"), - ] - - -class DatabaseUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - database: Database2 - - -class DatabaseResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - database: Database - - -class DatabasesResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - databases: list[Database] - - -class CurrentUserAuthAccount(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - email: str - image: str - login: str - name: str - provider: str - - -class UpdateUserInfoRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - email: str - id: UUID - image: str | None = None - first_name: str | None = None - last_name: str | None = None - - -class ProjectQuota(BaseModel): - """ - Per-project consumption quota. If the quota is exceeded, all active computes - are automatically suspended and it will not be possible to start them with - an API method call or incoming proxy connections. The only exception is - `logical_size_bytes`, which is applied on per-branch basis, i.e., only the - compute on the branch that exceeds the `logical_size` quota will be suspended. - - Quotas are enforced based on per-project consumption metrics with the same names, - which are reset at the end of each billing period (the first day of the month). - Logical size is also an exception in this case, as it represents the total size - of data stored in a branch, so it is not reset. - - A zero or empty quota value means 'unlimited'. - - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - active_time_seconds: Annotated[ - int | None, - Field( - None, - description="The total amount of wall-clock time allowed to be spent by the project's compute endpoints.\n", - ge=0, - ), - ] - compute_time_seconds: Annotated[ - int | None, - Field( - None, - description="The total amount of CPU seconds allowed to be spent by the project's compute endpoints.\n", - ge=0, - ), - ] - written_data_bytes: Annotated[ - int | None, - Field( - None, - description="Total amount of data written to all of a project's branches.\n", - ge=0, - ), - ] - data_transfer_bytes: Annotated[ - int | None, - Field( - None, - description="Total amount of data transferred from all of a project's branches using the proxy.\n", - ge=0, - ), - ] - logical_size_bytes: Annotated[ - int | None, - Field( - None, - description="Limit on the logical size of every project's branch.\n", - ge=0, - ), - ] - - -class HealthCheck(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - status: Annotated[str, Field(description="Service status")] - - -class ProjectOwnerData(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - email: str - branches_limit: int - subscription_type: BillingSubscriptionType - - -class SupportTicketSeverity(Enum): - LOW = "low" - NORMAL = "normal" - HIGH = "high" - CRITICAL = "critical" - - -class PaginationResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - pagination: Pagination | None = None - - -class Operation(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[UUID, Field(description="The operation ID")] - project_id: Annotated[str, Field(description="The Neon project ID")] - branch_id: Annotated[str | None, Field(None, description="The branch ID")] - endpoint_id: Annotated[str | None, Field(None, description="The endpoint ID")] - action: OperationAction - status: OperationStatus - error: Annotated[str | None, Field(None, description="The error that occured")] - failures_count: Annotated[ - int, Field(description="The number of times the operation failed") - ] - retry_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="A timestamp indicating when the operation was last retried", - ), - ] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the operation was created"), - ] - updated_at: Annotated[ - AwareDatetime, - Field( - description="A timestamp indicating when the operation status was last updated" - ), - ] - total_duration_ms: Annotated[ - int, Field(description="The total duration of the operation in milliseconds") - ] - - -class OperationResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - operation: Operation - - -class OperationsResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - operations: list[Operation] - - -class ProjectSettingsData(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - quota: ProjectQuota | None = None - allowed_ips: AllowedIps | None = None - enable_logical_replication: Annotated[ - bool | None, - Field( - None, - description="Sets wal_level=logical for all compute endpoints in this project.\nAll active endpoints will be suspended.\nOnce enabled, logical replication cannot be disabled.\n", - ), - ] - - -class ProjectsConsumptionResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - projects: list[ProjectConsumption] - periods_in_response: int - - -class Branch1(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[ - str, - Field( - description="The branch ID. This value is generated when a branch is created. A `branch_id` value has a `br` prefix. For example: `br-small-term-683261`.\n" - ), - ] - project_id: Annotated[ - str, Field(description="The ID of the project to which the branch belongs\n") - ] - parent_id: Annotated[ - str | None, Field(None, description="The `branch_id` of the parent branch\n") - ] - parent_lsn: Annotated[ - str | None, - Field( - None, - description="The Log Sequence Number (LSN) on the parent branch from which this branch was created\n", - ), - ] - parent_timestamp: Annotated[ - AwareDatetime | None, - Field( - None, - description="The point in time on the parent branch from which this branch was created\n", - ), - ] - name: Annotated[str, Field(description="The branch name\n")] - current_state: BranchState - pending_state: BranchState | None = None - logical_size: Annotated[ - int | None, - Field(None, description="The logical size of the branch, in bytes\n"), - ] - creation_source: Annotated[str, Field(description="The branch creation source\n")] - primary: Annotated[ - bool, Field(description="Whether the branch is the project's primary branch\n") - ] - cpu_used_sec: Annotated[ - int, - Field( - description="CPU seconds used by all the endpoints of the branch, including deleted ones.\nThis value is reset at the beginning of each billing period.\nExamples:\n1. A branch that uses 1 CPU for 1 second is equal to `cpu_used_sec=1`.\n2. A branch that uses 2 CPUs simultaneously for 1 second is equal to `cpu_used_sec=2`.\n" - ), - ] - compute_time_seconds: int - active_time_seconds: int - written_data_bytes: int - data_transfer_bytes: int - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the branch was created\n"), - ] - updated_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the branch was last updated\n"), - ] - last_reset_at: Annotated[ - AwareDatetime | None, - Field( - None, description="A timestamp indicating when the branch was last reset\n" - ), - ] - - -class BranchCreateRequestEndpointOptions(BaseModel): - model_config = ConfigDict( - extra="allow", populate_by_name=True, use_enum_values=True - ) - type: EndpointType - autoscaling_limit_min_cu: Annotated[ - float | None, - Field( - None, - description="The minimum number of Compute Units. The minimum value is `0.25`.\n See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\n for more information.\n", - ge=0.25, - ), - ] - autoscaling_limit_max_cu: Annotated[ - float | None, - Field( - None, - description="The maximum number of Compute Units.\n See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\n for more information.\n", - ge=0.25, - ), - ] - provisioner: Provisioner | None = None - suspend_timeout_seconds: Annotated[ - int | None, - Field( - None, - description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", - ge=-1, - le=604800, - ), - ] - - -class BranchCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - endpoints: list[BranchCreateRequestEndpointOptions] | None = None - branch: Branch2 | None = None - - -class BranchResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - branch: Branch1 - - -class BranchesResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - branches: list[Branch1] - - -class StatementResult(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - data: StatementData | None = None - error: str | None = None - explain_data: list[ExplainData] | None = None - query: str - - -class BillingAccount(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - payment_source: PaymentSource - subscription_type: BillingSubscriptionType - quota_reset_at_last: Annotated[ - AwareDatetime, - Field( - description="The last time the quota was reset. Defaults to the date-time the account is created.\n" - ), - ] - email: Annotated[ - str, - Field( - description="Billing email, to receive emails related to invoices and subscriptions.\n" - ), - ] - address_city: Annotated[str, Field(description="Billing address city.\n")] - address_country: Annotated[str, Field(description="Billing address country.\n")] - address_line1: Annotated[str, Field(description="Billing address line 1.\n")] - address_line2: Annotated[str, Field(description="Billing address line 2.\n")] - address_postal_code: Annotated[ - str, Field(description="Billing address postal code.\n") - ] - address_state: Annotated[ - str, Field(description="Billing address state or region.\n") - ] - orb_portal_url: Annotated[ - str | None, Field(None, description="Orb user portal url\n") - ] - - -class BillingAccountResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - billing_account: BillingAccount - - -class CurrentUserInfoResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - active_seconds_limit: Annotated[ - int, - Field( - description="Control plane observes active endpoints of a user this amount of wall-clock time.\n" - ), - ] - billing_account: BillingAccount - auth_accounts: list[CurrentUserAuthAccount] - email: str - id: str - image: str - login: str - name: str - last_name: str - projects_limit: int - branches_limit: int - max_autoscaling_limit: Annotated[float, Field(ge=0.25)] - compute_seconds_limit: int | None = None - plan: str - - -class EndpointSettingsData(BaseModel): - """ - A collection of settings for a compute endpoint - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - pg_settings: dict[str, str] | None = None - pgbouncer_settings: dict[str, str] | None = None - - -class DefaultEndpointSettings(BaseModel): - """ - A collection of settings for a Neon endpoint - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - pg_settings: dict[str, str] | None = None - pgbouncer_settings: dict[str, str] | None = None - autoscaling_limit_min_cu: Annotated[ - float | None, - Field( - None, - description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - autoscaling_limit_max_cu: Annotated[ - float | None, - Field( - None, - description="The maximum number of Compute Units. See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - suspend_timeout_seconds: Annotated[ - int | None, - Field( - None, - description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", - ge=-1, - le=604800, - ), - ] - - -class GeneralError(BaseModel): - """ - General Error - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - code: str - message: Annotated[str, Field(description="Error message")] - - -class BranchOperations(BranchResponse, OperationsResponse): - pass - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - - -class DatabaseOperations(DatabaseResponse, OperationsResponse): - pass - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - - -class RoleOperations(RoleResponse, OperationsResponse): - pass - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - - -class ProjectListItem(BaseModel): - """ - Essential data about the project. Full data is available at the getProject endpoint. - - """ - - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - id: Annotated[str, Field(description="The project ID\n")] - platform_id: Annotated[ - str, - Field( - description="The cloud platform identifier. Currently, only AWS is supported, for which the identifier is `aws`.\n" - ), - ] - region_id: Annotated[str, Field(description="The region identifier\n")] - name: Annotated[str, Field(description="The project name\n")] - provisioner: Provisioner - default_endpoint_settings: DefaultEndpointSettings | None = None - settings: ProjectSettingsData | None = None - pg_version: Annotated[ - int, - Field( - description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", - ge=14, - le=16, - ), - ] - proxy_host: Annotated[ - str, - Field( - description="The proxy host for the project. This value combines the `region_id`, the `platform_id`, and the Neon domain (`neon.tech`).\n" - ), - ] - branch_logical_size_limit: Annotated[ - int, - Field( - description="The logical size limit for a branch. The value is in MiB.\n" - ), - ] - branch_logical_size_limit_bytes: Annotated[ - int, - Field(description="The logical size limit for a branch. The value is in B.\n"), - ] - store_passwords: Annotated[ - bool, - Field( - description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n" - ), - ] - active_time: Annotated[ - int, - Field( - description="Control plane observed endpoints of this project being active this amount of wall-clock time.\n", - ge=0, - ), - ] - cpu_used_sec: Annotated[ - int, - Field( - description="DEPRECATED. Use data from the getProject endpoint instead.\n" - ), - ] - maintenance_starts_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="A timestamp indicating when project maintenance begins. If set, the project is placed into maintenance mode at this time.\n", - ), - ] - creation_source: Annotated[str, Field(description="The project creation source\n")] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the project was created\n"), - ] - updated_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the project was last updated\n"), - ] - synthetic_storage_size: Annotated[ - int | None, - Field( - None, - description="The current space occupied by the project in storage, in bytes. Synthetic storage size combines the logical data size and Write-Ahead Log (WAL) size for all branches in a project.\n", - ), - ] - quota_reset_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="DEPRECATED. Use `consumption_period_end` from the getProject endpoint instead.\nA timestamp indicating when the project quota resets\n", - ), - ] - owner_id: str - compute_last_active_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The most recent time when any endpoint of this project was active.\n\nOmitted when observed no actitivy for endpoints of this project.\n", - ), - ] - - -class Project(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - data_storage_bytes_hour: Annotated[ - int, - Field( - description="Bytes-Hour. Project consumed that much storage hourly during the billing period. The value has some lag.\nThe value is reset at the beginning of each billing period.\n", - ge=0, - ), - ] - data_transfer_bytes: Annotated[ - int, - Field( - description="Bytes. Egress traffic from the Neon cloud to the client for given project over the billing period.\nIncludes deleted endpoints. The value has some lag. The value is reset at the beginning of each billing period.\n", - ge=0, - ), - ] - written_data_bytes: Annotated[ - int, - Field( - description="Bytes. Amount of WAL that travelled through storage for given project across all branches.\nThe value has some lag. The value is reset at the beginning of each billing period.\n", - ge=0, - ), - ] - compute_time_seconds: Annotated[ - int, - Field( - description="Seconds. The number of CPU seconds used by the project's compute endpoints, including compute endpoints that have been deleted.\nThe value has some lag. 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", - ge=0, - ), - ] - active_time_seconds: Annotated[ - int, - Field( - description="Seconds. Control plane observed endpoints of this project being active this amount of wall-clock time.\nThe value has some lag.\nThe value is reset at the beginning of each billing period.\n", - ge=0, - ), - ] - cpu_used_sec: Annotated[ - int, Field(description="DEPRECATED, use compute_time instead.\n") - ] - id: Annotated[str, Field(description="The project ID\n")] - platform_id: Annotated[ - str, - Field( - description="The cloud platform identifier. Currently, only AWS is supported, for which the identifier is `aws`.\n" - ), - ] - region_id: Annotated[str, Field(description="The region identifier\n")] - name: Annotated[str, Field(description="The project name\n")] - provisioner: Provisioner - default_endpoint_settings: DefaultEndpointSettings | None = None - settings: ProjectSettingsData | None = None - pg_version: Annotated[ - int, - Field( - description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", - ge=14, - le=16, - ), - ] - proxy_host: Annotated[ - str, - Field( - description="The proxy host for the project. This value combines the `region_id`, the `platform_id`, and the Neon domain (`neon.tech`).\n" - ), - ] - branch_logical_size_limit: Annotated[ - int, - Field( - description="The logical size limit for a branch. The value is in MiB.\n" - ), - ] - branch_logical_size_limit_bytes: Annotated[ - int, - Field(description="The logical size limit for a branch. The value is in B.\n"), - ] - store_passwords: Annotated[ - bool, - Field( - description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n" - ), - ] - maintenance_starts_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="A timestamp indicating when project maintenance begins. If set, the project is placed into maintenance mode at this time.\n", - ), - ] - creation_source: Annotated[str, Field(description="The project creation source\n")] - history_retention_seconds: Annotated[ - int, - Field( - description="The number of seconds to retain point-in-time restore (PITR) backup history for this project.\n" - ), - ] - created_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the project was created\n"), - ] - updated_at: Annotated[ - AwareDatetime, - Field(description="A timestamp indicating when the project was last updated\n"), - ] - synthetic_storage_size: Annotated[ - int | None, - Field( - None, - description="The current space occupied by the project in storage, in bytes. Synthetic storage size combines the logical data size and Write-Ahead Log (WAL) size for all branches in a project.\n", - ), - ] - consumption_period_start: Annotated[ - AwareDatetime, - Field( - description="A date-time indicating when Neon Cloud started measuring consumption for current consumption period.\n" - ), - ] - consumption_period_end: Annotated[ - AwareDatetime, - Field( - description="A date-time indicating when Neon Cloud plans to stop measuring consumption for current consumption period.\n" - ), - ] - quota_reset_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="DEPRECATED. Use `consumption_period_end` from the getProject endpoint instead.\nA timestamp indicating when the project quota resets.\n", - ), - ] - owner_id: str - owner: ProjectOwnerData | None = None - compute_last_active_at: Annotated[ - AwareDatetime | None, - Field( - None, - description="The most recent time when any endpoint of this project was active.\n\nOmitted when observed no actitivy for endpoints of this project.\n", - ), - ] - - -class Project1(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - settings: ProjectSettingsData | None = None - name: Annotated[str | None, Field(None, description="The project name")] - branch: Branch | None = None - autoscaling_limit_min_cu: Annotated[ - float | None, - Field( - None, - description="DEPRECATED, use default_endpoint_settings.autoscaling_limit_min_cu instead.\n\nThe minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - autoscaling_limit_max_cu: Annotated[ - float | None, - Field( - None, - description="DEPRECATED, use default_endpoint_settings.autoscaling_limit_max_cu instead.\n\nThe maximum number of Compute Units. See [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - provisioner: Provisioner | None = None - region_id: Annotated[ - str | None, - Field( - None, - description="The region identifier. Refer to our [Regions](https://neon.tech/docs/introduction/regions) documentation for supported regions. Values are specified in this format: `aws-us-east-1`\n", - ), - ] - default_endpoint_settings: DefaultEndpointSettings | None = None - pg_version: Annotated[ - int | None, - Field( - None, - description="The major PostgreSQL version number. Currently supported versions are `14`, `15` and `16`.", - ge=14, - le=16, - ), - ] - store_passwords: Annotated[ - bool | None, - Field( - None, - description="Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.\n", - ), - ] - history_retention_seconds: Annotated[ - int | None, - Field( - None, - 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", - ge=0, - le=2592000, - ), - ] - - -class ProjectCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - project: Project1 - - -class Project2(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - settings: ProjectSettingsData | None = None - name: Annotated[str | None, Field(None, description="The project name")] - default_endpoint_settings: DefaultEndpointSettings | None = None - history_retention_seconds: Annotated[ - int | None, - Field( - None, - 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", - ge=0, - le=2592000, - ), - ] - - -class ProjectUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - project: Project2 - - -class ProjectResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - project: Project - - -class ProjectsResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - projects: list[ProjectListItem] - - -class Endpoint(BaseModel): - model_config = ConfigDict( - extra="allow", populate_by_name=True, use_enum_values=True - ) - host: Annotated[ - str, - Field( - description="The hostname of the compute endpoint. This is the hostname specified when connecting to a Neon database.\n" - ), - ] - id: Annotated[ - str, - Field( - description="The compute endpoint ID. Compute endpoint IDs have an `ep-` prefix. For example: `ep-little-smoke-851426`\n" - ), - ] - project_id: Annotated[ - str, - Field( - description="The ID of the project to which the compute endpoint belongs\n" - ), - ] - branch_id: Annotated[ - str, - Field( - description="The ID of the branch that the compute endpoint is associated with\n" - ), - ] - autoscaling_limit_min_cu: Annotated[ - float, Field(description="The minimum number of Compute Units\n", ge=0.25) - ] - autoscaling_limit_max_cu: Annotated[ - float, Field(description="The maximum number of Compute Units\n", ge=0.25) - ] - region_id: Annotated[str, Field(description="The region identifier\n")] - type: EndpointType - current_state: EndpointState - pending_state: EndpointState | None = None - settings: EndpointSettingsData - pooler_enabled: Annotated[ - bool, - Field( - description="Whether connection pooling is enabled for the compute endpoint\n" - ), - ] - pooler_mode: EndpointPoolerMode - disabled: Annotated[ - bool, - Field( - description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n" - ), - ] - passwordless_access: Annotated[ - bool, - Field( - description="Whether to permit passwordless access to the compute endpoint\n" - ), - ] - last_active: Annotated[ - AwareDatetime | None, - Field( - None, - description="A timestamp indicating when the compute endpoint was last active\n", - ), - ] - creation_source: Annotated[ - str, Field(description="The compute endpoint creation source\n") - ] - created_at: Annotated[ - AwareDatetime, - Field( - description="A timestamp indicating when the compute endpoint was created\n" - ), - ] - updated_at: Annotated[ - AwareDatetime, - Field( - description="A timestamp indicating when the compute endpoint was last updated\n" - ), - ] - proxy_host: Annotated[ - str, Field(description='DEPRECATED. Use the "host" property instead.\n') - ] - suspend_timeout_seconds: Annotated[ - int, - Field( - description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", - ge=-1, - le=604800, - ), - ] - provisioner: Provisioner - - -class Endpoint1(BaseModel): - model_config = ConfigDict( - extra="allow", populate_by_name=True, use_enum_values=True - ) - branch_id: Annotated[ - str, - Field( - description="The ID of the branch the compute endpoint will be associated with\n" - ), - ] - region_id: Annotated[ - str | None, - Field( - None, - description="The region where the compute endpoint will be created. Only the project's `region_id` is permitted.\n", - ), - ] - type: EndpointType - settings: EndpointSettingsData | None = None - autoscaling_limit_min_cu: Annotated[ - float | None, - Field( - None, - description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - autoscaling_limit_max_cu: Annotated[ - float | None, - Field( - None, - description="The maximum number of Compute Units.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - provisioner: Provisioner | None = None - pooler_enabled: Annotated[ - bool | None, - Field( - None, - description="Whether to enable connection pooling for the compute endpoint\n", - ), - ] - pooler_mode: EndpointPoolerMode | None = None - disabled: Annotated[ - bool | None, - Field( - None, - description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n", - ), - ] - passwordless_access: Annotated[ - bool | None, - Field( - None, - description="NOT YET IMPLEMENTED. Whether to permit passwordless access to the compute endpoint.\n", - ), - ] - suspend_timeout_seconds: Annotated[ - int | None, - Field( - None, - description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", - ge=-1, - le=604800, - ), - ] - - -class EndpointCreateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - endpoint: Endpoint1 - - -class Endpoint2(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - branch_id: Annotated[ - str | None, - Field( - None, - description="The destination branch ID. The destination branch must not have an exsiting read-write endpoint.\n", - ), - ] - autoscaling_limit_min_cu: Annotated[ - float | None, - Field( - None, - description="The minimum number of Compute Units. The minimum value is `0.25`.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - autoscaling_limit_max_cu: Annotated[ - float | None, - Field( - None, - description="The maximum number of Compute Units.\nSee [Compute size and Autoscaling configuration](https://neon.tech/docs/manage/endpoints#compute-size-and-autoscaling-configuration)\nfor more information.\n", - ge=0.25, - ), - ] - provisioner: Provisioner | None = None - settings: EndpointSettingsData | None = None - pooler_enabled: Annotated[ - bool | None, - Field( - None, - description="Whether to enable connection pooling for the compute endpoint\n", - ), - ] - pooler_mode: EndpointPoolerMode | None = None - disabled: Annotated[ - bool | None, - Field( - None, - description="Whether to restrict connections to the compute endpoint.\nEnabling this option schedules a suspend compute operation.\nA disabled compute endpoint cannot be enabled by a connection or\nconsole action. However, the compute endpoint is periodically\nenabled by check_availability operations.\n", - ), - ] - passwordless_access: Annotated[ - bool | None, - Field( - None, - description="NOT YET IMPLEMENTED. Whether to permit passwordless access to the compute endpoint.\n", - ), - ] - suspend_timeout_seconds: Annotated[ - int | None, - Field( - None, - description="Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Auto-suspend configuration](https://neon.tech/docs/manage/endpoints#auto-suspend-configuration).\n", - ge=-1, - le=604800, - ), - ] - - -class EndpointUpdateRequest(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - endpoint: Endpoint2 - - -class EndpointResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - endpoint: Endpoint - - -class EndpointsResponse(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - endpoints: list[Endpoint] - - -class EndpointOperations(EndpointResponse, OperationsResponse): - pass - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) diff --git a/neon_client/openapi_models_custom.py b/neon_client/openapi_models_custom.py deleted file mode 100644 index e69de29..0000000 diff --git a/neon_client/resources.py b/neon_client/resources.py index a574d8c..5cdd5a6 100644 --- a/neon_client/resources.py +++ b/neon_client/resources.py @@ -2,44 +2,17 @@ from typing import List from fastapi.encoders import jsonable_encoder from .http_client import Neon_API_V2 -from .openapi_models import ( - ApiKeyCreateRequest, - ApiKeyCreateResponse, - ApiKeyRevokeResponse, - ApiKeysListResponseItem, - CurrentUserInfoResponse, - Project, - ProjectResponse, - ProjectUpdateRequest, - ProjectsResponse, - DatabaseResponse, - DatabasesResponse, - DatabaseUpdateRequest, - Database, - Database1, - Database2, - DatabaseCreateRequest, - BranchesResponse, - BranchResponse, - OperationResponse, - OperationsResponse, - PaginationResponse, - Branch, - Branch2, - Branch3, - BranchCreateRequestEndpointOptions, - BranchCreateRequest, -) +from . import models from .utils import validate_obj_model -class PagedOperationsResponse(OperationsResponse, PaginationResponse): +class PagedOperationsResponse(models.OperationsResponse, models.PaginationResponse): """A response containing a list of operations and pagination information.""" pass -class PagedProjectsResponse(ProjectsResponse, PaginationResponse): +class PagedProjectsResponse(models.ProjectsResponse, models.PaginationResponse): """A response containing a list of projects and pagination information.""" pass @@ -63,7 +36,7 @@ class UserResource(Resource): return self.api.request( method="GET", path=self.api.url_join(self.base_path, "me"), - response_model=CurrentUserInfoResponse, + response_model=models.CurrentUserInfoResponse, ) @@ -78,7 +51,7 @@ class APIKeyResource(Resource): return self.api.request( method="GET", path=self.base_path, - response_model=ApiKeysListResponseItem, + response_model=models.ApiKeysListResponseItem, response_is_array=True, ) @@ -88,8 +61,8 @@ class APIKeyResource(Resource): return self.api.request( method="POST", path=self.base_path, - json=ApiKeyCreateRequest(key_name=key_name).model_dump(), - response_model=ApiKeyCreateResponse, + json=models.ApiKeyCreateRequest(key_name=key_name).model_dump(), + response_model=models.ApiKeyCreateResponse, ) def revoke(self, key_id: str): @@ -98,7 +71,7 @@ class APIKeyResource(Resource): return self.api.request( method="DELETE", path=self.api.url_join(self.base_path, str(key_id)), - response_model=ApiKeyRevokeResponse, + response_model=models.ApiKeyRevokeResponse, ) @@ -139,29 +112,29 @@ class ProjectResource(Resource): return self.api.request( method="GET", path=self.api.url_join(self.base_path, project_id), - response_model=ProjectResponse, + response_model=models.ProjectResponse, ) - # def create(self, name: str, **kwargs): - # """Create a new project.""" + def create(self, **kwargs): + """Create a new project.""" - # return self.api.request( - # method="POST", - # path=self.base_path, - # json={"project": {"name": name, **kwargs}}, - # response_model=ProjectResponse, - # ).model_dump() + return self.api.request( + method="POST", + path=self.base_path, + json={"project": kwargs}, + response_model=models.ProjectResponse, + ).model_dump() - def update(self, project: Project): + def update(self, project: models.Project): """Update a project.""" - payload = ProjectUpdateRequest(project=project.model_dump()) + payload = models.ProjectUpdateRequest(project=project.model_dump()) return self.api.request( method="PATCH", path=self.api.url_join(self.base_path, project.id), json={"project": payload.model_dump()}, - response_model=ProjectResponse, + response_model=models.ProjectResponse, ) def delete(self, project_id: str): @@ -170,7 +143,7 @@ class ProjectResource(Resource): return self.api.request( method="DELETE", path=self.api.url_join(self.base_path, project_id), - response_model=ProjectResponse, + response_model=models.ProjectResponse, ) @@ -180,16 +153,24 @@ class DatabaseResource(Resource): def _extract_database(self, obj): """Extract a database from the specified object.""" - assert isinstance(obj, (DatabaseCreateRequest, Database1, Database2, Database)) + assert isinstance( + obj, + ( + models.DatabaseCreateRequest, + models.Database1, + models.Database2, + models.Database, + ), + ) # Object mappings. - if isinstance(obj, DatabaseCreateRequest): + if isinstance(obj, models.DatabaseCreateRequest): obj = obj.database.model_dump() - if isinstance(obj, Database1): + if isinstance(obj, models.Database1): obj = obj.database.model_dump() - if isinstance(obj, Database2): + if isinstance(obj, models.Database2): obj = obj.database.model_dump() - if isinstance(obj, Database): + if isinstance(obj, models.Database): obj = obj.model_dump() return obj @@ -233,7 +214,10 @@ class DatabaseResource(Resource): self, project_id: str, branch_id: str, - db: DatabaseCreateRequest | Database1 | Database2 | Database, + db: models.DatabaseCreateRequest + | models.Database1 + | models.Database2 + | models.Database, ): """Create a new database.""" @@ -253,7 +237,7 @@ class DatabaseResource(Resource): project_id: str, branch_id: str, database_id: str, - db: DatabaseUpdateRequest | Database2, + db: models.DatabaseUpdateRequest | models.Database2, ): """Update a database.""" @@ -264,8 +248,8 @@ class DatabaseResource(Resource): path=self.api.url_join( "projects", project_id, "branches", branch_id, "databases", database_id ), - json=DatabaseUpdateRequest(database=db).model_dump(), - response_model=DatabaseResponse, + json=models.DatabaseUpdateRequest(database=db).model_dump(), + response_model=models.DatabaseResponse, ) @@ -280,7 +264,7 @@ class BranchResource(Resource): return self.api.request( method="GET", path=self.api.url_join("projects", project_id, "branches"), - response_model=BranchesResponse, + response_model=models.BranchesResponse, ) def get(self, project_id: str, branch_id: str): @@ -289,17 +273,17 @@ class BranchResource(Resource): return self.api.request( method="GET", path=self.api.url_join("projects", project_id, "branches", branch_id), - response_model=BranchResponse, + response_model=models.BranchResponse, ) - def create(self, project_id: str, request: BranchCreateRequest): + def create(self, project_id: str, request: models.BranchCreateRequest): """Create a new branch.""" return self.api.request( method="POST", path=self.api.url_join("projects", project_id, "branches"), json=request.model_dump(), - response_model=BranchResponse, + response_model=models.BranchResponse, ) @@ -335,7 +319,7 @@ class OperationResource(Resource): return self.api.request( method="GET", path=self.api.url_join("projects", project_id, "operations", operation_id), - response_model=OperationResponse, + response_model=models.OperationResponse, ) diff --git a/neon_client/v2_client.py b/neon_client/v2_client.py deleted file mode 100644 index d9644f0..0000000 --- a/neon_client/v2_client.py +++ /dev/null @@ -1,90 +0,0 @@ -from .http_client import Neon_API_V2 -from .resources import ResourceCollection - -from . import openapi_models - - -class BaseNeonItem: - def __repr__(self): - return str(self) - - -class NeonUser(BaseNeonItem, openapi_models.CurrentUserAuthAccount): - @classmethod - def from_get_response(cls, r): - """Create a NeonUser from an API response.""" - - # TODO: is this the right way to do this? - me = r.auth_accounts[0] - - return cls.model_validate(me.model_dump()) - - def __str__(self): - return f"" - - -class CollectionView: - def __init__(self, collection, key_ids=None): - if not key_ids: - key_ids = [] - - self._key_ids = key_ids - self._collection = collection - - def __iter__(self): - return iter(self._collection) - - def __getitem__(self, key): - for k in key_ids: - for item in self._collection: - if getattr(item, k) == key: - return item - - return self._collection[key] - - def __len__(self): - return len(self._collection) - - def __repr__(self): - return repr(self._collection) - - -class NeonAPIKey(BaseNeonItem, openapi_models.ApiKeysListResponseItem): - @classmethod - def from_list_response(cls, r, *, neon): - """Create a list of APIKeys from an API response.""" - - def gen(): - for key in r: - k = cls.model_validate(key.model_dump()) - k.neon = neon - - yield k - - return [g for g in gen()] - - def __str__(self): - return f"" - - def revoke(self, *, neon): - """Revoke this API key.""" - - return bool(neon.resources.api_keys.revoke(self.id)) - - -class NeonClient: - def __init__(self, api_key: str, **kwargs): - self.api = Neon_API_V2(api_key, **kwargs) - self.resources = ResourceCollection(self.api) - - @property - def me(self): - user = self.resources.users.get_current_user_info() - return NeonUser.from_get_response(user) - - @property - def api_keys(self): - keys = self.resources.api_keys.get_list() - return CollectionView( - NeonAPIKey.from_list_response(keys, neon=self), key_ids=["id"] - )