From dc283251d921e3b56a1a6c2ee569e50129beaea9 Mon Sep 17 00:00:00 2001 From: meow Date: Tue, 31 Dec 2019 19:54:08 +0500 Subject: [PATCH 1/2] refactoring done --- .gitignore | 4 +- bin/ucloud-cli | 27 ------ bin/uncloud-cli | 47 ++++++++++ conf/ucloud-cli.conf | 4 - setup.py | 11 +-- uncloud_cli/commands/helper.py | 67 ++++++++++++-- uncloud_cli/commands/host.py | 41 ++++----- uncloud_cli/commands/image.py | 19 ++-- uncloud_cli/commands/network.py | 23 +---- uncloud_cli/commands/user.py | 81 ++++------------ uncloud_cli/commands/vm.py | 157 ++++++++------------------------ uncloud_cli/config.py | 11 ++- uncloud_cli/helper.py | 24 +++++ 13 files changed, 227 insertions(+), 289 deletions(-) delete mode 100755 bin/ucloud-cli create mode 100755 bin/uncloud-cli delete mode 100644 conf/ucloud-cli.conf diff --git a/.gitignore b/.gitignore index 1e835aa..bc1cc8a 100755 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .vscode __pycache__ -ucloud_cli.egg-info +uncloud_cli.egg-info build/ -dist/ \ No newline at end of file +dist/ diff --git a/bin/ucloud-cli b/bin/ucloud-cli deleted file mode 100755 index 13cd678..0000000 --- a/bin/ucloud-cli +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 - -import click -import sys - -from ucloud_cli.commands.vm import vm -from ucloud_cli.commands.user import user -from ucloud_cli.commands.host import host -from ucloud_cli.commands.image import image -from ucloud_cli.commands.network import network - -from ucloud_cli.helper import exception_handler - - -@click.group() -def entry_point(): - pass - - -if __name__ == "__main__": - sys.excepthook = exception_handler - entry_point.add_command(vm) - entry_point.add_command(user) - entry_point.add_command(image) - entry_point.add_command(host) - entry_point.add_command(network) - entry_point() diff --git a/bin/uncloud-cli b/bin/uncloud-cli new file mode 100755 index 0000000..a02d9fd --- /dev/null +++ b/bin/uncloud-cli @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import click +import sys +import logging + +from logging.handlers import SysLogHandler + +from uncloud_cli.commands.vm import vm +from uncloud_cli.commands.user import user +from uncloud_cli.commands.host import host +from uncloud_cli.commands.image import image +from uncloud_cli.commands.network import network +from uncloud_cli.helper import exception_handler, NoTracebackStreamHandler + + +@click.group() +def entry_point(): + pass + + +if __name__ == "__main__": + sys.excepthook = exception_handler + + # Setting up root logger + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + syslog_handler = SysLogHandler(address='/dev/log') + syslog_handler.setLevel(logging.DEBUG) + syslog_formatter = logging.Formatter('%(pathname)s:%(lineno)d -- %(levelname)-8s %(message)s') + syslog_handler.setFormatter(syslog_formatter) + + stream_handler = NoTracebackStreamHandler() + stream_handler.setLevel(logging.INFO) + stream_formatter = logging.Formatter('%(message)s') + stream_handler.setFormatter(stream_formatter) + + logger.addHandler(syslog_handler) + logger.addHandler(stream_handler) + + entry_point.add_command(vm) + entry_point.add_command(user) + entry_point.add_command(image) + entry_point.add_command(host) + entry_point.add_command(network) + entry_point() diff --git a/conf/ucloud-cli.conf b/conf/ucloud-cli.conf deleted file mode 100644 index 54b0dea..0000000 --- a/conf/ucloud-cli.conf +++ /dev/null @@ -1,4 +0,0 @@ -OTP_NAME=replace_me -OTP_REALM=replace_me -OTP_SEED=replace_me -UCLOUD_API_SERVER=http://[::]:5000 \ No newline at end of file diff --git a/setup.py b/setup.py index 497cea1..7c20e4e 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,12 @@ -import os - from setuptools import setup, find_packages with open("README.md", "r") as fh: long_description = fh.read() -setup(name='ucloud_cli', +setup(name='uncloud_cli', version='0.1', - description='A utility to interact with ucloud server.', - url='https://code.ungleich.ch/ucloud/ucloud-cli', + description='A utility to interact with uncloud server.', + url='https://code.ungleich.ch/uncloud/uncloud-cli', long_description=long_description, long_description_content_type='text/markdown', classifiers=[ @@ -26,6 +24,5 @@ setup(name='ucloud_cli', 'pyotp', 'click' ], - scripts=['bin/ucloud-cli'], - data_files=[(os.path.expanduser('~/ucloud/'), ['conf/ucloud-cli.conf'])], + scripts=['bin/uncloud-cli'], zip_safe=False) diff --git a/uncloud_cli/commands/helper.py b/uncloud_cli/commands/helper.py index ce3da6b..1b2f341 100755 --- a/uncloud_cli/commands/helper.py +++ b/uncloud_cli/commands/helper.py @@ -1,16 +1,12 @@ import json +import binascii +import click +import requests + +from os.path import join as join_path from pyotp import TOTP - - -class OTPCredentials: - def __init__(self, name, realm, seed): - self.name = name # type: str - self.realm = realm # type: str - self.seed = seed # type: str - - def get_json(self): - return {"name": self.name, "realm": self.realm, "token": TOTP(self.seed).now()} +from uncloud_cli.config import config, config_file def load_dump_pretty(content): @@ -18,3 +14,54 @@ def load_dump_pretty(content): content = content.decode("utf-8") parsed = json.loads(content) return json.dumps(parsed, indent=4, sort_keys=True) + + +def make_request(*args, data=None, request_method=requests.post): + r = request_method( + join_path(config['client']['api_server'], *args), json=data + ) + print(load_dump_pretty(r.content)) + + +def get_token(ctx, param, value): + if value is not None: + try: + token = TOTP(value).now() + except binascii.Error: + raise click.BadParameter('Please enter the correct seed in {}'.format(config_file)) + else: + param.name = 'token' + return token + + +def add_otp_options(f): + options = [ + click.option( + "--name", required=True, default=config['client']['name'], + show_default='name mentioned in {}'.format(config_file) + ), + click.option( + "--realm", required=True, default=config['client']['realm'], + show_default='realm mentioned in {}'.format(config_file) + ), + click.option( + "--seed", required=True, default=config['client']['seed'], + callback=get_token, show_default='seed mentioned in {}'.format(config_file) + ) + ] + + for opt in reversed(options): + f = opt(f) + + return f + + +def add_vm_options(f): + options = [ + click.option('--vm-name', required=True), + click.option('--action', required=True, default=f.__name__) + ] + for opt in reversed(options): + f = opt(f) + + return f diff --git a/uncloud_cli/commands/host.py b/uncloud_cli/commands/host.py index c0a04f3..29ee417 100755 --- a/uncloud_cli/commands/host.py +++ b/uncloud_cli/commands/host.py @@ -1,9 +1,7 @@ import click import requests -from .helper import OTPCredentials, load_dump_pretty -from uncloud_cli.config import env_vars -from os.path import join as join_path +from .helper import add_otp_options, make_request @click.group() @@ -11,28 +9,23 @@ def host(): pass -@host.command("create") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--hostname", required=True) -@click.option("--cpu", required=True, type=int) -@click.option("--ram", required=True) -@click.option("--os-ssd", required=True) -@click.option("--hdd", default=list(), multiple=True) -def create(name, realm, seed, hostname, cpu, ram, os_ssd, hdd): - data = { - **OTPCredentials(name, realm, seed).get_json(), - "hostname": hostname, - "specs": {"cpu": cpu, "ram": ram, "os-ssd": os_ssd, "hdd": hdd}, +@host.command('create') +@add_otp_options +@click.option('--hostname', required=True) +@click.option('--cpu', required=True, type=int) +@click.option('--ram', required=True) +@click.option('--os-ssd', required=True) +@click.option('--hdd', default=list(), multiple=True) +def create(**kwargs): + kwargs['specs'] = { + 'cpu': kwargs.pop('cpu'), + 'ram': kwargs.pop('ram'), + 'os-ssd': kwargs.pop('os_ssd'), + 'hdd': kwargs.pop('hdd') } - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "host", "create"), json=data - ) - print(load_dump_pretty(r.content)) + make_request('host', 'create', data=kwargs) -@host.command("list") +@host.command('list') def list_host(): - r = requests.get(join_path(env_vars.get("UCLOUD_API_SERVER"), "host", "list")) - print(load_dump_pretty(r.content)) + make_request('host', 'list', request_method=requests.get) diff --git a/uncloud_cli/commands/image.py b/uncloud_cli/commands/image.py index 18e9cf3..2f54a53 100755 --- a/uncloud_cli/commands/image.py +++ b/uncloud_cli/commands/image.py @@ -1,10 +1,8 @@ -from uncloud_cli.commands.helper import load_dump_pretty -from uncloud_cli.config import env_vars -from os.path import join as join_path - import click import requests +from uncloud_cli.commands.helper import make_request + @click.group() def image(): @@ -15,17 +13,12 @@ def image(): @click.option("--public", is_flag=True) def _list(public): if public: - r = requests.get(join_path(env_vars.get("UCLOUD_API_SERVER"), "image", "list-public")) - print(load_dump_pretty(r.content)) + make_request('image', 'list-public', request_method=requests.get) @image.command("create-from-file") @click.option("--name", required=True) @click.option("--uuid", required=True) -@click.option("--image-store-name", required=True) -def create_from_file(name, uuid, image_store_name): - data = {"name": name, "uuid": uuid, "image_store": image_store_name} - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "image", "create"), json=data - ) - print(load_dump_pretty(r.content)) +@click.option("--image-store-name", 'image_store', required=True) +def create_from_file(**kwargs): + make_request('image', 'create', data=kwargs) diff --git a/uncloud_cli/commands/network.py b/uncloud_cli/commands/network.py index 48cbc0d..176beda 100644 --- a/uncloud_cli/commands/network.py +++ b/uncloud_cli/commands/network.py @@ -1,6 +1,4 @@ -from uncloud_cli.commands.helper import load_dump_pretty, OTPCredentials -from uncloud_cli.config import env_vars -from os.path import join as join_path +from uncloud_cli.commands.helper import add_otp_options, make_request import click import requests @@ -12,20 +10,9 @@ def network(): @network.command("create") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) +@add_otp_options @click.option("--network-name", required=True) -@click.option("--network-type", required=True) +@click.option("--network-type", 'type', required=True) @click.option("--user", required=True, type=bool, default=False) -def create(name, realm, seed, network_name, network_type, user): - data = { - **OTPCredentials(name, realm, seed).get_json(), - "network_name": network_name, - "type": network_type, - "user": user, - } - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "network", "create"), json=data - ) - print(load_dump_pretty(r.content)) +def create(**kwargs): + make_request('network', 'create', data=kwargs) diff --git a/uncloud_cli/commands/user.py b/uncloud_cli/commands/user.py index d8957be..9eb088b 100755 --- a/uncloud_cli/commands/user.py +++ b/uncloud_cli/commands/user.py @@ -1,9 +1,5 @@ -from uncloud_cli.commands.helper import OTPCredentials, load_dump_pretty -from uncloud_cli.config import env_vars -from os.path import join as join_path - import click -import requests +from uncloud_cli.commands.helper import add_otp_options, make_request @click.group() @@ -12,79 +8,40 @@ def user(): @user.command("files") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -def list_files(name, realm, seed): - data = OTPCredentials(name, realm, seed).get_json() - r = requests.get( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "files"), json=data - ) - print(load_dump_pretty(r.content)) +@add_otp_options +def list_files(**kwargs): + make_request('user', 'files', data=kwargs) @user.command("vms") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -def list_vms(name, realm, seed): - data = OTPCredentials(name, realm, seed).get_json() - r = requests.get( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "vms"), json=data - ) - print(load_dump_pretty(r.content)) +@add_otp_options +def list_vms(**kwargs): + make_request('user', 'vms', data=kwargs) @user.command("networks") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -def list_networks(name, realm, seed): - data = OTPCredentials(name, realm, seed).get_json() - r = requests.get( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "networks"), json=data - ) - print(load_dump_pretty(r.content)) +@add_otp_options +def list_networks(**kwargs): + make_request('user', 'network', data=kwargs) @user.command("add-ssh") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) +@add_otp_options @click.option("--key-name", required=True) @click.option("--key", required=True) -def add_ssh(name, realm, seed, key_name, key): - otp = OTPCredentials(name, realm, seed) - data = {**otp.get_json(), "key_name": key_name, "key": key} - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "add-ssh"), json=data - ) - print(load_dump_pretty(r.content)) +def add_ssh(**kwargs): + make_request('user', 'add-ssh', data=kwargs) @user.command("remove-ssh") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) +@add_otp_options @click.option("--key-name", required=True) -def remove_ssh(name, realm, seed, key_name): - otp = OTPCredentials(name, realm, seed) - data = {**otp.get_json(), "key_name": key_name} - r = requests.get( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "remove-ssh"), json=data - ) - print(load_dump_pretty(r.content)) +def remove_ssh(**kwargs): + make_request('user', 'remove-ssh', data=kwargs) @user.command("get-ssh") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) +@add_otp_options @click.option("--key-name", default="") -def get_ssh(name, realm, seed, key_name): - otp = OTPCredentials(name, realm, seed) - data = {**otp.get_json(), "key_name": key_name} - r = requests.get( - join_path(env_vars.get("UCLOUD_API_SERVER"), "user", "get-ssh"), json=data - ) - print(load_dump_pretty(r.content)) +def get_ssh(**kwargs): + make_request('user', 'get-ssh', data=kwargs) diff --git a/uncloud_cli/commands/vm.py b/uncloud_cli/commands/vm.py index 3c5c90c..b3d7a08 100755 --- a/uncloud_cli/commands/vm.py +++ b/uncloud_cli/commands/vm.py @@ -1,19 +1,7 @@ import click -import json import requests -import subprocess as sp -from uncloud_cli.commands.helper import OTPCredentials, load_dump_pretty -from uncloud_cli.config import env_vars -from os.path import join as join_path - - -def vm_command(command, otp, vm_name, **kwargs): - data = {**otp.get_json(), "vm_name": vm_name, "action": command, **kwargs} - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "vm", "action"), json=data - ) - return r +from uncloud_cli.commands.helper import add_otp_options, make_request, add_vm_options @click.group() @@ -21,121 +9,56 @@ def vm(): pass -@vm.command("create") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--cpu", required=True, type=int) -@click.option("--ram", required=True) -@click.option("--os-ssd", required=True) -@click.option("--hdd", default=list(), multiple=True) -@click.option("--image", required=True) -@click.option("--network", default=list(), multiple=True) -def create(name, realm, seed, vm_name, cpu, ram, os_ssd, hdd, image, network): - data = { - **OTPCredentials(name, realm, seed).get_json(), - "vm_name": vm_name, - "specs": {"cpu": cpu, "ram": ram, "os-ssd": os_ssd, "hdd": hdd}, - "network": network, - "image": image, +@vm.command('create') +@add_otp_options +@add_vm_options +@click.option('--cpu', required=True, type=int) +@click.option('--ram', required=True) +@click.option('--os-ssd', required=True) +@click.option('--hdd', default=list(), multiple=True) +@click.option('--image', required=True) +@click.option('--network', default=list(), multiple=True) +def create(**kwargs): + kwargs['specs'] = { + 'cpu': kwargs.pop('cpu'), + 'ram': kwargs.pop('ram'), + 'os-ssd': kwargs.pop('os_ssd'), + 'hdd': kwargs.pop('hdd') } - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "vm", "create"), json=data - ) - print(load_dump_pretty(r.content)) + make_request('vm', kwargs.pop('action'), data=kwargs) -@vm.command("start") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--in_support_of") -def start(name, realm, seed, vm_name, in_support_of): - r = vm_command( - "start", OTPCredentials(name, realm, seed), vm_name, in_support_of=in_support_of - ) - print(load_dump_pretty(r.content)) +@vm.command('start') +@add_otp_options +@add_vm_options +def start(**kwargs): + make_request('vm', 'action', data=kwargs) -@vm.command("stop") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--in_support_of") -def stop(name, realm, seed, vm_name, in_support_of): - r = vm_command( - "stop", OTPCredentials(name, realm, seed), vm_name, in_support_of=in_support_of - ) - print(load_dump_pretty(r.content)) +@vm.command('stop') +@add_otp_options +@add_vm_options +def stop(**kwargs): + make_request('vm', 'action', data=kwargs) -@vm.command("delete") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--in_support_of") -def delete(name, realm, seed, vm_name, in_support_of): - r = vm_command( - "delete", - OTPCredentials(name, realm, seed), - vm_name, - in_support_of=in_support_of, - ) - print(load_dump_pretty(r.content)) +@vm.command('delete') +@add_otp_options +@add_vm_options +def delete(**kwargs): + make_request('vm', 'action', data=kwargs) -@vm.command("status") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--in_support_of") -def status(name, realm, seed, vm_name, in_support_of): - otp = OTPCredentials(name, realm, seed) - data = {**otp.get_json(), "vm_name": vm_name, "in_support_of": in_support_of} - r = requests.get(join_path(env_vars.get("UCLOUD_API_SERVER"), "vm", "status"), json=data) - print(load_dump_pretty(r.content)) +@vm.command('status') +@add_otp_options +@click.option('--vm-name', required=True) +def status(**kwargs): + make_request('vm', 'status', data=kwargs) @vm.command("migrate") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) +@add_otp_options @click.option("--vm-name", required=True) @click.option("--destination", required=True) -@click.option("--in_support_of") -def vm_migration(name, realm, seed, vm_name, destination, in_support_of): - otp = OTPCredentials(name, realm, seed) - data = { - **otp.get_json(), - "vm_name": vm_name, - "destination": destination, - "in_support_of": in_support_of, - } - r = requests.post( - join_path(env_vars.get("UCLOUD_API_SERVER"), "vm", "migrate"), json=data - ) - print(load_dump_pretty(r.content)) - - -@vm.command("ssh") -@click.option("--name", required=True, default=env_vars.get("OTP_NAME")) -@click.option("--realm", required=True, default=env_vars.get("OTP_REALM")) -@click.option("--seed", required=True, default=env_vars.get("OTP_SEED")) -@click.option("--vm-name", required=True) -@click.option("--in_support_of") -def ssh(name, realm, seed, vm_name, in_support_of): - otp = OTPCredentials(name, realm, seed) - data = {**otp.get_json(), "vm_name": vm_name, "in_support_of": in_support_of} - r = requests.get(join_path(env_vars.get("UCLOUD_API_SERVER"), "vm", "status"), json=data) - try: - _json = json.loads(r.content) - sp.run(['ssh', '-o', 'ConnectTimeout=10', - 'root@{}'.format(_json['ip'][0])]) - except Exception as err: - print("Some error occurred while accessing VM." - "Make sure VM is running", err) +def vm_migration(**kwargs): + make_request('vm', 'migrate', data=kwargs) diff --git a/uncloud_cli/config.py b/uncloud_cli/config.py index 45343d8..9af3ba9 100644 --- a/uncloud_cli/config.py +++ b/uncloud_cli/config.py @@ -1,9 +1,10 @@ import sys -from os.path import expanduser -from decouple import Config, RepositoryEnv +import configparser +import os +config_file = os.path.expanduser('~/uncloud/uncloud.conf') try: - env_vars = Config(RepositoryEnv(expanduser("~/uncloud/uncloud-cli.conf"))) + config = configparser.ConfigParser() + config.read(config_file) except Exception as err: - print(err) - sys.exit(1) \ No newline at end of file + sys.exit(err) diff --git a/uncloud_cli/helper.py b/uncloud_cli/helper.py index e029945..f283eeb 100644 --- a/uncloud_cli/helper.py +++ b/uncloud_cli/helper.py @@ -1,5 +1,7 @@ import os import sys +import logging +import click def exception_handler(exception_type, exception, traceback): @@ -7,3 +9,25 @@ def exception_handler(exception_type, exception, traceback): sys.__excepthook__(exception_type, exception, traceback) else: print("%s: %s" % (exception_type.__name__, exception)) + + +class NoTracebackStreamHandler(logging.StreamHandler): + def handle(self, record): + info, cache = record.exc_info, record.exc_text + record.exc_info, record.exc_text = None, None + + if record.levelname in ["WARNING", "WARN"]: + click.echo(click.style('', fg='yellow', bold=True, reset=False), nl=False) + elif record.levelname == "ERROR": + click.echo(click.style('', fg='red', bold=True, reset=False), nl=False) + elif record.levelname == "INFO": + click.echo(click.style('', fg='green', bold=True, reset=False), nl=False) + elif record.levelname == "CRITICAL": + click.echo(click.style('', fg='cyan', bold=True, reset=False), nl=False) + + try: + super().handle(record) + finally: + record.exc_info = info + record.exc_text = cache + click.echo(click.style('', 'reset'), nl=False) From 436cb881b2d29ed10042a6ad797cc3430ac1c129 Mon Sep 17 00:00:00 2001 From: meow Date: Tue, 31 Dec 2019 20:18:14 +0500 Subject: [PATCH 2/2] refactoring --- bin/uncloud-cli | 26 +------------------------- setup.py | 2 +- uncloud_cli/commands/helper.py | 24 ++++++++++++++---------- uncloud_cli/commands/image.py | 12 ++++++------ uncloud_cli/commands/network.py | 8 ++++---- uncloud_cli/commands/user.py | 20 ++++++++++---------- uncloud_cli/commands/vm.py | 7 +++---- uncloud_cli/helper.py | 33 --------------------------------- 8 files changed, 39 insertions(+), 93 deletions(-) delete mode 100644 uncloud_cli/helper.py diff --git a/bin/uncloud-cli b/bin/uncloud-cli index a02d9fd..5d7c4b0 100755 --- a/bin/uncloud-cli +++ b/bin/uncloud-cli @@ -1,17 +1,12 @@ #!/usr/bin/env python3 import click -import sys -import logging - -from logging.handlers import SysLogHandler from uncloud_cli.commands.vm import vm from uncloud_cli.commands.user import user from uncloud_cli.commands.host import host from uncloud_cli.commands.image import image from uncloud_cli.commands.network import network -from uncloud_cli.helper import exception_handler, NoTracebackStreamHandler @click.group() @@ -19,26 +14,7 @@ def entry_point(): pass -if __name__ == "__main__": - sys.excepthook = exception_handler - - # Setting up root logger - logger = logging.getLogger() - logger.setLevel(logging.DEBUG) - - syslog_handler = SysLogHandler(address='/dev/log') - syslog_handler.setLevel(logging.DEBUG) - syslog_formatter = logging.Formatter('%(pathname)s:%(lineno)d -- %(levelname)-8s %(message)s') - syslog_handler.setFormatter(syslog_formatter) - - stream_handler = NoTracebackStreamHandler() - stream_handler.setLevel(logging.INFO) - stream_formatter = logging.Formatter('%(message)s') - stream_handler.setFormatter(stream_formatter) - - logger.addHandler(syslog_handler) - logger.addHandler(stream_handler) - +if __name__ == '__main__': entry_point.add_command(vm) entry_point.add_command(user) entry_point.add_command(image) diff --git a/setup.py b/setup.py index 7c20e4e..ee40e77 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -with open("README.md", "r") as fh: +with open('README.md', 'r') as fh: long_description = fh.read() setup(name='uncloud_cli', diff --git a/uncloud_cli/commands/helper.py b/uncloud_cli/commands/helper.py index 1b2f341..c7661c9 100755 --- a/uncloud_cli/commands/helper.py +++ b/uncloud_cli/commands/helper.py @@ -11,16 +11,19 @@ from uncloud_cli.config import config, config_file def load_dump_pretty(content): if isinstance(content, bytes): - content = content.decode("utf-8") + content = content.decode('utf-8') parsed = json.loads(content) return json.dumps(parsed, indent=4, sort_keys=True) def make_request(*args, data=None, request_method=requests.post): r = request_method( - join_path(config['client']['api_server'], *args), json=data + join_path(config.get('client', 'api_server'), *args), json=data ) - print(load_dump_pretty(r.content)) + try: + print(load_dump_pretty(r.content)) + except Exception: + print('Error occurred while getting output from api server.') def get_token(ctx, param, value): @@ -28,7 +31,7 @@ def get_token(ctx, param, value): try: token = TOTP(value).now() except binascii.Error: - raise click.BadParameter('Please enter the correct seed in {}'.format(config_file)) + raise click.BadParameter('') else: param.name = 'token' return token @@ -37,16 +40,17 @@ def get_token(ctx, param, value): def add_otp_options(f): options = [ click.option( - "--name", required=True, default=config['client']['name'], - show_default='name mentioned in {}'.format(config_file) + '--name', required=True, default=config.get('client', 'name', fallback=''), + show_default='name mentioned in {}'.format(config_file), prompt=True ), click.option( - "--realm", required=True, default=config['client']['realm'], - show_default='realm mentioned in {}'.format(config_file) + '--realm', required=True, default=config.get('client', 'realm', fallback=''), + show_default='realm mentioned in {}'.format(config_file), prompt=True ), click.option( - "--seed", required=True, default=config['client']['seed'], - callback=get_token, show_default='seed mentioned in {}'.format(config_file) + '--seed', required=True, default=config.get('client', 'seed', fallback=''), + callback=get_token, prompt=True, + show_default='seed mentioned in {}'.format(config_file) ) ] diff --git a/uncloud_cli/commands/image.py b/uncloud_cli/commands/image.py index 2f54a53..916d276 100755 --- a/uncloud_cli/commands/image.py +++ b/uncloud_cli/commands/image.py @@ -9,16 +9,16 @@ def image(): pass -@image.command("list") -@click.option("--public", is_flag=True) +@image.command('list') +@click.option('--public', is_flag=True) def _list(public): if public: make_request('image', 'list-public', request_method=requests.get) -@image.command("create-from-file") -@click.option("--name", required=True) -@click.option("--uuid", required=True) -@click.option("--image-store-name", 'image_store', required=True) +@image.command('create-from-file') +@click.option('--name', required=True) +@click.option('--uuid', required=True) +@click.option('--image-store-name', 'image_store', required=True) def create_from_file(**kwargs): make_request('image', 'create', data=kwargs) diff --git a/uncloud_cli/commands/network.py b/uncloud_cli/commands/network.py index 176beda..978ec75 100644 --- a/uncloud_cli/commands/network.py +++ b/uncloud_cli/commands/network.py @@ -9,10 +9,10 @@ def network(): pass -@network.command("create") +@network.command('create') @add_otp_options -@click.option("--network-name", required=True) -@click.option("--network-type", 'type', required=True) -@click.option("--user", required=True, type=bool, default=False) +@click.option('--network-name', required=True) +@click.option('--network-type', 'type', required=True) +@click.option('--user', required=True, type=bool, default=False) def create(**kwargs): make_request('network', 'create', data=kwargs) diff --git a/uncloud_cli/commands/user.py b/uncloud_cli/commands/user.py index 9eb088b..fbfdee2 100755 --- a/uncloud_cli/commands/user.py +++ b/uncloud_cli/commands/user.py @@ -7,41 +7,41 @@ def user(): pass -@user.command("files") +@user.command('files') @add_otp_options def list_files(**kwargs): make_request('user', 'files', data=kwargs) -@user.command("vms") +@user.command('vms') @add_otp_options def list_vms(**kwargs): make_request('user', 'vms', data=kwargs) -@user.command("networks") +@user.command('networks') @add_otp_options def list_networks(**kwargs): make_request('user', 'network', data=kwargs) -@user.command("add-ssh") +@user.command('add-ssh') @add_otp_options -@click.option("--key-name", required=True) -@click.option("--key", required=True) +@click.option('--key-name', required=True) +@click.option('--key', required=True) def add_ssh(**kwargs): make_request('user', 'add-ssh', data=kwargs) -@user.command("remove-ssh") +@user.command('remove-ssh') @add_otp_options -@click.option("--key-name", required=True) +@click.option('--key-name', required=True) def remove_ssh(**kwargs): make_request('user', 'remove-ssh', data=kwargs) -@user.command("get-ssh") +@user.command('get-ssh') @add_otp_options -@click.option("--key-name", default="") +@click.option('--key-name', default='') def get_ssh(**kwargs): make_request('user', 'get-ssh', data=kwargs) diff --git a/uncloud_cli/commands/vm.py b/uncloud_cli/commands/vm.py index b3d7a08..c8616b2 100755 --- a/uncloud_cli/commands/vm.py +++ b/uncloud_cli/commands/vm.py @@ -1,5 +1,4 @@ import click -import requests from uncloud_cli.commands.helper import add_otp_options, make_request, add_vm_options @@ -56,9 +55,9 @@ def status(**kwargs): make_request('vm', 'status', data=kwargs) -@vm.command("migrate") +@vm.command('migrate') @add_otp_options -@click.option("--vm-name", required=True) -@click.option("--destination", required=True) +@click.option('--vm-name', required=True) +@click.option('--destination', required=True) def vm_migration(**kwargs): make_request('vm', 'migrate', data=kwargs) diff --git a/uncloud_cli/helper.py b/uncloud_cli/helper.py deleted file mode 100644 index f283eeb..0000000 --- a/uncloud_cli/helper.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import sys -import logging -import click - - -def exception_handler(exception_type, exception, traceback): - if bool(os.getenv('DEBUG_UCLOUD')) is True: - sys.__excepthook__(exception_type, exception, traceback) - else: - print("%s: %s" % (exception_type.__name__, exception)) - - -class NoTracebackStreamHandler(logging.StreamHandler): - def handle(self, record): - info, cache = record.exc_info, record.exc_text - record.exc_info, record.exc_text = None, None - - if record.levelname in ["WARNING", "WARN"]: - click.echo(click.style('', fg='yellow', bold=True, reset=False), nl=False) - elif record.levelname == "ERROR": - click.echo(click.style('', fg='red', bold=True, reset=False), nl=False) - elif record.levelname == "INFO": - click.echo(click.style('', fg='green', bold=True, reset=False), nl=False) - elif record.levelname == "CRITICAL": - click.echo(click.style('', fg='cyan', bold=True, reset=False), nl=False) - - try: - super().handle(record) - finally: - record.exc_info = info - record.exc_text = cache - click.echo(click.style('', 'reset'), nl=False)