Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The list command redesigned. #184

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 90 additions & 116 deletions dem/cli/command/list_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,136 +3,110 @@

from dem.core.platform import Platform
from dem.core.dev_env import DevEnv
from dem.core.tool_images import ToolImage
from dem.core.dev_env_catalog import DevEnvCatalog
from dem.cli.console import stdout, stderr
from rich.table import Table
from typing import List

(
DEV_ENV_ORG_NOT_IN_REGISTRY,
DEV_ENV_ORG_INSTALLED_LOCALLY,
DEV_ENV_ORG_REINSTALL,
DEV_ENV_ORG_READY,
) = range(4)

(
DEV_ENV_LOCAL_NOT_AVAILABLE,
DEV_ENV_LOCAL_REINSTALL,
DEV_ENV_LOCAL_INSTALLED,
) = range(3)

dev_env_org_status_messages = {
DEV_ENV_ORG_NOT_IN_REGISTRY: "[red]Error: Required image is not available in the registry![/]",
DEV_ENV_ORG_INSTALLED_LOCALLY: "Installed locally.",
DEV_ENV_ORG_REINSTALL: "Incomplete local install. The missing images are available in the registry. Use `dem pull` to reinstall.",
DEV_ENV_ORG_READY: "Ready to be installed.",
}

dev_env_local_status_messages = {
DEV_ENV_LOCAL_NOT_AVAILABLE: "[red]Error: Required image is not available![/]",
DEV_ENV_LOCAL_REINSTALL: "Incomplete local install. The missing images are available in the registry. Use `dem pull` to reinstall.",
DEV_ENV_LOCAL_INSTALLED: "Installed.",
}

def get_catalog_dev_env_status(platform: Platform, dev_env: DevEnv) -> str:
image_statuses = []
for tool_image in dev_env.tool_images:
image_statuses.append(tool_image.availability)

if (ToolImage.NOT_AVAILABLE in image_statuses) or (ToolImage.LOCAL_ONLY in image_statuses):
dev_env_status = dev_env_org_status_messages[DEV_ENV_ORG_NOT_IN_REGISTRY]
elif (image_statuses.count(ToolImage.LOCAL_AND_REGISTRY) == len(image_statuses)) and \
platform.get_dev_env_by_name(dev_env.name):
dev_env_status = dev_env_org_status_messages[DEV_ENV_ORG_INSTALLED_LOCALLY]
else:
if platform.get_dev_env_by_name(dev_env.name):
dev_env_status = dev_env_org_status_messages[DEV_ENV_ORG_REINSTALL]
def add_dev_env_info_to_table(platform: Platform, table: Table, dev_env: DevEnv) -> None:
""" Add Development Environment information to the table.

Args:
platform -- the Platform
table -- the Table
dev_env -- the Development Environment
"""
if dev_env.is_installed:
dev_env.assign_tool_image_instances(platform.tool_images)
installed_column = "[green]Yes[/]"
tool_image_status = dev_env.get_tool_image_status()
if tool_image_status == DevEnv.Status.UNAVAILABLE_IMAGE:
status_column = "[red]Error: Required image is not available![/]"
elif tool_image_status == DevEnv.Status.REINSTALL_NEEDED:
status_column = "[red]Error: Incomplete local install![/]"
else:
dev_env_status = dev_env_org_status_messages[DEV_ENV_ORG_READY]
return dev_env_status

def get_local_dev_env_status(dev_env: DevEnv, tool_images: ToolImage) -> str:
image_statuses = []
for tool_image in dev_env.tool_images:
image_statuses.append(tool_image.availability)

if (ToolImage.NOT_AVAILABLE in image_statuses):
dev_env_status = dev_env_local_status_messages[DEV_ENV_LOCAL_NOT_AVAILABLE]
elif (ToolImage.REGISTRY_ONLY in image_statuses):
dev_env_status = dev_env_local_status_messages[DEV_ENV_LOCAL_REINSTALL]
status_column = "Ok"
else:
dev_env_status = dev_env_local_status_messages[DEV_ENV_LOCAL_INSTALLED]
return dev_env_status

def list_dev_envs(platform: Platform, local: bool, org: bool)-> None:

installed_column = "No"
status_column = "Ok"
table.add_row(dev_env.name, installed_column, status_column)

table = Table()
table.add_column("Development Environment")
table.add_column("Status")

