v10.2.0: Support new deleted_by and forgotten_at fields for servers
This commit is contained in:
parent
7c6f57068d
commit
c5c4d9797d
|
@ -8,12 +8,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## Deprecated features that will be removed in the next major version.
|
## Deprecated features that will be removed in the next major version.
|
||||||
|
|
||||||
- `burn_rate` from `TokenInfo` is deprecated. Use `burn_rate_cents` or `burn_rate_usd` instead.
|
- `burn_rate` from `TokenInfo` is deprecated. Use `burn_rate_cents` or `burn_rate_usd` instead.
|
||||||
|
- `--no-local` will become the default for `sporestack server list`.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
- Nothing yet.
|
- Nothing yet.
|
||||||
|
|
||||||
## [10.1.2]
|
## [10.2.0 - 2023-05-03]
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Updated client to support new `forgotten_at` field and `deleted_by`.
|
||||||
|
|
||||||
|
## [10.1.2 - 2023-04-14]
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
__all__ = ["api", "api_client", "exceptions"]
|
__all__ = ["api", "api_client", "exceptions"]
|
||||||
|
|
||||||
__version__ = "10.1.2"
|
__version__ = "10.2.0"
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
"""
|
"""SporeStack API request/response models"""
|
||||||
|
|
||||||
SporeStack API request/response models
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -21,7 +17,7 @@ class TokenAdd:
|
||||||
class Request(BaseModel):
|
class Request(BaseModel):
|
||||||
currency: str
|
currency: str
|
||||||
dollars: int
|
dollars: int
|
||||||
affiliate_token: Optional[str] = None
|
affiliate_token: Union[str, None] = None
|
||||||
|
|
||||||
class Response(BaseModel):
|
class Response(BaseModel):
|
||||||
token: str
|
token: str
|
||||||
|
@ -88,6 +84,15 @@ class ServerTopup:
|
||||||
token: Union[str, None] = None
|
token: Union[str, None] = None
|
||||||
|
|
||||||
|
|
||||||
|
class ServerDeletedBy(str, Enum):
|
||||||
|
EXPIRATION = "expiration"
|
||||||
|
"""The server was deleted automatically for being expired."""
|
||||||
|
MANUAL = "manual"
|
||||||
|
"""The server was deleted before its expiration via the API."""
|
||||||
|
SPORESTACK = "sporestack"
|
||||||
|
"""The server was deleted by SporeStack, likely due to an AUP violation."""
|
||||||
|
|
||||||
|
|
||||||
class ServerInfo:
|
class ServerInfo:
|
||||||
url = "/server/{machine_id}/info"
|
url = "/server/{machine_id}/info"
|
||||||
method = "GET"
|
method = "GET"
|
||||||
|
@ -104,6 +109,8 @@ class ServerInfo:
|
||||||
flavor: Flavor
|
flavor: Flavor
|
||||||
deleted: bool
|
deleted: bool
|
||||||
deleted_at: int
|
deleted_at: int
|
||||||
|
deleted_by: Union[ServerDeletedBy, None]
|
||||||
|
forgotten_at: Union[datetime, None]
|
||||||
operating_system: str
|
operating_system: str
|
||||||
hostname: str
|
hostname: str
|
||||||
autorenew: bool
|
autorenew: bool
|
||||||
|
@ -120,13 +127,8 @@ class ServerStop:
|
||||||
|
|
||||||
|
|
||||||
class ServerDelete:
|
class ServerDelete:
|
||||||
url = "/server/{machine_id}/delete"
|
url = "/server/{machine_id}"
|
||||||
method = "POST"
|
method = "DELETE"
|
||||||
|
|
||||||
|
|
||||||
class ServerDestroy:
|
|
||||||
url = "/server/{machine_id}/destroy"
|
|
||||||
method = "POST"
|
|
||||||
|
|
||||||
|
|
||||||
class ServerForget:
|
class ServerForget:
|
||||||
|
|
|
@ -185,13 +185,11 @@ class APIClient:
|
||||||
def server_delete(self, machine_id: str) -> None:
|
def server_delete(self, machine_id: str) -> None:
|
||||||
"""Delete a server."""
|
"""Delete a server."""
|
||||||
url = self.api_endpoint + api.ServerDelete.url.format(machine_id=machine_id)
|
url = self.api_endpoint + api.ServerDelete.url.format(machine_id=machine_id)
|
||||||
response = self._httpx_client.post(url)
|
response = self._httpx_client.delete(url)
|
||||||
_handle_response(response)
|
_handle_response(response)
|
||||||
|
|
||||||
def server_forget(self, machine_id: str) -> None:
|
def server_forget(self, machine_id: str) -> None:
|
||||||
"""
|
"""Forget about a deleted server to hide it from view."""
|
||||||
Forget about a destroyed/deleted server.
|
|
||||||
"""
|
|
||||||
url = self.api_endpoint + api.ServerForget.url.format(machine_id=machine_id)
|
url = self.api_endpoint + api.ServerForget.url.format(machine_id=machine_id)
|
||||||
response = self._httpx_client.post(url)
|
response = self._httpx_client.post(url)
|
||||||
_handle_response(response)
|
_handle_response(response)
|
||||||
|
|
|
@ -279,6 +279,10 @@ def pretty_machine_info(info: Dict[str, Any]) -> str:
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
def epoch_to_human(epoch: int) -> str:
|
||||||
|
return time.strftime("%Y-%m-%d %H:%M:%S %z", time.localtime(epoch))
|
||||||
|
|
||||||
|
|
||||||
def print_machine_info(info: "api.ServerInfo.Response") -> None:
|
def print_machine_info(info: "api.ServerInfo.Response") -> None:
|
||||||
if info.hostname != "":
|
if info.hostname != "":
|
||||||
typer.echo(f"Hostname: {info.hostname}")
|
typer.echo(f"Hostname: {info.hostname}")
|
||||||
|
@ -296,13 +300,16 @@ def print_machine_info(info: "api.ServerInfo.Response") -> None:
|
||||||
typer.echo("IPv4: (Not yet assigned)")
|
typer.echo("IPv4: (Not yet assigned)")
|
||||||
typer.echo(f"Region: {info.region}")
|
typer.echo(f"Region: {info.region}")
|
||||||
typer.echo(f"Flavor: {info.flavor.slug}")
|
typer.echo(f"Flavor: {info.flavor.slug}")
|
||||||
human_expiration = time.strftime(
|
typer.echo(f"Expiration: {epoch_to_human(info.expiration)}")
|
||||||
"%Y-%m-%d %H:%M:%S %z", time.localtime(info.expiration)
|
|
||||||
)
|
|
||||||
typer.echo(f"Expiration: {info.expiration} ({human_expiration})")
|
|
||||||
typer.echo(f"Token: {info.token}")
|
typer.echo(f"Token: {info.token}")
|
||||||
if info.deleted:
|
if info.deleted_at != 0 or info.deleted:
|
||||||
typer.echo("Server was deleted!")
|
typer.echo("Server was deleted!")
|
||||||
|
if info.deleted_at != 0:
|
||||||
|
typer.echo(f"Server deleted at: {epoch_to_human(info.deleted_at)}")
|
||||||
|
if info.deleted_by is not None:
|
||||||
|
typer.echo(f"Server deleted by: {info.deleted_by.value}")
|
||||||
|
if info.forgotten_at is not None:
|
||||||
|
typer.echo(f"Server forgotten at: {info.forgotten_at}")
|
||||||
else:
|
else:
|
||||||
typer.echo(f"Running: {info.running}")
|
typer.echo(f"Running: {info.running}")
|
||||||
time_to_live = info.expiration - int(time.time())
|
time_to_live = info.expiration - int(time.time())
|
||||||
|
@ -317,6 +324,9 @@ def server_list(
|
||||||
local: bool = typer.Option(
|
local: bool = typer.Option(
|
||||||
True, help="List older servers not associated to token."
|
True, help="List older servers not associated to token."
|
||||||
),
|
),
|
||||||
|
show_forgotten: bool = typer.Option(
|
||||||
|
False, help="Show deleted and forgotten servers."
|
||||||
|
),
|
||||||
) -> None:
|
) -> None:
|
||||||
"""List all locally known servers and all servers under the given token."""
|
"""List all locally known servers and all servers under the given token."""
|
||||||
from .api_client import APIClient
|
from .api_client import APIClient
|
||||||
|
@ -339,6 +349,9 @@ def server_list(
|
||||||
printed_machine_ids = []
|
printed_machine_ids = []
|
||||||
|
|
||||||
for info in server_infos:
|
for info in server_infos:
|
||||||
|
if not show_forgotten and info.forgotten_at is not None:
|
||||||
|
continue
|
||||||
|
|
||||||
typer.echo()
|
typer.echo()
|
||||||
|
|
||||||
hostname = info.hostname
|
hostname = info.hostname
|
||||||
|
@ -408,6 +421,8 @@ def _get_machine_id(machine_id: str, hostname: str, token: str) -> str:
|
||||||
api_client = APIClient(api_endpoint=get_api_endpoint())
|
api_client = APIClient(api_endpoint=get_api_endpoint())
|
||||||
|
|
||||||
for server in api_client.servers_launched_from_token(token=_token).servers:
|
for server in api_client.servers_launched_from_token(token=_token).servers:
|
||||||
|
if server.forgotten_at is not None:
|
||||||
|
continue
|
||||||
if server.hostname == hostname:
|
if server.hostname == hostname:
|
||||||
return server.machine_id
|
return server.machine_id
|
||||||
|
|
||||||
|
|
|
@ -82,9 +82,11 @@ class Token:
|
||||||
"""Returns support messages for/from the token."""
|
"""Returns support messages for/from the token."""
|
||||||
self.api_client.token_send_message(token=self.token, message=message)
|
self.api_client.token_send_message(token=self.token, message=message)
|
||||||
|
|
||||||
def servers(self) -> List[Server]:
|
def servers(self, show_forgotten: bool = False) -> List[Server]:
|
||||||
server_classes: List[Server] = []
|
server_classes: List[Server] = []
|
||||||
for server in self.api_client.servers_launched_from_token(self.token).servers:
|
for server in self.api_client.servers_launched_from_token(self.token).servers:
|
||||||
|
if not show_forgotten and server.forgotten_at is not None:
|
||||||
|
continue
|
||||||
server_classes.append(
|
server_classes.append(
|
||||||
Server(
|
Server(
|
||||||
machine_id=server.machine_id,
|
machine_id=server.machine_id,
|
||||||
|
|
Loading…
Reference in New Issue