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

[#112] Add --remote flag to all cli commands #109

Merged
merged 4 commits into from
Aug 29, 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
2 changes: 1 addition & 1 deletion .docker/Dockerfile.das-toolbox
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:20.04 AS builder
FROM ubuntu:22.04 AS builder

ENV TZ=America/Sao_Paulo \
DEBIAN_FRONTEND=noninteractive
Expand Down
87 changes: 84 additions & 3 deletions src/common/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any

import click
from fabric import Connection

from common.logger import logger

Expand Down Expand Up @@ -34,19 +35,99 @@ class Command:
help = ""
short_help = ""
params = []
# TODO: Add more ways to connect, example: ssh-key file, etc. Look at the fabric docs.
remote_params = [
CommandOption(
["--remote"],
type=bool,
default=False,
is_flag=True,
help="whether to run the command on a remote server",
),
CommandOption(
["--host", "-H"],
type=str,
help="the login user for the remote connection",
required=False,
),
CommandOption(
["--user", "-H"],
type=str,
help="the login user for the remote connection",
required=False,
),
CommandOption(
["--port", "-H"],
type=int,
help="the remote port",
required=False,
),
]

def __init__(self) -> None:
self.command = click.Command(
name=self.name,
callback=self.safe_run,
help=self.help,
short_help=self.short_help,
params=self.params,
params=self.params + self.remote_params,
)

def safe_run(self, **kwarg):
def _get_remote_kwargs(self, kwargs) -> tuple[bool, dict, dict]:
"""
Gets remote kwargs from kwargs.
Params:
Returns (bool, kwargs, remote_kwargs):
First value is whether the command should be run on a remote server or not.
"""
if not kwargs:
return (False, kwargs, {})
remote_kwargs = {
"user": kwargs.pop("user") or "",
"port": kwargs.pop("port") or 22,
"host": kwargs.pop("host") or "",
}
remote = kwargs.pop("remote") or False

return (remote, kwargs, remote_kwargs)

def _dict_to_command_line_args(self, d: dict) -> str:
"""
Convert dict to command line args

Params:
d (dict): the dict to be converted convert

"""
args = []
for key, value in d.items():
arg_key = str(key).replace("_", "-")

if isinstance(value, bool):
if value:
args.append(f"--{arg_key}")
else:
if value:
arg_value = str(value).lower()
arg = f"--{arg_key} {arg_value}"
args.append(arg)

return " ".join(args)

def _remote_run(self, kwargs, remote_kwargs):
ctx = click.get_current_context()
prefix = "das-cli"
command_path = " ".join(ctx.command_path.split(" ")[1:])
extra_args = self._dict_to_command_line_args(kwargs)
command = f"{prefix} {command_path} {extra_args}"
Connection(**remote_kwargs).run(command)

def safe_run(self, **kwargs):
remote, kwargs, remote_kwargs = self._get_remote_kwargs(kwargs)
try:
return self.run(**kwarg)
if remote:
return self._remote_run(kwargs, remote_kwargs)
return self.run(**kwargs)
except Exception as e:
error_type = e.__class__.__name__
error_message = str(e)
Expand Down
2 changes: 1 addition & 1 deletion src/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Click==7.0
Click==8.1.6
docker==7.1.0
distro==1.9.0
click-man==0.4.1
Expand Down
55 changes: 55 additions & 0 deletions tests/integration/test_remote.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/local/bin/bats

load 'libs/bats-support/load'
load 'libs/bats-assert/load'
load 'libs/utils'
load 'libs/docker'

setup() {
if [ -z "${REMOTE_HOST+x}" ]; then
skip "Environment variable REMOTE_HOST is not set. Skipping all tests in this file."
fi

libs=(hyperon-das hyperon-das-atomdb)

pip3 install hyperon-das==0.7.13
}

teardown() {
pip3 uninstall -y hyperon-das
pip3 uninstall -y hyperon-das-atomdb
}

@test "Listing all python library versions" {
local available_versions_regex="^.*\savailable\sversions:"
local available_versions_match_count

run python3 src/das_cli.py python-library list --remote --host $REMOTE_HOST

available_versions_match_count=$(echo "$output" | grep -cE "$available_versions_regex")

assert_output --regexp "$available_versions_regex"
assert [ "$available_versions_match_count" -eq "${#libs[@]}" ]
}

@test "Show available python library versions" {
local available_versions_regex="^.*\savailable\sversions:"

for lib in "${libs[@]}"; do
local available_versions_match_count

run python3 src/das_cli.py python-library list --library "$lib" --remote --host $REMOTE_HOST
available_versions_match_count=$(echo "$output" | grep -cE "$available_versions_regex")

assert_output --regexp "$available_versions_regex"
assert [ "$available_versions_match_count" -eq 1 ]
done
}

@test "Trying to show version to an invalid python library" {
local invalid_lib="invalid-python-library"

run python3 src/das_cli.py python-library list --library $invalid_lib --remote --host $REMOTE_HOST

assert_failure
}
Loading