if ((local == True) and (org == False)):
if not platform.local_dev_envs:
stdout.print("[yellow]No installed Development Environments.[/]")
return
else:
for dev_env in platform.local_dev_envs:
table.add_row(dev_env.name, get_local_dev_env_status(dev_env, platform.tool_images))
elif((local == False) and (org == True)):
if not platform.dev_env_catalogs.catalogs:
stdout.print("[yellow]No Development Environment Catalogs are available!")
return
for catalog in platform.dev_env_catalogs.catalogs:
catalog.request_dev_envs()
if not catalog.dev_envs:
stdout.print("[yellow]No Development Environments are available in the catalogs.[/]")
return
else:
for dev_env in catalog.dev_envs:
table.add_row(dev_env.name, get_catalog_dev_env_status(platform, dev_env))
else:
stderr.print("[red]Error: Invalid options.[/]")
def list_local_dev_envs(platform: Platform) -> None:
""" List the local Development Environments.

Args:
platform -- the Platform
"""
if not platform.local_dev_envs:
stdout.print("[yellow]No Development Environment descriptors are available.[/]")
return
else:
table = Table()
table.add_column("Name")
table.add_column("Installed")
table.add_column("Status")

stdout.print(table)
for dev_env in sorted(platform.local_dev_envs, key=lambda dev_env: dev_env.name.lower()):
add_dev_env_info_to_table(platform, table, dev_env)

def list_tool_images(platform: Platform, local: bool, org: bool) -> None:
""" List tool images
stdout.print(f"\n [italic]Local Development Environments[/]")
stdout.print(table)

def list_actual_cat_dev_envs(catalog: DevEnvCatalog) -> None:
""" List the Development Environments in the catalog.

Args:
local -- list local tool images
org -- list the tool catalog
Args:
catalog -- the Development Environment Catalog
"""
if (local == True) and (org == False):
local_images = platform.container_engine.get_local_tool_images()

catalog.request_dev_envs()
if not catalog.dev_envs:
stdout.print(f"[yellow]No Development Environments are available in the {catalog.name} catalog.[/]")
else:
table = Table()
table.add_column("Repository")
for local_image in local_images:
table.add_row(local_image)
table.add_column("Name")
for dev_env in catalog.dev_envs:
table.add_row(dev_env.name)
stdout.print(f"\n [italic]Development Environments in the {catalog.name} catalog:[/]")
stdout.print(table)
elif (local == False) and (org == True):
if not platform.registries.registries:
stdout.print("[yellow]No registries are available!")
return

def list_all_cat_dev_envs(platform: Platform) -> None:
""" List all Development Environments in the catalogs.

Args:
platform -- the Platform
"""
if not platform.dev_env_catalogs.catalogs:
stdout.print("[yellow]No Development Environment Catalogs are available!")
return

for catalog in platform.dev_env_catalogs.catalogs:
list_actual_cat_dev_envs(catalog)

registry_images = platform.registries.list_repos()
if registry_images:
table = Table()
table.add_column("Repository")
for registry_image in registry_images:
table.add_row(registry_image)
stdout.print(table)
def list_selected_cat_dev_envs(platform: Platform, cat: List[str]) -> None:
""" List the Development Environments from the specified catalogs.

Args:
platform -- the Platform
cat -- the specified catalogs
"""
for cat_name in cat:
for catalog in platform.dev_env_catalogs.catalogs:
if catalog.name == cat_name:
list_actual_cat_dev_envs(catalog)
break
else:
stdout.print("[yellow]No images are available in the registries!")
stderr.print(f"[red]Error: Catalog '{cat_name}' not found![/]")

def execute(platform: Platform, local: bool, org: bool, env: bool, tool: bool) -> None:
if ((local == True) or (org == True)) and (env == True) and (tool == False):
list_dev_envs(platform, local, org)
elif ((local == True) or (org == True)) and (env == False) and (tool == True):
list_tool_images(platform, local, org)
def execute(platform: Platform, cat: bool, specified_cats: list[str]) -> None:
""" List Development Environments

Args:
cat -- if true list all Development Environments in the catalogs
specified_cats -- list the Development Environments from the specified catalogs
"""
if cat and not specified_cats:
list_all_cat_dev_envs(platform)
elif specified_cats:
list_selected_cat_dev_envs(platform, specified_cats)
else:
stderr.print(\
"""Usage: dem list [OPTIONS]
Try 'dem list --help' for help.

Error: You need to set the scope and what to list!""")
list_local_dev_envs(platform)
27 changes: 10 additions & 17 deletions dem/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,19 @@ def autocomplete_host_name(incomplete: str) -> Generator:
yield host_config["name"]

# DEM commands
@typer_cli.command("list") # "list" is a Python keyword
def list_(local: Annotated[bool, typer.Option(help="Scope is the local host.")] = False,
all: Annotated[bool, typer.Option(help="Scope is the catalogs.")] = False,
env: Annotated[bool, typer.Option(help="List the environments.")] = False,
tool: Annotated[bool, typer.Option(help="List the tool images.")] = False) -> None:
@typer_cli.command("list", context_settings={"allow_extra_args": True}) # "list" is a Python keyword
def list_(cat: Annotated[bool, typer.Option(help="List the Dev Envs available from the catalogs.",
show_default=False)] = False,
ctx: Annotated[typer.Context, typer.Option()] = None) -> None:
"""
List the Development Environments available locally or from the catalogs.
List the locally available Dev Envs.

