249 lines
7.1 KiB
Python
249 lines
7.1 KiB
Python
import logging
|
|
from pathlib import Path
|
|
from typing import Any, List, Union
|
|
|
|
import typer
|
|
from pydantic import BaseModel
|
|
from typing_extensions import Annotated
|
|
|
|
from fastapi_cloud_cli.utils.api import APIClient
|
|
from fastapi_cloud_cli.utils.apps import get_app_config
|
|
from fastapi_cloud_cli.utils.auth import is_logged_in
|
|
from fastapi_cloud_cli.utils.cli import get_rich_toolkit, handle_http_errors
|
|
from fastapi_cloud_cli.utils.env import validate_environment_variable_name
|
|
from fastapi_cloud_cli.utils.pydantic_compat import model_validate
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class EnvironmentVariable(BaseModel):
|
|
name: str
|
|
value: str
|
|
|
|
|
|
class EnvironmentVariableResponse(BaseModel):
|
|
data: List[EnvironmentVariable]
|
|
|
|
|
|
def _get_environment_variables(app_id: str) -> EnvironmentVariableResponse:
|
|
with APIClient() as client:
|
|
response = client.get(f"/apps/{app_id}/environment-variables/")
|
|
response.raise_for_status()
|
|
|
|
return model_validate(EnvironmentVariableResponse, response.json())
|
|
|
|
|
|
def _delete_environment_variable(app_id: str, name: str) -> bool:
|
|
with APIClient() as client:
|
|
response = client.delete(f"/apps/{app_id}/environment-variables/{name}")
|
|
|
|
if response.status_code == 404:
|
|
return False
|
|
|
|
response.raise_for_status()
|
|
|
|
return True
|
|
|
|
|
|
def _set_environment_variable(
|
|
app_id: str, name: str, value: str, is_secret: bool = False
|
|
) -> None:
|
|
with APIClient() as client:
|
|
response = client.post(
|
|
f"/apps/{app_id}/environment-variables/",
|
|
json={"name": name, "value": value, "is_secret": is_secret},
|
|
)
|
|
response.raise_for_status()
|
|
|
|
|
|
env_app = typer.Typer()
|
|
|
|
|
|
@env_app.command()
|
|
def list(
|
|
path: Annotated[
|
|
Union[Path, None],
|
|
typer.Argument(
|
|
help="A path to the folder containing the app you want to deploy"
|
|
),
|
|
] = None,
|
|
) -> Any:
|
|
"""
|
|
List the environment variables for the app.
|
|
"""
|
|
|
|
with get_rich_toolkit(minimal=True) as toolkit:
|
|
if not is_logged_in():
|
|
toolkit.print(
|
|
"No credentials found. Use [blue]`fastapi login`[/] to login.",
|
|
tag="auth",
|
|
)
|
|
|
|
raise typer.Exit(1)
|
|
|
|
app_path = path or Path.cwd()
|
|
|
|
app_config = get_app_config(app_path)
|
|
|
|
if not app_config:
|
|
toolkit.print(
|
|
f"No app found in the folder [bold]{app_path}[/].",
|
|
)
|
|
raise typer.Exit(1)
|
|
|
|
with toolkit.progress(
|
|
"Fetching environment variables...", transient=True
|
|
) as progress:
|
|
with handle_http_errors(progress):
|
|
environment_variables = _get_environment_variables(app_config.app_id)
|
|
|
|
if not environment_variables.data:
|
|
toolkit.print("No environment variables found.")
|
|
return
|
|
|
|
toolkit.print("Environment variables:")
|
|
toolkit.print_line()
|
|
|
|
for env_var in environment_variables.data:
|
|
toolkit.print(f"[bold]{env_var.name}[/]")
|
|
|
|
|
|
@env_app.command()
|
|
def delete(
|
|
name: Union[str, None] = typer.Argument(
|
|
None,
|
|
help="The name of the environment variable to delete",
|
|
),
|
|
path: Annotated[
|
|
Union[Path, None],
|
|
typer.Argument(
|
|
help="A path to the folder containing the app you want to deploy"
|
|
),
|
|
] = None,
|
|
) -> Any:
|
|
"""
|
|
Delete an environment variable from the app.
|
|
"""
|
|
|
|
with get_rich_toolkit(minimal=True) as toolkit:
|
|
# TODO: maybe this logic can be extracted to a function
|
|
if not is_logged_in():
|
|
toolkit.print(
|
|
"No credentials found. Use [blue]`fastapi login`[/] to login.",
|
|
tag="auth",
|
|
)
|
|
|
|
raise typer.Exit(1)
|
|
|
|
path_to_deploy = path or Path.cwd()
|
|
|
|
app_config = get_app_config(path_to_deploy)
|
|
|
|
if not app_config:
|
|
toolkit.print(
|
|
f"No app found in the folder [bold]{path_to_deploy}[/].",
|
|
)
|
|
raise typer.Exit(1)
|
|
|
|
if not name:
|
|
with toolkit.progress(
|
|
"Fetching environment variables...", transient=True
|
|
) as progress:
|
|
with handle_http_errors(progress):
|
|
environment_variables = _get_environment_variables(
|
|
app_config.app_id
|
|
)
|
|
|
|
if not environment_variables.data:
|
|
toolkit.print("No environment variables found.")
|
|
return
|
|
|
|
name = toolkit.ask(
|
|
"Select the environment variable to delete:",
|
|
options=[
|
|
{"name": env_var.name, "value": env_var.name}
|
|
for env_var in environment_variables.data
|
|
],
|
|
)
|
|
|
|
assert name
|
|
else:
|
|
if not validate_environment_variable_name(name):
|
|
toolkit.print(
|
|
f"The environment variable name [bold]{name}[/] is invalid."
|
|
)
|
|
raise typer.Exit(1)
|
|
|
|
toolkit.print_line()
|
|
|
|
with toolkit.progress(
|
|
"Deleting environment variable", transient=True
|
|
) as progress:
|
|
with handle_http_errors(progress):
|
|
deleted = _delete_environment_variable(app_config.app_id, name)
|
|
|
|
if not deleted:
|
|
toolkit.print("Environment variable not found.")
|
|
raise typer.Exit(1)
|
|
|
|
toolkit.print(f"Environment variable [bold]{name}[/] deleted.")
|
|
|
|
|
|
@env_app.command()
|
|
def set(
|
|
name: Union[str, None] = typer.Argument(
|
|
None,
|
|
help="The name of the environment variable to set",
|
|
),
|
|
value: Union[str, None] = typer.Argument(
|
|
None,
|
|
help="The value of the environment variable to set",
|
|
),
|
|
path: Annotated[
|
|
Union[Path, None],
|
|
typer.Argument(
|
|
help="A path to the folder containing the app you want to deploy"
|
|
),
|
|
] = None,
|
|
) -> Any:
|
|
"""
|
|
Set an environment variable for the app.
|
|
"""
|
|
|
|
with get_rich_toolkit(minimal=True) as toolkit:
|
|
if not is_logged_in():
|
|
toolkit.print(
|
|
"No credentials found. Use [blue]`fastapi login`[/] to login.",
|
|
tag="auth",
|
|
)
|
|
|
|
raise typer.Exit(1)
|
|
|
|
path_to_deploy = path or Path.cwd()
|
|
|
|
app_config = get_app_config(path_to_deploy)
|
|
|
|
if not app_config:
|
|
toolkit.print(
|
|
f"No app found in the folder [bold]{path_to_deploy}[/].",
|
|
)
|
|
raise typer.Exit(1)
|
|
|
|
if not name:
|
|
name = toolkit.input("Enter the name of the environment variable to set:")
|
|
|
|
if not value:
|
|
value = toolkit.input(
|
|
"Enter the value of the environment variable to set:", password=True
|
|
)
|
|
|
|
with toolkit.progress(
|
|
"Setting environment variable", transient=True
|
|
) as progress:
|
|
assert name is not None
|
|
assert value is not None
|
|
|
|
with handle_http_errors(progress):
|
|
_set_environment_variable(app_config.app_id, name, value)
|
|
|
|
toolkit.print(f"Environment variable [bold]{name}[/] set.")
|