Skip to content

Commit

Permalink
The del-host command implemented.
Browse files Browse the repository at this point in the history
* Host class added for easier config management.
* Documentation and new test cases have been added.
  • Loading branch information
janosmurai committed Jan 3, 2024
1 parent a50073f commit e5f76bb
Show file tree
Hide file tree
Showing 15 changed files with 470 additions and 184 deletions.
46 changes: 9 additions & 37 deletions dem/cli/command/add_host_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from dem.core.platform import Platform
from dem.cli.console import stdout
import typer

def execute(platform: Platform, name: str, address: str) -> None:
""" Add a new host.
Expand All @@ -10,41 +11,12 @@ def execute(platform: Platform, name: str, address: str) -> None:
name -- name of the host
address -- IP or hostname of the host
"""
if not name or not address:
stdout.print("[red]Error: NAME or ADDRESS cannot be empty.[/]")
exit(1)
existing_host: dict | None = next((host for host in platform.hosts.list_host_configs() if host["name"] == name),
None)
if existing_host:
typer.confirm(f"Host with name {name} already exists. Do you want to overwrite it?",
abort=True)
platform.hosts.delete_host(existing_host)

data = platform.config_file.deserialized.get("hosts", [])

if not data:
platform.config_file.deserialized["hosts"] = [{"name": name, "address": address}]
else:
# Check if the host name already exists
existing_host = next((host for host in data if host["name"] == name), None)
if existing_host:
# Ask the user if they want to overwrite the existing host
try:
choice = input(f"Host with name {name} already exists. Do you want to overwrite it? (yes/no): ")
except EOFError:
stdout.print("[yellow]Host addition cancelled.[/]")
exit(1)

while choice.lower() not in ['yes', 'no']:
stdout.print("[yellow]Please enter 'yes' or 'no'.[/]")
try:
choice = input(f"Host with name {name} already exists. Do you want to overwrite it? (yes/no): ")
except EOFError:
stdout.print("[yellow]Host addition cancelled.[/]")
return

if choice.lower() == 'yes':
existing_host["address"] = address
else:
stdout.print("[yellow]Host addition cancelled.[/]")
return
else:
data.append({"name": name, "address": address})