The following option combinations are suppported:

--local --env -> List the local Development Environments.

--all --env -> List the Development Environments available from the catalogs.

--local --tool -> List the local tool images.

--all --tool -> List the tool images available from the registries.
--cat: List the available Dev Envs from the catalogs. Specify the catalogs' name to list the Dev
Envs from. More then one catalog can be specified. If no catalog is specified, all the available
catalogs will be used.
"""
if platform:
list_cmd.execute(platform, local, all, env, tool)
if platform and ctx:
list_cmd.execute(platform, cat, ctx.args)
else:
raise InternalError("Error: The platform hasn't been initialized properly!")

Expand Down
38 changes: 38 additions & 0 deletions dem/core/dev_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
# dem/core/dev_env.py

from dem.core.tool_images import ToolImage, ToolImages
from enum import Enum
import json, os

class DevEnv():
""" A Development Environment. """

class Status(Enum):
""" The status of an installed Development Environment. """
OK = 0
REINSTALL_NEEDED = 1
UNAVAILABLE_IMAGE = 2

def __init__(self, descriptor: dict | None = None, descriptor_path: str | None = None) -> None:
""" Init the DevEnv class.

Expand Down Expand Up @@ -45,11 +52,42 @@ def __init__(self, descriptor: dict | None = None, descriptor_path: str | None =
self.is_installed = False

def assign_tool_image_instances(self, tool_images: ToolImages) -> None:
""" Assign the Tool Images to the Development Environment.

After creating a DevEnv instance, the Tool Images are not yet assigned to it. This
method must be called if the Tool Images are needed.

Args:
tool_images -- the Tool Images to assign

Exceptions:
ToolImageError -- if the Tool Image name is invalid
"""
for tool_descriptor in self.tool_image_descriptors:
tool_image_name = tool_descriptor["image_name"] + ':' + tool_descriptor["image_version"]
tool_image = tool_images.all_tool_images.get(tool_image_name, ToolImage(tool_image_name))
self.tool_images.append(tool_image)

def get_tool_image_status(self) -> Status:
""" Get the status of the Tool Images.

Can only be used if the Dev Env is insalled.

This method checks the availability of the assigned Tool Images.
If at least one of the Tool Images is unkonwn: NOT_AVAILABLE.
If at least one of the Tool Images is only available in the registry: REINSTALL_NEEDED.
If all the Tool Images are available: OK.

Returns:
Status -- the status of the Dev Env
"""
for tool_image in self.tool_images:
if tool_image.availability == ToolImage.NOT_AVAILABLE:
return self.Status.UNAVAILABLE_IMAGE
elif tool_image.availability == ToolImage.REGISTRY_ONLY:
return self.Status.REINSTALL_NEEDED
return self.Status.OK

def get_deserialized(self, omit_is_installed: bool = False) -> dict[str, str]:
""" Create the deserialized json.

Expand Down
8 changes: 8 additions & 0 deletions dem/core/tool_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ class ToolImage():
) = range(4)

def __init__(self, name: str) -> None:
""" Init the class.

Args:
name -- the name of the tool image

Exceptions:
ToolImageError -- if the name is invalid
"""
self.name = name
try:
self.repository = self.name.split(":")[0]
Expand Down
19 changes: 7 additions & 12 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
## **`dem list [OPTIONS]`**

List the Development Environments installed locally or available in the catalog.
List the locally available Dev Envs.

Options:

- Level 1:
- `--local` Scope is the local host.
- `--all` Scope is the catalog.
- Level 2:
- `--env` List the Development Environments.
- `--tool` List the tool images.
`--cat`: List the available Dev Envs from the catalogs. Specify the catalogs' name to list the Dev
Envs from. More then one catalog can be specified. If no catalog is specified, all the available
catalogs will be used.

!!! abstract "The following option combinations are supported:"
Examples:

`--local --env` -> List the local Development Environments.
`--all --env` -> List the catalog Development Environments.
`--local --tool` -> List the local tool images.
`--all --tool` -> List the tool images available in the registries.
- `dem list --cat` List all the Dev Envs from all the available catalogs.
- `dem list --cat catalog1 catalog2` List all the Dev Envs from the catalog1 and catalog2.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Now that you have the DEM installed, you might find yourself in one of the follo
Here at axem we'd like to create a template for every target out there. List the currently available
ones with:

dem list --all --env
dem list --cat

You can clone the selected template with:

Expand Down
4 changes: 0 additions & 4 deletions docs/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ div {
font-size: 20px;
}

span {
font-size: 24px;
}

@font-face {
font-family: 'DarkerGrotesque-Medium';
src: url(../Darker_Grotesque/DarkerGrotesque-Medium.ttf) format('truetype');
Expand Down
Binary file modified docs/wp-content/dev_env_settings_window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading