diff --git a/cloudscale/__init__.py b/cloudscale/__init__.py index e7a2840..b182591 100644 --- a/cloudscale/__init__.py +++ b/cloudscale/__init__.py @@ -1,6 +1,7 @@ import os import configparser from .client import RestAPI +from .log import logger from .lib.server import Server from .lib.server_group import ServerGroup from .lib.volume import Volume @@ -23,7 +24,7 @@ class Cloudscale: - def __init__(self, api_token=None, profile=None, verbose=False): + def __init__(self, api_token=None, profile=None): if api_token and profile: raise CloudscaleException("API token and profile are mutually exclusive") @@ -36,13 +37,15 @@ def __init__(self, api_token=None, profile=None, verbose=False): else: self.api_token = self.config.get('api_token') + if not self.api_token: + raise CloudscaleException("Missing API key") + + logger.debug("API token: {}...".format(self.api_token[:4])) + # Configre requests timeout self.timeout = self.config.get('timeout', 60) + logger.debug("Timeout: {}".format(self.timeout)) - if not self.api_token: - raise CloudscaleException("Missing API key: see -h for help") - - self.verbose = verbose self.service_classes = { 'server': Server, 'server_group': ServerGroup, @@ -75,6 +78,8 @@ def _read_from_configfile(self, profile=None): else: profile = os.getenv('CLOUDSCALE_PROFILE', 'default') + logger.info("Profile: {}".format(profile)) + if not conf._sections.get(profile): return dict() @@ -91,7 +96,6 @@ def __getattr__(self, name): ) obj = self.service_classes[name]() obj._client = client - obj.verbose = self.verbose return obj except NameError as e: raise CloudscaleException(e) diff --git a/cloudscale/cli.py b/cloudscale/cli.py index ce47004..97e006a 100644 --- a/cloudscale/cli.py +++ b/cloudscale/cli.py @@ -1,4 +1,6 @@ import click +import click_log +from .log import logger from click_repl import register_repl from .util import OrderedGroup from .commands.version import cmd_version @@ -13,10 +15,12 @@ from .commands.volume import volume from .commands.objects_user import objects_user +click_log.basic_config(logger) @click.group(cls=OrderedGroup, context_settings={ 'help_option_names': ['-h', '--help'], }) +@click_log.simple_verbosity_option(logger) def cli(): pass diff --git a/cloudscale/client.py b/cloudscale/client.py index 0e2f1ab..ea2f17b 100644 --- a/cloudscale/client.py +++ b/cloudscale/client.py @@ -1,5 +1,6 @@ import requests from urllib.parse import urlencode +from .log import logger class RestAPI: @@ -51,6 +52,7 @@ def get_resources(self, resource, payload=None, resource_id=None): query_url = query_url + '?' + data + logger.debug("HTTP GET: {}".format(query_url)) r = requests.get(query_url, headers=self.headers, timeout=self.timeout) return self._return_result(r) @@ -58,22 +60,24 @@ def post_patch_resource(self, resource, payload=None, resource_id=None, action=N data = self._handle_payload(payload) query_url = self.endpoint + '/' + resource - if not resource_id: + logger.debug("HTTP POST URL {}, data {}".format(query_url, data)) r = requests.post(query_url, json=data, headers=self.headers, timeout=self.timeout) return self._return_result(r) - query_url += '/' + resource_id if action: query_url += '/' + action + logger.debug("HTTP POSTst URL {}, data {}".format(query_url, data)) r = requests.post(query_url, json=data, headers=self.headers, timeout=self.timeout) return self._return_result(r) else: + logger.debug("HTTP POST URL {}, data {}".format(query_url, data)) r = requests.patch(query_url, json=data, headers=self.headers, timeout=self.timeout) return self._return_result(r) def delete_resource(self, resource, resource_id): query_url = self.endpoint + '/' + resource + '/' + resource_id + logger.debug("HTTP DELETE: {}".format(query_url)) r = requests.delete(query_url, headers=self.headers, timeout=self.timeout) return self._return_result(r) diff --git a/cloudscale/commands/flavor.py b/cloudscale/commands/flavor.py index 5316477..e8fb515 100644 --- a/cloudscale/commands/flavor.py +++ b/cloudscale/commands/flavor.py @@ -1,18 +1,18 @@ import sys import click +from ..log import logger from ..util import to_table from .. import Cloudscale, CloudscaleException, CloudscaleApiException @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def flavor(ctx, profile, api_token, verbose): +def flavor(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @flavor.command("list") @@ -25,5 +25,5 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/floating_ip.py b/cloudscale/commands/floating_ip.py index 9320df1..5f8da63 100644 --- a/cloudscale/commands/floating_ip.py +++ b/cloudscale/commands/floating_ip.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def floating_ip(ctx, profile, api_token, verbose): +def floating_ip(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @floating_ip.command("list") @@ -26,7 +26,7 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--network-id', 'uuid', required=True) @@ -37,7 +37,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.floating_ip.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--ip-version', type=int, default=4, show_default=True) @@ -62,7 +62,7 @@ def cmd_create(cloudscale, ip_version, server_uuid, prefix_length, reverse_ptr, ) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--network-id', 'uuid', required=True) @@ -82,7 +82,7 @@ def cmd_update(cloudscale, uuid, server_uuid, reverse_ptr, tags): response = cloudscale.floating_ip.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--network-id', 'uuid', required=True) @@ -96,5 +96,5 @@ def cmd_delete(cloudscale, uuid): cloudscale.floating_ip.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/image.py b/cloudscale/commands/image.py index d4fb8a9..a7010a8 100644 --- a/cloudscale/commands/image.py +++ b/cloudscale/commands/image.py @@ -1,18 +1,18 @@ import sys import click +from ..log import logger from ..util import to_table from .. import Cloudscale, CloudscaleApiException, CloudscaleException @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def image(ctx, profile, api_token, verbose): +def image(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @image.command("list") @@ -25,5 +25,5 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/network.py b/cloudscale/commands/network.py index c80c7cf..0833115 100644 --- a/cloudscale/commands/network.py +++ b/cloudscale/commands/network.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def network(ctx, profile, api_token, verbose): +def network(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @network.command("list") @@ -26,7 +26,7 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -37,7 +37,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.network.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--name', required=True) @@ -58,7 +58,7 @@ def cmd_create(cloudscale, name, zone, mtu, auto_create_ipv4_subnet, tags): ) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -78,7 +78,7 @@ def cmd_update(cloudscale, uuid, name, mtu, tags): response = cloudscale.network.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -92,5 +92,5 @@ def cmd_delete(cloudscale, uuid): cloudscale.network.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/objects_user.py b/cloudscale/commands/objects_user.py index ba48d83..bed3b72 100644 --- a/cloudscale/commands/objects_user.py +++ b/cloudscale/commands/objects_user.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def objects_user(ctx, profile, api_token, verbose): +def objects_user(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--filter-tag') @@ -27,7 +27,7 @@ def cmd_list(cloudscale, filter_tag): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--id', '--uuid', 'uuid', required=True) @@ -38,7 +38,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.objects_user.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--display-name', required=True) @@ -50,7 +50,7 @@ def cmd_create(cloudscale, display_name, tags): response = cloudscale.objects_user.create(display_name, to_dict(tags)) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--id', '--uuid', 'uuid', required=True) @@ -64,7 +64,7 @@ def cmd_update(cloudscale, uuid, display_name, tags): response = cloudscale.objects_user.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--id', '--uuid', 'uuid', required=True) @@ -78,5 +78,5 @@ def cmd_delete(cloudscale, uuid): cloudscale.objects_user.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/region.py b/cloudscale/commands/region.py index d64fcd1..001ebc1 100644 --- a/cloudscale/commands/region.py +++ b/cloudscale/commands/region.py @@ -1,18 +1,18 @@ import sys import click +from ..log import logger from ..util import to_table from .. import Cloudscale, CloudscaleApiException, CloudscaleException @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def region(ctx, profile, api_token, verbose): +def region(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @region.command("list") @@ -25,5 +25,5 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/server.py b/cloudscale/commands/server.py index 9fb2520..f1a1ac2 100644 --- a/cloudscale/commands/server.py +++ b/cloudscale/commands/server.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def server(ctx, profile, api_token, verbose): +def server(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--filter-tag') @@ -27,7 +27,7 @@ def cmd_list(cloudscale, filter_tag): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -38,7 +38,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.server.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--name', required=True) @@ -96,7 +96,7 @@ def cmd_create( ) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @@ -117,7 +117,7 @@ def cmd_update(cloudscale, uuid, name, flavor, tags): response = cloudscale.server.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -131,7 +131,7 @@ def cmd_delete(cloudscale, uuid): cloudscale.server.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -143,7 +143,7 @@ def cmd_start(cloudscale, uuid): response = cloudscale.server.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -155,7 +155,7 @@ def cmd_stop(cloudscale, uuid): response = cloudscale.server.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -167,5 +167,5 @@ def cmd_reboot(cloudscale, uuid): response = cloudscale.server.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/server_group.py b/cloudscale/commands/server_group.py index b10720a..77b6af1 100644 --- a/cloudscale/commands/server_group.py +++ b/cloudscale/commands/server_group.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def server_group(ctx, profile, api_token, verbose): +def server_group(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--filter-tag') @@ -27,7 +27,7 @@ def cmd_list(cloudscale, filter_tag): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -38,7 +38,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.server_group.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--name', required=True) @@ -51,7 +51,7 @@ def cmd_create(cloudscale, name, group_type, tags): response = cloudscale.server_group.create(name, group_type, to_dict(tags)) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -65,7 +65,7 @@ def cmd_update(cloudscale, uuid, name, tags): response = cloudscale.server_group.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -79,5 +79,5 @@ def cmd_delete(cloudscale, uuid): cloudscale.server_group.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/subnet.py b/cloudscale/commands/subnet.py index f94bd07..c7bf597 100644 --- a/cloudscale/commands/subnet.py +++ b/cloudscale/commands/subnet.py @@ -1,18 +1,18 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json from .. import Cloudscale, CloudscaleException, CloudscaleApiException @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', envvar='CLOUDSCALE_PROFILE', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def subnet(ctx, profile, api_token, verbose): +def subnet(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @subnet.command("list") @@ -25,7 +25,7 @@ def cmd_list(cloudscale): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -36,5 +36,5 @@ def cmd_show(cloudscale, uuid): response = cloudscale.subnet.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/commands/volume.py b/cloudscale/commands/volume.py index 9d1f1a6..8a14d88 100644 --- a/cloudscale/commands/volume.py +++ b/cloudscale/commands/volume.py @@ -1,5 +1,6 @@ import sys import click +from ..log import logger from ..util import to_table, to_pretty_json, to_dict from .. import Cloudscale, CloudscaleApiException, CloudscaleException from . import abort_if_false @@ -7,13 +8,12 @@ @click.group() @click.option('--api-token', '-a', envvar='CLOUDSCALE_API_TOKEN', help="API token.") @click.option('--profile', '-p', envvar='CLOUDSCALE_PROFILE', help="Profile used in config file.") -@click.option('--verbose', '-v', is_flag=True, help='Enables verbose mode.') @click.pass_context -def volume(ctx, profile, api_token, verbose): +def volume(ctx, profile, api_token): try: - ctx.obj = Cloudscale(api_token, profile, verbose) + ctx.obj = Cloudscale(api_token, profile) except CloudscaleException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--filter-tag') @@ -27,7 +27,7 @@ def cmd_list(cloudscale, filter_tag): table = to_table(response, headers) click.echo(table) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -38,7 +38,7 @@ def cmd_show(cloudscale, uuid): response = cloudscale.volume.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--name', required=True) @@ -61,7 +61,7 @@ def cmd_create(cloudscale, name, server_uuids, size_gb, volume_type, zone, tags) ) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -83,7 +83,7 @@ def cmd_update(cloudscale, uuid, name, server_uuids, size_gb, tags): response = cloudscale.volume.get_by_uuid(uuid) click.echo(to_pretty_json(response)) except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) @click.option('--uuid', required=True) @@ -97,5 +97,5 @@ def cmd_delete(cloudscale, uuid): cloudscale.volume.delete(uuid) click.echo("Deleted!") except CloudscaleApiException as e: - click.echo(e, err=True) + logger.error(e) sys.exit(1) diff --git a/cloudscale/lib/__init__.py b/cloudscale/lib/__init__.py index 7a15729..45ab384 100644 --- a/cloudscale/lib/__init__.py +++ b/cloudscale/lib/__init__.py @@ -1,13 +1,15 @@ from ..error import CloudscaleApiException +from ..log import logger class CloudscaleBase: def __init__(self): - self.verbose = False self._client = None self.resource = None def _process_response(self, response): + logger.debug("API respnose: {}".format(response)) + status_code = response.get('status_code') data = response.get('data', dict()) if status_code not in (200, 201, 204): @@ -23,6 +25,8 @@ def _process_response(self, response): def get_all(self, filter_tag=None): if filter_tag is not None: + logger.debug("Filter tag: {}".format(filter_tag)) + if '=' in filter_tag: tag_key, tag_value = filter_tag.split('=') else: diff --git a/cloudscale/log.py b/cloudscale/log.py new file mode 100644 index 0000000..78fe3ba --- /dev/null +++ b/cloudscale/log.py @@ -0,0 +1,5 @@ +import logging +import sys + +logger = logging.getLogger(__name__) +logger.setLevel(logging.ERROR) diff --git a/cloudscale/tests/test_server.py b/cloudscale/tests/test_server.py index 81a2113..826020c 100644 --- a/cloudscale/tests/test_server.py +++ b/cloudscale/tests/test_server.py @@ -236,7 +236,7 @@ def test_server_missing_api_key(): cloudscale = Cloudscale(api_token=None) cloudscale.server.get_all() except CloudscaleException as e: - assert str(e) == "Missing API key: see -h for help" + assert str(e) == "Missing API key" @responses.activate def test_server_create(): diff --git a/requirements.txt b/requirements.txt index 71af6a3..29d5208 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ requests click>=7.0.0 click-repl +click-log tabulate