CLI improvements ()

This commit is contained in:
Martin Xu 2023-10-24 15:35:51 -07:00 committed by GitHub
parent 93d19d6dc3
commit f404205c3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 72 deletions

View File

@ -275,10 +275,10 @@ def export(
help="The directory to export the zip files to.",
show_default=False,
),
backend_exclude_sqlite_db_files: bool = typer.Option(
True,
upload_db_file: bool = typer.Option(
False,
help="Whether to exclude sqlite db files when exporting backend.",
show_default=False,
hidden=True,
),
loglevel: constants.LogLevel = typer.Option(
console._LOG_LEVEL, help="The log level to use."
@ -310,7 +310,7 @@ def export(
zip=zipping,
zip_dest_dir=zip_dest_dir,
deploy_url=config.deploy_url,
backend_exclude_sqlite_db_files=backend_exclude_sqlite_db_files,
upload_db_file=upload_db_file,
)
# Post a telemetry event.
@ -431,6 +431,7 @@ def deploy(
config.app_name,
"--app-name",
help="The name of the App to deploy under.",
hidden=True,
),
regions: List[str] = typer.Option(
list(),
@ -441,20 +442,29 @@ def deploy(
envs: List[str] = typer.Option(
list(),
"--env",
help="The environment variables to set: <key>=<value>. For multiple envs, repeat this option followed by the env name.",
help="The environment variables to set: <key>=<value>. For multiple envs, repeat this option, e.g. --env k1=v2 --env k2=v2.",
),
cpus: Optional[int] = typer.Option(
None, help="The number of CPUs to allocate.", hidden=True
),
cpus: Optional[int] = typer.Option(None, help="The number of CPUs to allocate."),
memory_mb: Optional[int] = typer.Option(
None, help="The amount of memory to allocate."
None, help="The amount of memory to allocate.", hidden=True
),
auto_start: Optional[bool] = typer.Option(
True, help="Whether to auto start the instance."
True,
help="Whether to auto start the instance.",
hidden=True,
),
auto_stop: Optional[bool] = typer.Option(
True, help="Whether to auto stop the instance."
True,
help="Whether to auto stop the instance.",
hidden=True,
),
frontend_hostname: Optional[str] = typer.Option(
None, "--frontend-hostname", help="The hostname of the frontend."
None,
"--frontend-hostname",
help="The hostname of the frontend.",
hidden=True,
),
interactive: Optional[bool] = typer.Option(
True,
@ -463,14 +473,17 @@ def deploy(
with_metrics: Optional[str] = typer.Option(
None,
help="Setting for metrics scraping for the deployment. Setup required in user code.",
hidden=True,
),
with_tracing: Optional[str] = typer.Option(
None,
help="Setting to export tracing for the deployment. Setup required in user code.",
hidden=True,
),
backend_exclude_sqlite_db_files: bool = typer.Option(
True,
help="Whether to exclude sqlite db files from the backend export.",
upload_db_file: bool = typer.Option(
False,
help="Whether to include local sqlite db files when uploading to hosting service.",
hidden=True,
),
loglevel: constants.LogLevel = typer.Option(
config.loglevel, help="The log level to use."
@ -558,16 +571,15 @@ def deploy(
zipping=True,
zip_dest_dir=tmp_dir,
loglevel=loglevel,
backend_exclude_sqlite_db_files=backend_exclude_sqlite_db_files,
upload_db_file=upload_db_file,
)
except ImportError as ie:
console.error(
f"Encountered ImportError, did you install all the dependencies? {ie}"
)
raise typer.Exit(1) from ie
finally:
if os.path.exists(tmp_dir):
shutil.rmtree(tmp_dir)
raise typer.Exit(1) from ie
frontend_file_name = constants.ComponentName.FRONTEND.zip()
backend_file_name = constants.ComponentName.BACKEND.zip()
@ -750,43 +762,6 @@ def get_deployment_logs(
raise typer.Exit(1) from ex
@deployments_cli.command(name="all-logs")
def get_deployment_all_logs(
key: str = typer.Argument(..., help="The name of the deployment."),
loglevel: constants.LogLevel = typer.Option(
config.loglevel, help="The log level to use."
),
):
"""Get the logs for a deployment."""
console.set_log_level(loglevel)
console.print("Note: there is a few seconds delay for logs to be available.")
try:
asyncio.run(hosting.get_logs(key, log_type=hosting.LogType.ALL_LOG))
except Exception as ex:
console.error(f"Unable to get deployment logs due to: {ex}")
raise typer.Exit(1) from ex
@deployments_cli.command(name="deploy-logs")
def get_deployment_deploy_logs(
key: str = typer.Argument(..., help="The name of the deployment."),
loglevel: constants.LogLevel = typer.Option(
config.loglevel, help="The log level to use."
),
):
"""Get the logs for a deployment."""
console.set_log_level(loglevel)
console.print("Note: there is a few seconds delay for logs to be available.")
try:
# TODO: we need to pass in the from time stamp
asyncio.run(hosting.get_logs(key, log_type=hosting.LogType.DEPLOY_LOG))
except Exception as ex:
console.error(f"Unable to get deployment logs due to: {ex}")
raise typer.Exit(1) from ex
@deployments_cli.command(name="regions")
def get_deployment_regions(
loglevel: constants.LogLevel = typer.Option(

View File

@ -60,7 +60,7 @@ def _zip(
target: str,
root_dir: str,
exclude_venv_dirs: bool,
exclude_sqlite_db_files: bool = True,
upload_db_file: bool = False,
dirs_to_exclude: set[str] | None = None,
files_to_exclude: set[str] | None = None,
) -> None:
@ -71,7 +71,7 @@ def _zip(
target: The target zip file.
root_dir: The root directory to zip.
exclude_venv_dirs: Whether to exclude venv directories.
exclude_sqlite_db_files: Whether to exclude sqlite db files.
upload_db_file: Whether to include local sqlite db files.
dirs_to_exclude: The directories to exclude.
files_to_exclude: The files to exclude.
@ -97,8 +97,7 @@ def _zip(
files[:] = [
f
for f in files
if not f.startswith(".")
and (not exclude_sqlite_db_files or not f.endswith(".db"))
if not f.startswith(".") and (upload_db_file or not f.endswith(".db"))
]
files_to_zip += [
os.path.join(root, file) for file in files if file not in files_to_exclude
@ -127,7 +126,7 @@ def export(
zip: bool = False,
zip_dest_dir: str = os.getcwd(),
deploy_url: str | None = None,
backend_exclude_sqlite_db_files: bool = True,
upload_db_file: bool = False,
):
"""Export the app for deployment.
@ -137,7 +136,7 @@ def export(
zip: Whether to zip the app.
zip_dest_dir: The destination directory for created zip files (if any)
deploy_url: The URL of the deployed app.
backend_exclude_sqlite_db_files: Whether to exclude sqlite db files from the backend zip.
upload_db_file: Whether to include local sqlite db files from the backend zip.
"""
# Remove the static folder.
path_ops.rm(constants.Dirs.WEB_STATIC)
@ -196,7 +195,7 @@ def export(
dirs_to_exclude={"assets", "__pycache__"},
files_to_exclude=files_to_exclude,
exclude_venv_dirs=True,
exclude_sqlite_db_files=backend_exclude_sqlite_db_files,
upload_db_file=upload_db_file,
)

View File

@ -405,6 +405,7 @@ def deploy(
with_metrics: A string indicating the metrics endpoint.
Raises:
AssertionError: If the request is rejected by the hosting server.
Exception: If the operation fails. The exception message is the reason.
Returns:
@ -449,13 +450,16 @@ def deploy(
# If the server explicitly states bad request,
# display a different error
if response.status_code == HTTPStatus.BAD_REQUEST:
raise ValueError(response.json()["detail"])
raise AssertionError("Server rejected this request")
response.raise_for_status()
response_json = response.json()
return DeploymentPostResponse(
frontend_url=response_json["frontend_url"],
backend_url=response_json["backend_url"],
)
except OSError as oe:
console.debug(f"Client side error related to file operation: {oe}")
raise
except httpx.RequestError as re:
console.debug(f"Unable to deploy due to request error: {re}")
raise Exception("request error") from re
@ -468,9 +472,10 @@ def deploy(
except (KeyError, ValidationError) as kve:
console.debug(f"Post params or server response format unexpected: {kve}")
raise Exception("internal errors") from kve
except ValueError as ve:
except AssertionError as ve:
console.debug(f"Unable to deploy due to request error: {ve}")
raise Exception("request error") from ve
# re-raise the error back to the user as client side error
raise
except Exception as ex:
console.debug(f"Unable to deploy due to internal errors: {ex}.")
raise Exception("internal errors") from ex
@ -950,8 +955,12 @@ def interactive_get_deployment_key_from_user_input(
key=key_input,
frontend_hostname=frontend_hostname,
)
assert pre_deploy_response.reply is not None
assert key_input == pre_deploy_response.reply.key
if (
pre_deploy_response.reply is None
or key_input != pre_deploy_response.reply.key
):
# Rejected by server, try again
continue
key_candidate = pre_deploy_response.reply.key
api_url = pre_deploy_response.reply.api_url
deploy_url = pre_deploy_response.reply.deploy_url
@ -1105,13 +1114,16 @@ def get_regions() -> list[dict]:
)
response.raise_for_status()
response_json = response.json()
assert response_json and isinstance(
response_json, list
), "Expect server to return a list "
assert not response_json or (
response_json[0] is not None and isinstance(response_json[0], dict)
), "Expect return values are dict's"
if response_json is None or not isinstance(response_json, list):
console.debug("Expect server to return a list ")
return []
if (
response_json
and response_json[0] is not None
and isinstance(response_json[0], dict)
):
console.debug("Expect return values are dict's")
return []
return response_json
except Exception as ex:
console.debug(f"Unable to get regions due to {ex}.")