10.7.0: Add suspended server support
parent
190b94746c
commit
ac7eb3a186
|
@ -15,6 +15,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Nothing yet.
|
||||
|
||||
## [10.7.0 - 2023-10-31]
|
||||
|
||||
## Added
|
||||
|
||||
- Added `suspended_at` to server info response object.
|
||||
- Added `autorenew_servers` to token info response object.
|
||||
- Added `suspended_servers` to token info response object.
|
||||
|
||||
## [10.6.3 - 2023-09-18]
|
||||
|
||||
## Changed
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""SporeStack API library and CLI for launching servers with Monero or Bitcoin"""
|
||||
|
||||
__all__ = ["api", "api_client", "exceptions"]
|
||||
__all__ = ["api", "api_client", "client", "exceptions"]
|
||||
|
||||
__version__ = "10.6.3"
|
||||
__version__ = "10.7.0"
|
||||
|
|
|
@ -117,10 +117,11 @@ class ServerInfo:
|
|||
ipv6: str
|
||||
region: str
|
||||
flavor: Flavor
|
||||
deleted: bool
|
||||
deleted: Annotated[bool, Field(deprecated=True)]
|
||||
deleted_at: int
|
||||
deleted_by: Union[ServerDeletedBy, None]
|
||||
forgotten_at: Union[datetime, None]
|
||||
suspended_at: Union[datetime, None]
|
||||
operating_system: str
|
||||
hostname: str
|
||||
autorenew: bool
|
||||
|
|
|
@ -303,38 +303,49 @@ def epoch_to_human(epoch: int) -> str:
|
|||
|
||||
|
||||
def print_machine_info(info: "api.ServerInfo.Response") -> None:
|
||||
if info.hostname != "":
|
||||
typer.echo(f"Hostname: {info.hostname}")
|
||||
else:
|
||||
typer.echo("Hostname: (none) (No hostname set)")
|
||||
from rich.console import Console
|
||||
|
||||
typer.echo(f"Machine ID (keep this secret!): {info.machine_id}")
|
||||
console = Console(width=None if sys.stdout.isatty() else 10**9)
|
||||
|
||||
output = ""
|
||||
|
||||
if info.hostname != "":
|
||||
output += f"Hostname: {info.hostname}\n"
|
||||
else:
|
||||
output += "Hostname: (none) (No hostname set)\n"
|
||||
|
||||
output += f"Machine ID (keep this secret!): {info.machine_id}\n"
|
||||
if info.ipv6 != "":
|
||||
typer.echo(f"IPv6: {info.ipv6}")
|
||||
output += f"IPv6: {info.ipv6}\n"
|
||||
else:
|
||||
typer.echo("IPv6: (Not yet assigned)")
|
||||
output += "IPv6: (Not yet assigned)\n"
|
||||
if info.ipv4 != "":
|
||||
typer.echo(f"IPv4: {info.ipv4}")
|
||||
output += f"IPv4: {info.ipv4}\n"
|
||||
else:
|
||||
typer.echo("IPv4: (Not yet assigned)")
|
||||
typer.echo(f"Region: {info.region}")
|
||||
typer.echo(f"Flavor: {info.flavor.slug}")
|
||||
typer.echo(f"Expiration: {epoch_to_human(info.expiration)}")
|
||||
typer.echo(f"Token (keep this secret!): {info.token}")
|
||||
if info.deleted_at != 0 or info.deleted:
|
||||
typer.echo("Server was deleted!")
|
||||
if info.deleted_at != 0:
|
||||
typer.echo(f"Server deleted at: {epoch_to_human(info.deleted_at)}")
|
||||
output += "IPv4: (Not yet assigned)\n"
|
||||
output += f"Region: {info.region}\n"
|
||||
output += f"Flavor: {info.flavor.slug}\n"
|
||||
output += f"Token (keep this secret!): {info.token}\n"
|
||||
if info.deleted_at != 0:
|
||||
output += f"Server deleted at: {epoch_to_human(info.deleted_at)}\n"
|
||||
if info.deleted_by is not None:
|
||||
typer.echo(f"Server deleted by: {info.deleted_by.value}")
|
||||
output += f"Server deleted by: {info.deleted_by.value}\n"
|
||||
if info.forgotten_at is not None:
|
||||
typer.echo(f"Server forgotten at: {info.forgotten_at}")
|
||||
output += f"Server forgotten at: {info.forgotten_at}\n"
|
||||
else:
|
||||
typer.echo(f"Running: {info.running}")
|
||||
msg = f"Running: {info.running}\n"
|
||||
if info.suspended_at is not None:
|
||||
msg = (
|
||||
"Running: Server is powered off because it is [bold]suspended[/bold].\n"
|
||||
)
|
||||
output += msg
|
||||
time_to_live = info.expiration - int(time.time())
|
||||
hours = time_to_live // 3600
|
||||
typer.echo(f"Server will be deleted in {hours} hours.")
|
||||
typer.echo(f"Autorenew: {info.autorenew}")
|
||||
output += f"Server will be deleted in {hours} hours.\n"
|
||||
output += f"Expiration: {epoch_to_human(info.expiration)}\n"
|
||||
output += f"Autorenew: {info.autorenew}"
|
||||
|
||||
console.print(output)
|
||||
|
||||
|
||||
@server_cli.command(name="list")
|
||||
|
@ -414,6 +425,9 @@ def server_list(
|
|||
str(info.autorenew),
|
||||
)
|
||||
|
||||
if info.suspended_at != 0:
|
||||
typer.echo(f"Warning: {info.machine_id} is suspended!", err=True)
|
||||
|
||||
printed_machine_ids.append(info.machine_id)
|
||||
|
||||
console.print(table)
|
||||
|
@ -887,7 +901,9 @@ def token_info(token: Annotated[str, typer.Argument()] = DEFAULT_TOKEN) -> None:
|
|||
info = client.token.info()
|
||||
print(f"[bold]Token Information for {token} ({_token})[/bold]")
|
||||
print(f"Balance: [green]{info.balance_usd}")
|
||||
print(f"Total Servers: {info.servers}")
|
||||
print(f"Total Servers (not deleted): {info.servers}")
|
||||
print(f"Servers set to autorenew: {info.autorenew_servers}")
|
||||
print(f"Suspended servers: {info.suspended_servers}")
|
||||
print(
|
||||
f"Burn Rate: [red]{info.burn_rate_usd}[/red] "
|
||||
"(per day of servers set to autorenew)"
|
||||
|
|
|
@ -62,12 +62,13 @@ class OperatingSystem(BaseModel):
|
|||
class TokenInfo(BaseModel):
|
||||
balance_cents: int
|
||||
balance_usd: str
|
||||
burn_rate: int
|
||||
"""Deprecated."""
|
||||
burn_rate: Annotated[int, Field(deprecated=True)]
|
||||
burn_rate_cents: int
|
||||
burn_rate_usd: str
|
||||
days_remaining: int
|
||||
servers: int
|
||||
autorenew_servers: int
|
||||
suspended_servers: int
|
||||
|
||||
|
||||
class Region(BaseModel):
|
||||
|
|
|
@ -81,6 +81,8 @@ def test_token_info(respx_mock: respx.MockRouter) -> None:
|
|||
"balance_cents": 0,
|
||||
"balance_usd": "$0.00",
|
||||
"servers": 0,
|
||||
"autorenew_servers": 0,
|
||||
"suspended_servers": 0,
|
||||
"burn_rate": 0,
|
||||
"burn_rate_usd": "$0.00",
|
||||
"burn_rate_cents": 0,
|
||||
|
@ -133,6 +135,7 @@ def test_server_info(respx_mock: respx.MockRouter) -> None:
|
|||
"deleted_at": 0,
|
||||
"deleted_by": None,
|
||||
"forgotten_at": None,
|
||||
"suspended_at": None,
|
||||
"operating_system": "debian-11",
|
||||
}
|
||||
route_response = httpx.Response(200, json=response_json)
|
||||
|
|
Loading…
Reference in New Issue