# Save the updated data
platform.config_file.flush()
stdout.print("[green]Host added successfully![/]")
platform.hosts.add_host({"name": name, "address": address})
stdout.print("[green]Host added successfully![/]")
19 changes: 19 additions & 0 deletions dem/cli/command/del_host_cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""CLI command implementation for deleting a Host."""
# dem/cli/command/del_host_cmd.py

from dem.core.platform import Platform
from dem.cli.console import stdout, stderr

def execute(platform: Platform, host_name: str) -> None:
""" Delete the Host.
Args:
host_name -- name of the host to delete
"""
for host_config in platform.hosts.list_host_configs():
if host_config["name"] == host_name:
platform.hosts.delete_host(host_config)
stdout.print("[green]Host deleted successfully![/]")
break
else:
stderr.print("[red]Error: The input Host does not exist.[/]")
4 changes: 2 additions & 2 deletions dem/cli/command/list_host_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from dem.cli.console import stdout
from rich.table import Table

def execute(platform) -> None:
def execute(platform: Platform) -> None:
""" List available Hosts.
Usage: dem list-host
"""

hosts = platform.config_file.deserialized.get("hosts", [])
hosts: list[dict] = platform.hosts.list_host_configs()
"""
Ideally, if 'hosts' is populated, it should look something like:
hosts = [
Expand Down
26 changes: 25 additions & 1 deletion dem/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from dem.cli.command import cp_cmd, info_cmd, list_cmd, pull_cmd, create_cmd, modify_cmd, delete_cmd, \
rename_cmd, run_cmd, export_cmd, load_cmd, clone_cmd, add_reg_cmd, \
list_reg_cmd, del_reg_cmd, add_cat_cmd, list_cat_cmd, del_cat_cmd, \
add_host_cmd, uninstall_cmd, list_host_cmd
add_host_cmd, uninstall_cmd, list_host_cmd, del_host_cmd
from dem.cli.console import stdout
from dem.core.platform import Platform
from dem.core.exceptions import InternalError
Expand Down Expand Up @@ -56,6 +56,19 @@ def autocomplete_reg_name(incomplete: str) -> Generator:
if registry_config["name"].startswith(incomplete) or (incomplete == ""):
yield registry_config["name"]

def autocomplete_host_name(incomplete: str) -> Generator:
"""
Autocomplete the input Host name with the available matching Hosts.
Return with the matching Host name by a Generator.
Args:
incomplete -- the parameter the user supplied so far when the tab was pressed
"""
for host_config in platform.hosts.list_configs():
if host_config["name"].startswith(incomplete) or (incomplete == ""):
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,
Expand Down Expand Up @@ -321,6 +334,17 @@ def list_host() -> None:
else:
raise InternalError("Error: The platform hasn't been initialized properly!")

@typer_cli.command()
def del_host(host_name: Annotated[str, typer.Argument(help="Name of the host to delete.",
autocompletion=autocomplete_host_name)]) -> None:
"""
Delete a host.
"""
if platform:
del_host_cmd.execute(platform, host_name)
else:
raise InternalError("Error: The platform hasn't been initialized properly!")

def _version_callback(value: bool) -> None:
if value:
try:
Expand Down
8 changes: 5 additions & 3 deletions dem/core/data_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dem.core.properties import __config_dir_path__
from pathlib import PurePath
import os
import json, requests
import json

class BaseJSON(Core):
""" This class acts as an abstracted buffer over a json file.
Expand Down Expand Up @@ -98,8 +98,10 @@ def __init__(self) -> None:
"url": "https://axemsolutions.io/dem/dev_env_org.json"
}
]
"hosts": []
}"""
super().__init__()

self.registries: list[dict] = self.deserialized["registries"]
self.catalogs: list[dict] = self.deserialized["catalogs"]
self.registries: list[dict] = self.deserialized.get("registries", [])
self.catalogs: list[dict] = self.deserialized.get("catalogs", [])
self.hosts: list[dict] = self.deserialized.get("hosts", [])
70 changes: 70 additions & 0 deletions dem/core/hosts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Hosts."""
# dem/core/hosts.py

from dem.core.data_management import ConfigFile
from dem.core.core import Core

class Host():
""" A Host. """
def __init__(self, host_config: dict) -> None:
""" Init the class with the host config.
Args:
host_config -- the host config
"""
self.config: dict = host_config
self.name: str = host_config["name"]
self.address: str = host_config["address"]

class Hosts(Core):
""" List of the available Hosts. """
def __init__(self, config_file: ConfigFile) -> None:
""" Init the class with the host configurations.
Args:
config_file -- contains the host configurations
"""
self._config_file: ConfigFile = config_file
self.hosts: list[Host] = []
for host_config in config_file.hosts:
self._try_to_add_host(host_config)

def _try_to_add_host(self, host_config: dict) -> bool:
try:
self.hosts.append(Host(host_config))
except Exception as e:
self.user_output.error(str(e))
self.user_output.error("Error: Couldn't add this Host.")
return False
else:
return True

def add_host(self, host_config: dict) -> None:
""" Add a new host.
Args:
catalog_config -- the new catalog to add
"""
if self._try_to_add_host(host_config):
self._config_file.hosts.append(host_config)
self._config_file.flush()

def list_host_configs(self) -> list[dict]:
""" List the host configs. (As stored in the config file.)
Return with the list of the available host configurations.
"""
return self._config_file.hosts

def delete_host(self, host_config: dict) -> None:
""" Delete the host.
Args:
host_config -- config of the host to delete
"""
for host in self.hosts.copy():
if host.config == host_config:
self.hosts.remove(host)

self._config_file.hosts.remove(host_config)
self._config_file.flush()
13 changes: 13 additions & 0 deletions dem/core/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from dem.core.registry import Registries
from dem.core.tool_images import ToolImages
from dem.core.dev_env import DevEnv
from dem.core.hosts import Hosts

class Platform(Core):
""" Representation of the Development Platform:
Expand Down Expand Up @@ -46,6 +47,7 @@ def __init__(self) -> None:
self._container_engine = None
self._registries = None
self._config_file = None
self._hosts = None

self.local_dev_envs: list[DevEnv] = []
for dev_env_descriptor in self.dev_env_json.deserialized["development_environments"]:
Expand Down Expand Up @@ -106,6 +108,17 @@ def dev_env_catalogs(self) -> DevEnvCatalogs:

return self._dev_env_catalogs

@property
def hosts(self) -> Hosts:
""" The hosts.
The Hosts() gets instantiated only at the first access.
"""
if self._hosts is None:
self._hosts = Hosts(self.config_file)

return self._hosts

def get_deserialized(self) -> dict:
""" Create the deserialized json.
Expand Down
27 changes: 20 additions & 7 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ Arguments:

---

## **`dem uninstall DEV_ENV_NAME`**

Uninstall the selected Development Environment. Set installed flag to False if it was True. Dem checks whether a tool image is
required or not by any of the remaining installed local Development Environments. In case the tool image is
not required anymore, the dem delete it.

Arguments:

`DEV_ENV_NAME` Name of the Development Environment to uninstall. [required]

---

## **`dem run DEV_ENV_NAME *`**

:warning: Experimental feature!
Expand Down Expand Up @@ -286,6 +298,8 @@ Arguments:

`NAME` Name of the registry to delete. [required]

# Host management

## **`dem add-host NAME ADDRESS`**

Add a new host to the configuration.
Expand All @@ -296,19 +310,18 @@ Arguments:

`ADDRESS` IP or hostname of the host. [required]

---

## **`dem list-host`**

List the available hosts from the config file.

---
## **`dem uninstall DEV_ENV_NAME`**

Uninstall the selected Development Environment. Set installed flag to False if it was True. Dem checks whether a tool image is
required or not by any of the remaining installed local Development Environments. In case the tool image is
not required anymore, the dem delete it.
## **`dem del-host NAME`**

Arguments:
Delete a host from the config file.

`DEV_ENV_NAME` Name of the Development Environment to uninstall. [required]
Arguments:

---
`NAME` Name of the host to delete. [required]
Loading

0 comments on commit e5f76bb

Please sign in to comment.