# Copyright (c) 2014 Rackspace # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import json import os from oslo_log import log as logging from solumclient import client as solum_client from solumclient.common import cliutils from solumclient.common import exc class CommandsBase(object): """Base command parsing class.""" parser = None solum = None json_output = False verify = True def __init__(self, parser): self.parser = parser self._get_global_flags() try: self._get_auth_flags() except exc.CommandError as ce: print(self.__doc__) print("ERROR: %s" % ce.message) return self.parser.add_argument('action', default='help', help='Action to perform on resource') parsed, _ = self.parser.parse_known_args() action = vars(parsed).get('action') client_args = vars(parsed) client_args.pop('insecure', None) client_args['verify'] = self.verify if 'os_auth_token' in client_args: del client_args['os_auth_token'] self.client = solum_client.get_client(parsed.solum_api_version, **client_args) if action in self._actions: try: return self._actions[action]() except exc.CommandError as ce: print("ERROR: %s" % ce.message) else: print(self.__doc__) def _get_auth_flags(self): self.parser.add_argument('--os-username', default=env('OS_USERNAME'), help='Defaults to env[OS_USERNAME]') self.parser.add_argument('--os-password', default=env('OS_PASSWORD'), help='Defaults to env[OS_PASSWORD]') self.parser.add_argument('--os-tenant-name', default=env('OS_TENANT_NAME'), help='Defaults to env[OS_TENANT_NAME]') self.parser.add_argument('--os-tenant-id', default=env('OS_TENANT_ID'), help='Defaults to env[OS_TENANT_ID]') self.parser.add_argument('--os-project-name', default=env('OS_PROJECT_NAME'), help='Defaults to env[OS_PROJECT_NAME]') self.parser.add_argument('--os-project-id', default=env('OS_PROJECT_ID'), help='Defaults to env[OS_PROJECT_ID]') self.parser.add_argument('--os-project-domain-name', default=env('OS_PROJECT_DOMAIN_NAME'), help='Defaults to ' 'env[OS_PROJECT_DOMAIN_NAME]') self.parser.add_argument('--os-project-domain-id', default=env('OS_PROJECT_DOMAIN_ID'), help='Defaults to ' 'env[OS_PROJECT_DOMAIN_NAME]') self.parser.add_argument('--os-user-domain-name', default=env('OS_USER_DOMAIN_NAME'), help='Defaults to env[OS_USER_DOMAIN_NAME]') self.parser.add_argument('--os-user-domain-id', default=env('OS_USER_DOMAIN_ID'), help='Defaults to env[OS_USER_DOMAIN_NAME]') self.parser.add_argument('--os-region-name', default=env('OS_REGION_NAME'), help='Defaults to env[OS_REGION_NAME]') self.parser.add_argument('--os-auth-url', default=env('OS_AUTH_URL'), help='Defaults to env[OS_AUTH_URL]') self.parser.add_argument('--os-auth-token', default=env('OS_AUTH_TOKEN'), help='Defaults to env[OS_AUTH_TOKEN]') self.parser.add_argument('--solum-url', default=env('SOLUM_URL'), help='Defaults to env[SOLUM_URL]') api_version = env('SOLUM_API_VERSION', default='1') self.parser.add_argument('--solum-api-version', default=api_version, help='Defaults to env[SOLUM_API_VERSION] ' 'or 1') parsed, _ = self.parser.parse_known_args() client_args = vars(parsed) if not parsed.os_auth_token: # Remove arguments that are not to be passed to the client in this # case. del client_args['os_auth_token'] if not parsed.os_username: raise exc.CommandError("You must provide a username via " "either --os-username or via " "env[OS_USERNAME]") if not parsed.os_password: raise exc.CommandError("You must provide a password via " "either --os-password or via " "env[OS_PASSWORD]") if not (parsed.os_tenant_name or parsed.os_project_name): raise exc.CommandError("You must provide a tenant_name via " "either --os-tenant-name or via " "env[OS_TENANT_NAME]") if not parsed.os_auth_url: raise exc.CommandError("You must provide an auth url via " "either --os-auth-url or via " "env[OS_AUTH_URL]") @property def _actions(self): """Action handler.""" return dict((attr, getattr(self, attr)) for attr in dir(self) if not attr.startswith('_') and callable(getattr(self, attr))) def _get_global_flags(self): """Get global flags.""" # Good location to add_argument() global options like --verbose self.parser.add_argument('--json', action='store_true', help='JSON formatted output') self.parser.add_argument('-k', '--insecure', action='store_true', help='Explicitly allow the client to perform' ' \"insecure SSL\" (https) requests.' ' The server\'s certificate will not be' ' verified against any certificate' ' authorities. This option should be' ' used with caution.') self.parser.add_argument('-d', '--debug', action='store_true', help='Print out request and response ' 'details.') args, _ = self.parser.parse_known_args() if args.json: self.json_output = True if args.insecure: self.verify = False if args.debug: logging.basicConfig( format="%(levelname)s (%(module)s) %(message)s", level=logging.DEBUG) logging.getLogger('iso8601').setLevel(logging.WARNING) urllibpool = 'urllib3.connectionpool' logging.getLogger(urllibpool).setLevel(logging.WARNING) def _sanitized_fields(self, fields): def allowed(field): if field.startswith('_'): return False if field == 'manager': return False if field == 'artifacts': return False return True return [f for f in fields if allowed(f)] def _print_dict(self, obj, fields, dict_property="Property", wrap=0): fields = self._sanitized_fields(fields) try: # datsun180b: I have no idea why, but following a PATCH # app resources need to have this evaluated once or else # the subset assignment below fails. obj.attrs except TypeError: pass except AttributeError: pass subset = dict([(f, getattr(obj, f, '')) for f in fields]) if self.json_output: print(json.dumps(subset, indent=2, sort_keys=True)) else: cliutils.print_dict(subset, dict_property, wrap) def _print_list(self, objs, fields, formatters=None, sortby_index=0, mixed_case_fields=None, field_labels=None): fields = self._sanitized_fields(fields) if self.json_output: subsets = [dict([(f, getattr(obj, f, '')) for f in fields]) for obj in objs] print(json.dumps(subsets, indent=2, sort_keys=True)) else: cliutils.print_list(objs, fields, formatters, sortby_index, mixed_case_fields, field_labels) class NoSubCommands(CommandsBase): """Command parsing class that lacks an 'action'.""" parser = None solum = None json_output = False verify = True def __init__(self, parser): self.parser = parser self._get_global_flags() try: self._get_auth_flags() except exc.CommandError as ce: print(self.__doc__) print("ERROR: %s" % ce.message) return parsed, _ = self.parser.parse_known_args() client_args = vars(parsed) client_args.pop('insecure', None) client_args['verify'] = self.verify if 'os_auth_token' in client_args: del client_args['os_auth_token'] self.client = solum_client.get_client(parsed.solum_api_version, **client_args) return self.info() def info(self): pass def env(*vars, **kwargs): """Search for the first defined of possibly many env vars Returns the first environment variable defined in vars, or returns the default defined in kwargs. """ for v in vars: value = os.environ.get(v, None) if value: return value return kwargs.get('default', '') def filter_ready_lps(lp_list): filtered_list = [] for lp in lp_list: if lp.status == 'READY': filtered_list.append(lp) return filtered_list