AmmarFahmy
adding all files
105b369
from pathlib import Path
from typing import Optional, List
from typer import launch as typer_launch
from phi.cli.settings import phi_cli_settings, PHI_CLI_DIR
from phi.cli.config import PhiCliConfig
from phi.cli.console import print_info, print_heading
from phi.infra.type import InfraType
from phi.infra.resources import InfraResources
from phi.utils.log import logger
def delete_phidata_conf() -> None:
from phi.utils.filesystem import delete_from_fs
logger.debug("Removing existing Phidata configuration")
delete_from_fs(PHI_CLI_DIR)
def authenticate_user() -> None:
"""Authenticate the user using credentials from phidata.com
Steps:
1. Authenticate the user by opening the phidata sign-in url
and the web-app will post an auth token to a mini http server
running on the auth_server_port.
2. Using the auth_token, authenticate the CLI with api and
save the auth_token. This step is handled by authenticate_and_get_user()
3. After the user is authenticated update the PhiCliConfig.
"""
from phi.api.user import authenticate_and_get_user
from phi.api.schemas.user import UserSchema
from phi.cli.auth_server import (
get_port_for_auth_server,
get_auth_token_from_web_flow,
)
print_heading("Authenticating with phidata.com ...")
auth_server_port = get_port_for_auth_server()
redirect_uri = "http%3A%2F%2Flocalhost%3A{}%2F".format(auth_server_port)
auth_url = "{}?source=cli&action=signin&redirecturi={}".format(phi_cli_settings.signin_url, redirect_uri)
print_info("\nYour browser will be opened to visit:\n{}".format(auth_url))
typer_launch(auth_url)
print_info("\nWaiting for a response from browser...\n")
tmp_auth_token = get_auth_token_from_web_flow(auth_server_port)
if tmp_auth_token is None:
logger.error("Could not authenticate, please try again")
return
phi_config: Optional[PhiCliConfig] = PhiCliConfig.from_saved_config()
existing_user: Optional[UserSchema] = phi_config.user if phi_config is not None else None
try:
user: Optional[UserSchema] = authenticate_and_get_user(
tmp_auth_token=tmp_auth_token, existing_user=existing_user
)
except Exception as e:
logger.exception(e)
logger.error("Could not authenticate, please try again")
return
if user is None:
logger.error("Could not authenticate, please try again")
return
if phi_config is None:
phi_config = PhiCliConfig(user)
phi_config.save_config()
else:
phi_config.user = user
print_info("Welcome {}".format(user.email))
def initialize_phi(reset: bool = False, login: bool = False) -> bool:
"""Initialize phi on the users machine.
Steps:
1. Check if PHI_CLI_DIR exists, if not, create it. If reset == True, recreate PHI_CLI_DIR.
2. Authenticates the user if login == True.
3. If PhiCliConfig exists and auth is valid, return True.
"""
from phi.utils.filesystem import delete_from_fs
from phi.api.user import create_anon_user
print_heading("Welcome to phidata!")
if reset:
delete_phidata_conf()
logger.debug("Initializing phidata")
# Check if ~/.phi exists, if it is not a dir - delete it and create the dir
if PHI_CLI_DIR.exists():
logger.debug(f"{PHI_CLI_DIR} exists")
if not PHI_CLI_DIR.is_dir():
try:
delete_from_fs(PHI_CLI_DIR)
except Exception as e:
logger.exception(e)
raise Exception(f"Something went wrong, please delete {PHI_CLI_DIR} and run again")
PHI_CLI_DIR.mkdir(parents=True, exist_ok=True)
else:
PHI_CLI_DIR.mkdir(parents=True)
logger.debug(f"Created {PHI_CLI_DIR}")
# Confirm PHI_CLI_DIR exists otherwise we should return
if PHI_CLI_DIR.exists():
logger.debug(f"Phidata config location: {PHI_CLI_DIR}")
else:
raise Exception("Something went wrong, please try again")
phi_config: Optional[PhiCliConfig] = PhiCliConfig.from_saved_config()
if phi_config is None:
logger.debug("Creating new PhiCliConfig")
phi_config = PhiCliConfig()
phi_config.save_config()
# Authenticate user
if login:
authenticate_user()
else:
anon_user = create_anon_user()
if anon_user is not None and phi_config is not None:
phi_config.user = anon_user
if phi_config is not None:
logger.debug("Phidata initialized")
return True
else:
logger.error("Something went wrong, please try again")
return False
def sign_in_using_cli() -> None:
from getpass import getpass
from phi.api.user import sign_in_user
from phi.api.schemas.user import UserSchema, EmailPasswordAuthSchema
print_heading("Log in")
email_raw = input("email: ")
pass_raw = getpass()
if email_raw is None or pass_raw is None:
logger.error("Incorrect email or password")
try:
user: Optional[UserSchema] = sign_in_user(EmailPasswordAuthSchema(email=email_raw, password=pass_raw))
except Exception as e:
logger.exception(e)
logger.error("Could not authenticate, please try again")
return
if user is None:
logger.error("Could not get user, please try again")
return
phi_config: Optional[PhiCliConfig] = PhiCliConfig.from_saved_config()
if phi_config is None:
phi_config = PhiCliConfig(user)
phi_config.save_config()
else:
phi_config.user = user
print_info("Welcome {}".format(user.email))
def start_resources(
phi_config: PhiCliConfig,
resources_file_path: Path,
target_env: Optional[str] = None,
target_infra: Optional[InfraType] = None,
target_group: Optional[str] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
dry_run: Optional[bool] = False,
auto_confirm: Optional[bool] = False,
force: Optional[bool] = None,
pull: Optional[bool] = False,
) -> None:
print_heading(f"Starting resources in: {resources_file_path}")
logger.debug(f"\ttarget_env : {target_env}")
logger.debug(f"\ttarget_infra : {target_infra}")
logger.debug(f"\ttarget_name : {target_name}")
logger.debug(f"\ttarget_type : {target_type}")
logger.debug(f"\ttarget_group : {target_group}")
logger.debug(f"\tdry_run : {dry_run}")
logger.debug(f"\tauto_confirm : {auto_confirm}")
logger.debug(f"\tforce : {force}")
logger.debug(f"\tpull : {pull}")
from phi.workspace.config import WorkspaceConfig
if not resources_file_path.exists():
logger.error(f"File does not exist: {resources_file_path}")
return
# Get resource groups to deploy
resource_groups_to_create: List[InfraResources] = WorkspaceConfig.get_resources_from_file(
resource_file=resources_file_path,
env=target_env,
infra=target_infra,
order="create",
)
# Track number of resource groups created
num_rgs_created = 0
num_rgs_to_create = len(resource_groups_to_create)
# Track number of resources created
num_resources_created = 0
num_resources_to_create = 0
if num_rgs_to_create == 0:
print_info("No resources to create")
return
logger.debug(f"Deploying {num_rgs_to_create} resource groups")
for rg in resource_groups_to_create:
_num_resources_created, _num_resources_to_create = rg.create_resources(
group_filter=target_group,
name_filter=target_name,
type_filter=target_type,
dry_run=dry_run,
auto_confirm=auto_confirm,
force=force,
pull=pull,
)
if _num_resources_created > 0:
num_rgs_created += 1
num_resources_created += _num_resources_created
num_resources_to_create += _num_resources_to_create
logger.debug(f"Deployed {num_resources_created} resources in {num_rgs_created} resource groups")
if dry_run:
return
if num_resources_created == 0:
return
print_heading(f"\n--**-- ResourceGroups deployed: {num_rgs_created}/{num_rgs_to_create}\n")
if num_resources_created != num_resources_to_create:
logger.error("Some resources failed to create, please check logs")
def stop_resources(
phi_config: PhiCliConfig,
resources_file_path: Path,
target_env: Optional[str] = None,
target_infra: Optional[InfraType] = None,
target_group: Optional[str] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
dry_run: Optional[bool] = False,
auto_confirm: Optional[bool] = False,
force: Optional[bool] = None,
) -> None:
print_heading(f"Stopping resources in: {resources_file_path}")
logger.debug(f"\ttarget_env : {target_env}")
logger.debug(f"\ttarget_infra : {target_infra}")
logger.debug(f"\ttarget_name : {target_name}")
logger.debug(f"\ttarget_type : {target_type}")
logger.debug(f"\ttarget_group : {target_group}")
logger.debug(f"\tdry_run : {dry_run}")
logger.debug(f"\tauto_confirm : {auto_confirm}")
logger.debug(f"\tforce : {force}")
from phi.workspace.config import WorkspaceConfig
if not resources_file_path.exists():
logger.error(f"File does not exist: {resources_file_path}")
return
# Get resource groups to shutdown
resource_groups_to_shutdown: List[InfraResources] = WorkspaceConfig.get_resources_from_file(
resource_file=resources_file_path,
env=target_env,
infra=target_infra,
order="create",
)
# Track number of resource groups deleted
num_rgs_shutdown = 0
num_rgs_to_shutdown = len(resource_groups_to_shutdown)
# Track number of resources created
num_resources_shutdown = 0
num_resources_to_shutdown = 0
if num_rgs_to_shutdown == 0:
print_info("No resources to delete")
return
logger.debug(f"Deleting {num_rgs_to_shutdown} resource groups")
for rg in resource_groups_to_shutdown:
_num_resources_shutdown, _num_resources_to_shutdown = rg.delete_resources(
group_filter=target_group,
name_filter=target_name,
type_filter=target_type,
dry_run=dry_run,
auto_confirm=auto_confirm,
force=force,
)
if _num_resources_shutdown > 0:
num_rgs_shutdown += 1
num_resources_shutdown += _num_resources_shutdown
num_resources_to_shutdown += _num_resources_to_shutdown
logger.debug(f"Deleted {num_resources_shutdown} resources in {num_rgs_shutdown} resource groups")
if dry_run:
return
if num_resources_shutdown == 0:
return
print_heading(f"\n--**-- ResourceGroups deleted: {num_rgs_shutdown}/{num_rgs_to_shutdown}\n")
if num_resources_shutdown != num_resources_to_shutdown:
logger.error("Some resources failed to delete, please check logs")
def patch_resources(
phi_config: PhiCliConfig,
resources_file_path: Path,
target_env: Optional[str] = None,
target_infra: Optional[InfraType] = None,
target_group: Optional[str] = None,
target_name: Optional[str] = None,
target_type: Optional[str] = None,
dry_run: Optional[bool] = False,
auto_confirm: Optional[bool] = False,
force: Optional[bool] = None,
) -> None:
print_heading(f"Updating resources in: {resources_file_path}")
logger.debug(f"\ttarget_env : {target_env}")
logger.debug(f"\ttarget_infra : {target_infra}")
logger.debug(f"\ttarget_name : {target_name}")
logger.debug(f"\ttarget_type : {target_type}")
logger.debug(f"\ttarget_group : {target_group}")
logger.debug(f"\tdry_run : {dry_run}")
logger.debug(f"\tauto_confirm : {auto_confirm}")
logger.debug(f"\tforce : {force}")
from phi.workspace.config import WorkspaceConfig
if not resources_file_path.exists():
logger.error(f"File does not exist: {resources_file_path}")
return
# Get resource groups to update
resource_groups_to_patch: List[InfraResources] = WorkspaceConfig.get_resources_from_file(
resource_file=resources_file_path,
env=target_env,
infra=target_infra,
order="create",
)
num_rgs_patched = 0
num_rgs_to_patch = len(resource_groups_to_patch)
# Track number of resources updated
num_resources_patched = 0
num_resources_to_patch = 0
if num_rgs_to_patch == 0:
print_info("No resources to patch")
return
logger.debug(f"Patching {num_rgs_to_patch} resource groups")
for rg in resource_groups_to_patch:
_num_resources_patched, _num_resources_to_patch = rg.update_resources(
group_filter=target_group,
name_filter=target_name,
type_filter=target_type,
dry_run=dry_run,
auto_confirm=auto_confirm,
force=force,
)
if _num_resources_patched > 0:
num_rgs_patched += 1
num_resources_patched += _num_resources_patched
num_resources_to_patch += _num_resources_to_patch
logger.debug(f"Patched {num_resources_patched} resources in {num_rgs_patched} resource groups")
if dry_run:
return
if num_resources_patched == 0:
return
print_heading(f"\n--**-- ResourceGroups patched: {num_rgs_patched}/{num_rgs_to_patch}\n")
if num_resources_patched != num_resources_to_patch:
logger.error("Some resources failed to patch, please check logs")