|
|
|
@ -113,6 +113,7 @@ def launch(
|
|
|
|
|
token: str = DEFAULT_TOKEN,
|
|
|
|
|
region: Optional[str] = None,
|
|
|
|
|
quote: bool = typer.Option(True, help="Require manual price confirmation."),
|
|
|
|
|
autorenew: bool = typer.Option(False, help="BETA: Automatically renew server."),
|
|
|
|
|
) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Launch a server on SporeStack.
|
|
|
|
@ -151,12 +152,24 @@ def launch(
|
|
|
|
|
retry=True,
|
|
|
|
|
quote=True,
|
|
|
|
|
hostname=hostname,
|
|
|
|
|
autorenew=autorenew,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
msg = f"Is {response.payment.usd} for {days} day(s) of {flavor} okay?"
|
|
|
|
|
typer.echo(msg, err=True)
|
|
|
|
|
input("[Press ctrl+c to cancel, or enter to accept.]")
|
|
|
|
|
|
|
|
|
|
if autorenew:
|
|
|
|
|
typer.echo("Autorenew is a BETA feature!!!", err=True)
|
|
|
|
|
typer.echo(
|
|
|
|
|
"Server will be automatically renewed (from this token) to one week of expiration.", # noqa: E501
|
|
|
|
|
err=True,
|
|
|
|
|
)
|
|
|
|
|
typer.echo(
|
|
|
|
|
"If using this feature, watch your token balance and server expiration closely!", # noqa: E501
|
|
|
|
|
err=True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
tries = 360
|
|
|
|
|
while tries > 0:
|
|
|
|
|
response = api_client.launch(
|
|
|
|
@ -168,6 +181,7 @@ def launch(
|
|
|
|
|
region=region,
|
|
|
|
|
token=_token,
|
|
|
|
|
hostname=hostname,
|
|
|
|
|
autorenew=autorenew,
|
|
|
|
|
api_endpoint=get_api_endpoint(),
|
|
|
|
|
retry=True,
|
|
|
|
|
)
|
|
|
|
@ -183,8 +197,6 @@ def launch(
|
|
|
|
|
raise typer.Exit(code=1)
|
|
|
|
|
|
|
|
|
|
created_dict = response.dict()
|
|
|
|
|
created_dict["vm_hostname"] = hostname
|
|
|
|
|
save_machine_info(created_dict)
|
|
|
|
|
typer.echo(pretty_machine_info(created_dict), err=True)
|
|
|
|
|
typer.echo(json.dumps(created_dict, indent=4))
|
|
|
|
|
|
|
|
|
@ -213,7 +225,6 @@ def topup(
|
|
|
|
|
response = api_client.topup(
|
|
|
|
|
machine_id=machine_id,
|
|
|
|
|
days=days,
|
|
|
|
|
currency="settlement",
|
|
|
|
|
api_endpoint=get_api_endpoint(),
|
|
|
|
|
token=_token,
|
|
|
|
|
retry=True,
|
|
|
|
@ -226,16 +237,13 @@ def topup(
|
|
|
|
|
response = api_client.topup(
|
|
|
|
|
machine_id=machine_id,
|
|
|
|
|
days=days,
|
|
|
|
|
currency="settlement",
|
|
|
|
|
api_endpoint=get_api_endpoint(),
|
|
|
|
|
token=_token,
|
|
|
|
|
retry=True,
|
|
|
|
|
)
|
|
|
|
|
assert response.payment.paid is True
|
|
|
|
|
|
|
|
|
|
machine_info["expiration"] = response.expiration
|
|
|
|
|
save_machine_info(machine_info, overwrite=True)
|
|
|
|
|
typer.echo(machine_info["expiration"])
|
|
|
|
|
typer.echo(response.expiration)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def server_info_path() -> Path:
|
|
|
|
@ -268,18 +276,6 @@ def token_path() -> Path:
|
|
|
|
|
return token_dir
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_machine_info(machine_info: Dict[str, Any], overwrite: bool = False) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Save info to disk.
|
|
|
|
|
"""
|
|
|
|
|
directory = server_info_path()
|
|
|
|
|
hostname = machine_info["vm_hostname"]
|
|
|
|
|
json_file = directory / f"{hostname}.json"
|
|
|
|
|
if overwrite is False:
|
|
|
|
|
assert json_file.exists() is False, f"{json_file} already exists."
|
|
|
|
|
json_file.write_text(json.dumps(machine_info))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_machine_info(hostname: str) -> Dict[str, Any]:
|
|
|
|
|
"""
|
|
|
|
|
Get info from disk.
|
|
|
|
@ -435,7 +431,7 @@ def start(hostname: str) -> None:
|
|
|
|
|
@server_cli.command()
|
|
|
|
|
def stop(hostname: str) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Immediately kills the VM.
|
|
|
|
|
Immediately shuts down the VM.
|
|
|
|
|
"""
|
|
|
|
|
machine_info = get_machine_info(hostname)
|
|
|
|
|
machine_id = machine_info["machine_id"]
|
|
|
|
@ -443,17 +439,34 @@ def stop(hostname: str) -> None:
|
|
|
|
|
typer.echo(f"{hostname} stopped.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@server_cli.command()
|
|
|
|
|
def destroy(hostname: str) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Deletes/destroys the VM before expiration (no refunds/credits)
|
|
|
|
|
"""
|
|
|
|
|
_destroy(hostname)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@server_cli.command()
|
|
|
|
|
def delete(hostname: str) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Deletes the VM before expiration (no refunds/credits)
|
|
|
|
|
|
|
|
|
|
Deprecated: Use destroy instead.
|
|
|
|
|
"""
|
|
|
|
|
_destroy(hostname)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _destroy(hostname: str) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Deletes the VM before expiration (no refunds/credits)
|
|
|
|
|
"""
|
|
|
|
|
machine_info = get_machine_info(hostname)
|
|
|
|
|
machine_id = machine_info["machine_id"]
|
|
|
|
|
api_client.delete(machine_id=machine_id, api_endpoint=get_api_endpoint())
|
|
|
|
|
api_client.destroy(machine_id=machine_id, api_endpoint=get_api_endpoint())
|
|
|
|
|
# Also remove the .json file
|
|
|
|
|
server_info_path().joinpath(f"{hostname}.json").unlink()
|
|
|
|
|
typer.echo(f"{hostname} was deleted.")
|
|
|
|
|
server_info_path().joinpath(f"{hostname}.json").unlink(missing_ok=True)
|
|
|
|
|
typer.echo(f"{hostname} was destroyed.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@server_cli.command()
|
|
|
|
|