def test(self): self.assertEqual( bundle_utils.short_id('45e0c477d3e5ea92aa8d85c0d8f3e25c'), '45e0c47') self.assertEqual( bundle_utils.short_id('c1ab77e63b722ef8c6ea8a1c274be053-3cc322b62e7608b5cdf37185240f7853'), 'c1ab77e-3cc322b')
def stop(args): """`conduct stop` command""" log = logging.getLogger(__name__) path = 'bundles/{}?scale=0'.format(args.bundle) url = conduct_url.url(path, args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.put(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) log.info('Bundle stop request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], 0, args) log.info('Unload bundle with: conduct unload{} {}'.format( args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format( args.cli_parameters)) return True
def get_acls_from_bundles(args, bundles): def is_started(bundle_executions): for execution in bundle_executions: if execution['isStarted']: return 'Running' return 'Starting' all_acls = [{ 'acl': acl, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': is_started(bundle['bundleExecutions']) } for bundle in bundles if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'acls' in endpoint for acl in endpoint['acls']] http_acls = [acl for acl in all_acls if 'http' in acl['acl']] tcp_acls = [acl for acl in all_acls if 'tcp' in acl['acl']] return all_acls, http_acls, tcp_acls
def stop(args): """`conduct stop` command""" log = logging.getLogger(__name__) path = 'bundles/{}?scale=0'.format(args.bundle) url = conduct_url.url(path, args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.put(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) log.info('Bundle stop request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], 0, args) log.info('Unload bundle with: conduct unload{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) return True
def stop(args): """`conduct stop` command""" log = logging.getLogger(__name__) path = "bundles/{}?scale=0".format(args.bundle) url = conduct_url.url(path, args) response = conduct_request.put( args.dcos_mode, conductr_host(args), url, auth=args.conductr_auth, verify=args.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, ) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json["bundleId"] if args.long_ids else bundle_utils.short_id(response_json["bundleId"]) log.info("Bundle stop request sent.") if not args.no_wait: bundle_scale.wait_for_scale(response_json["bundleId"], 0, args) if not args.disable_instructions: log.info("Unload bundle with: {} unload{} {}".format(args.command, args.cli_parameters, bundle_id)) log.info("Print ConductR info with: {} info{}".format(args.command, args.cli_parameters)) return True
def stop(args): """`conduct stop` command""" log = logging.getLogger(__name__) path = 'bundles/{}?scale=0'.format(args.bundle) url = conduct_url.url(path, args) response = conduct_request.put(args.dcos_mode, conductr_host(args), url, auth=args.conductr_auth, verify=args.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) log.info('Bundle stop request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], 0, args) if not args.disable_instructions: log.info('Unload bundle with: {} unload{} {}'.format( args.command, args.cli_parameters, bundle_id)) log.info('Print ConductR info with: {} info{}'.format( args.command, args.cli_parameters)) return True
def request_deploy_confirmation(resolved_version, args): bundle_id = resolved_version['digest'] if args.long_ids else bundle_utils.short_id(resolved_version['digest']) user_input = input('Deploy {}:{}-{}? [Y/n]: '.format(resolved_version['package_name'], resolved_version['compatibility_version'], bundle_id)) confirmation = (user_input if user_input else 'y').lower().strip() return confirmation == 'y' or confirmation == 'yes'
def services(args): """`conduct services` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = sorted([ ( { 'service': service, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id( bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': 'Running' if execution['isStarted'] else 'Starting' } ) for bundle in json.loads(response.text) for execution in bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'services' in endpoint for service in endpoint['services'] ], key=lambda line: line['service']) service_endpoints = {} for service in data: url = urlparse(service['service']) if not (url.path == '' or url.path == '/'): try: service_endpoints[url.path] |= {service['service']} except KeyError: service_endpoints[url.path] = {service['service']} duplicate_endpoints = [service for (service, endpoint) in service_endpoints.items() if len(endpoint) > 1] \ if len(service_endpoints) > 0 else [] data.insert(0, {'service': 'SERVICE', 'bundle_id': 'BUNDLE ID', 'bundle_name': 'BUNDLE NAME', 'status': 'STATUS'}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) for row in data: log.screen( '{service: <{service_width}}{padding}' '{bundle_id: <{bundle_id_width}}{padding}' '{bundle_name: <{bundle_name_width}}{padding}' '{status: <{status_width}}'.format(**dict(row, **column_widths)).rstrip()) if len(duplicate_endpoints) > 0: log.screen('') log.warning('Multiple endpoints found for the following services: {}'.format(', '.join(duplicate_endpoints))) log.warning('Service resolution for these services is undefined.') return True
def run(args): """`conduct run` command""" log = logging.getLogger(__name__) if args.affinity is not None and args.api_version == '1': log.error('Affinity feature is only available for v1.1 onwards of ConductR') return elif args.affinity is not None: path = 'bundles/{}?scale={}&affinity={}'.format(args.bundle, args.scale, args.affinity) else: path = 'bundles/{}?scale={}'.format(args.bundle, args.scale) url = conduct_url.url(path, args) response = requests.put(url) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) log.info('Bundle run request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], args.scale, args) log.info('Stop bundle with: conduct stop{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) return True
def request_deploy_confirmation(resolved_version, args): bundle_id = resolved_version[ 'digest'] if args.long_ids else bundle_utils.short_id( resolved_version['digest']) user_input = input('Deploy {}:{}-{}? [Y/n]: '.format( resolved_version['package_name'], resolved_version['tag'], bundle_id)) confirmation = (user_input if user_input else 'y').lower().strip() return confirmation == 'y' or confirmation == 'yes'
def acls(args): """`conduct acls` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) response = conduct_request.get(args.dcos_mode, conductr_host(args), url, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) def get_system_version(bundle): if 'systemVersion' in bundle['attributes']: return bundle['attributes']['systemVersion'] else: return bundle['attributes']['system'].split('-')[-1] def is_started(bundle_executions): for execution in bundle_executions: if execution['isStarted']: return 'Running' return 'Starting' all_acls = [{ 'acl': acl, 'system': bundle['attributes']['system'], 'system_version': get_system_version(bundle), 'endpoint_name': endpoint_name, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': is_started(bundle['bundleExecutions']) } for bundle in json.loads(response.text) if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig'] ['endpoints'].items() if 'acls' in endpoint for acl in endpoint['acls']] if args.protocol_family == 'http': http_acls = [acl for acl in all_acls if 'http' in acl['acl']] display_http_acls(log, http_acls) elif args.protocol_family == 'tcp': tcp_acls = [acl for acl in all_acls if 'tcp' in acl['acl']] display_tcp_acls(log, tcp_acls) return True
def services(args): """`conduct services` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = sorted([ ( { 'service': service, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id( bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': 'Running' if execution['isStarted'] else 'Starting' } ) for bundle in json.loads(response.text) for execution in bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() for service in endpoint['services'] ], key=lambda line: line['service']) service_endpoints = {} for service in data: url = urlparse(service['service']) if not (url.path == '' or url.path == '/'): try: service_endpoints[url.path] |= {service['service']} except KeyError: service_endpoints[url.path] = {service['service']} duplicate_endpoints = [service for (service, endpoint) in service_endpoints.items() if len(endpoint) > 1] \ if len(service_endpoints) > 0 else [] data.insert(0, {'service': 'SERVICE', 'bundle_id': 'BUNDLE ID', 'bundle_name': 'BUNDLE NAME', 'status': 'STATUS'}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) for row in data: log.screen( '{service: <{service_width}}{padding}' '{bundle_id: <{bundle_id_width}}{padding}' '{bundle_name: <{bundle_name_width}}{padding}' '{status: <{status_width}}'.format(**dict(row, **column_widths)).rstrip()) if len(duplicate_endpoints) > 0: log.screen('') log.warning('Multiple endpoints found for the following services: {}'.format(', '.join(duplicate_endpoints))) log.warning('Service resolution for these services is undefined.') return True
def acls(args): """`conduct acls` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) def get_system_version(bundle): if 'systemVersion' in bundle['attributes']: return bundle['attributes']['systemVersion'] else: return bundle['attributes']['system'].split('-')[-1] all_acls = [{ 'acl': acl, 'system': bundle['attributes']['system'], 'system_version': get_system_version(bundle), 'endpoint_name': endpoint_name, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': 'Running' if execution['isStarted'] else 'Starting' } for bundle in json.loads(response.text) for execution in bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'acls' in endpoint for acl in endpoint['acls']] if args.protocol_family == 'http': http_acls = [acl for acl in all_acls if 'http' in acl['acl']] display_http_acls(log, http_acls) elif args.protocol_family == 'tcp': tcp_acls = [acl for acl in all_acls if 'tcp' in acl['acl']] display_tcp_acls(log, tcp_acls) return True
def info(args): """`conduct info` command""" log = logging.getLogger(__name__) url = conduct_url.url("bundles", args) response = conduct_request.get( args.dcos_mode, conductr_host(args), url, auth=args.conductr_auth, verify=args.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, ) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = [ { "id": ("! " if bundle.get("hasError", False) else "") + (bundle["bundleId"] if args.long_ids else bundle_utils.short_id(bundle["bundleId"])), "name": bundle["attributes"]["bundleName"], "replications": len(bundle["bundleInstallations"]), "starting": sum([not execution["isStarted"] for execution in bundle["bundleExecutions"]]), "executions": sum([execution["isStarted"] for execution in bundle["bundleExecutions"]]), } for bundle in json.loads(response.text) ] data.insert(0, {"id": "ID", "name": "NAME", "replications": "#REP", "starting": "#STR", "executions": "#RUN"}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{"padding": " " * padding}) has_error = False for row in data: has_error |= "!" in row["id"] log.screen( """\ {id: <{id_width}}{padding}\ {name: <{name_width}}{padding}\ {replications: >{replications_width}}{padding}\ {starting: >{starting_width}}{padding}\ {executions: >{executions_width}}""".format( **dict(row, **column_widths) ).rstrip() ) if has_error: log.screen("There are errors: use `conduct events` or `conduct logs` for further information") return True
def load_v2(args): log = logging.getLogger(__name__) log.info('Retrieving bundle...') custom_settings = args.custom_settings resolve_cache_dir = args.resolve_cache_dir bundle_name, bundle_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.bundle) bundle_conf = bundle_utils.zip_entry('bundle.conf', bundle_file) if bundle_conf is None: raise MalformedBundleError('Unable to find bundle.conf within the bundle file') else: configuration_name, configuration_file, bundle_conf_overlay = (None, None, None) if args.configuration is not None: log.info('Retrieving configuration...') configuration_name, configuration_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.configuration) bundle_conf_overlay = bundle_utils.zip_entry('bundle.conf', configuration_file) files = [('bundleConf', ('bundle.conf', bundle_conf))] if bundle_conf_overlay is not None: files.append(('bundleConfOverlay', ('bundle.conf', bundle_conf_overlay))) files.append(('bundle', (bundle_name, open(bundle_file, 'rb')))) if configuration_file is not None: files.append(('configuration', (configuration_name, open(configuration_file, 'rb')))) url = conduct_url.url('bundles', args) log.info('Loading bundle to ConductR...') response = requests.post(url, files=files, timeout=LOAD_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) if not args.no_wait: bundle_installation.wait_for_installation(response_json['bundleId'], args) log.info('Bundle loaded.') log.info('Start bundle with: conduct run{} {}'.format(args.cli_parameters, bundle_id)) log.info('Unload bundle with: conduct unload{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) if not log.is_info_enabled() and log.is_quiet_enabled(): log.quiet(response_json['bundleId']) return True
def run(args): """`conduct run` command""" log = logging.getLogger(__name__) if args.affinity is not None and args.api_version == '1': log.error( 'Affinity feature is only available for v1.1 onwards of ConductR') return elif args.affinity is not None: path = 'bundles/{}?scale={}&affinity={}'.format( args.bundle, args.scale, args.affinity) else: path = 'bundles/{}?scale={}'.format(args.bundle, args.scale) url = conduct_url.url(path, args) response = conduct_request.put(args.dcos_mode, conductr_host(args), url, auth=args.conductr_auth, verify=args.server_verification_file) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) log.info('Bundle run request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], args.scale, wait_for_is_active=True, args=args) if not args.disable_instructions: log.info('Stop bundle with: {} stop{} {}'.format( args.command, args.cli_parameters, bundle_id)) log.info('Print ConductR info with: {} info{}'.format( args.command, args.cli_parameters)) log.info('Print bundle info with: {} info{} {}'.format( args.command, args.cli_parameters, bundle_id)) return True
def acls(args): """`conduct acls` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) response = conduct_request.get(args.dcos_mode, conductr_host(args), url, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) def get_system_version(bundle): if 'systemVersion' in bundle['attributes']: return bundle['attributes']['systemVersion'] else: return bundle['attributes']['system'].split('-')[-1] def is_started(bundle_executions): for execution in bundle_executions: if execution['isStarted']: return 'Running' return 'Starting' all_acls = [ { 'acl': acl, 'system': bundle['attributes']['system'], 'system_version': get_system_version(bundle), 'endpoint_name': endpoint_name, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': is_started(bundle['bundleExecutions']) } for bundle in json.loads(response.text) if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'acls' in endpoint for acl in endpoint['acls'] ] if args.protocol_family == 'http': http_acls = [acl for acl in all_acls if 'http' in acl['acl']] display_http_acls(log, http_acls) elif args.protocol_family == 'tcp': tcp_acls = [acl for acl in all_acls if 'tcp' in acl['acl']] display_tcp_acls(log, tcp_acls) return True
def acls(args): """`conduct acls` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) def get_system_version(bundle): if 'systemVersion' in bundle['attributes']: return bundle['attributes']['systemVersion'] else: return bundle['attributes']['system'].split('-')[-1] all_acls = [ { 'acl': acl, 'system': bundle['attributes']['system'], 'system_version': get_system_version(bundle), 'endpoint_name': endpoint_name, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': 'Running' if execution['isStarted'] else 'Starting' } for bundle in json.loads(response.text) for execution in bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'acls' in endpoint for acl in endpoint['acls'] ] if args.protocol_family == 'http': http_acls = [acl for acl in all_acls if 'http' in acl['acl']] display_http_acls(log, http_acls) elif args.protocol_family == 'tcp': tcp_acls = [acl for acl in all_acls if 'tcp' in acl['acl']] display_tcp_acls(log, tcp_acls) return True
def load_v1(args): log = logging.getLogger(__name__) log.info('Retrieving bundle...') custom_settings = args.custom_settings resolve_cache_dir = args.resolve_cache_dir bundle_name, bundle_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.bundle) configuration_name, configuration_file = (None, None) if args.configuration is not None: log.info('Retrieving configuration...') configuration_name, configuration_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.configuration) bundle_conf = ConfigFactory.parse_string(bundle_utils.conf(bundle_file)) overlay_bundle_conf = None if configuration_file is None else \ ConfigFactory.parse_string(bundle_utils.conf(configuration_file)) with_bundle_configurations = partial(apply_to_configurations, bundle_conf, overlay_bundle_conf) url = conduct_url.url('bundles', args) files = get_payload(bundle_name, bundle_file, with_bundle_configurations) if configuration_file is not None: files.append(('configuration', (configuration_name, open(configuration_file, 'rb')))) log.info('Loading bundle to ConductR...') response = requests.post(url, files=files, timeout=LOAD_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) if not args.no_wait: bundle_installation.wait_for_installation(response_json['bundleId'], args) log.info('Bundle loaded.') log.info('Start bundle with: conduct run{} {}'.format(args.cli_parameters, bundle_id)) log.info('Unload bundle with: conduct unload{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) if not log.is_info_enabled() and log.is_quiet_enabled(): log.quiet(response_json['bundleId']) return True
def stop(args): """`conduct stop` command""" path = "bundles/{}?scale=0".format(args.bundle) url = conduct_url.url(path, args) response = requests.put(url) conduct_logging.raise_for_status_inc_3xx(response) if args.verbose: conduct_logging.pretty_json(response.text) response_json = json.loads(response.text) bundle_id = response_json["bundleId"] if args.long_ids else bundle_utils.short_id(response_json["bundleId"]) print("Bundle stop request sent.") print("Unload bundle with: conduct unload{} {}".format(args.cli_parameters, bundle_id)) print("Print ConductR info with: conduct info{}".format(args.cli_parameters))
def run(args): """`conduct run` command""" path = 'bundles/{}?scale={}'.format(args.bundle, args.scale) url = conduct_url.url(path, args) response = requests.put(url) conduct_logging.raise_for_status_inc_3xx(response) if args.verbose: conduct_logging.pretty_json(response.text) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) print('Bundle run request sent.') print('Stop bundle with: conduct stop{} {}'.format(args.cli_parameters, bundle_id)) print('Print ConductR info with: conduct info{}'.format(args.cli_parameters))
def run(args): """`conduct run` command""" log = logging.getLogger(__name__) if args.affinity is not None and args.api_version == '1': log.error( 'Affinity feature is only available for v1.1 onwards of ConductR') return elif args.affinity is not None: path = 'bundles/{}?scale={}&affinity={}'.format( args.bundle, args.scale, args.affinity) else: path = 'bundles/{}?scale={}'.format(args.bundle, args.scale) url = conduct_url.url(path, args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.put(url, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) log.info('Bundle run request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], args.scale, args) log.info('Stop bundle with: conduct stop{} {}'.format( args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format( args.cli_parameters)) return True
def info(args): """`conduct info` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = [ { 'id': ('! ' if bundle.get('hasError', False) else '') + (bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId'])), 'name': bundle['attributes']['bundleName'], 'replications': len(bundle['bundleInstallations']), 'starting': sum([not execution['isStarted'] for execution in bundle['bundleExecutions']]), 'executions': sum([execution['isStarted'] for execution in bundle['bundleExecutions']]) } for bundle in json.loads(response.text) ] data.insert(0, {'id': 'ID', 'name': 'NAME', 'replications': '#REP', 'starting': '#STR', 'executions': '#RUN'}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) has_error = False for row in data: has_error |= '!' in row['id'] log.screen('''\ {id: <{id_width}}{padding}\ {name: <{name_width}}{padding}\ {replications: >{replications_width}}{padding}\ {starting: >{starting_width}}{padding}\ {executions: >{executions_width}}'''.format(**dict(row, **column_widths)).rstrip()) if has_error: log.screen('There are errors: use `conduct events` or `conduct logs` for further information') return True
def info(args): """`conduct info` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) response = conduct_request.get(args.dcos_mode, conductr_host(args), url, auth=args.conductr_auth, verify=args.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = [ { 'id': ('! ' if bundle.get('hasError', False) else '') + (bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId'])), 'name': bundle['attributes']['bundleName'], 'replications': len(bundle['bundleInstallations']), 'starting': sum([not execution['isStarted'] for execution in bundle['bundleExecutions']]), 'executions': sum([execution['isStarted'] for execution in bundle['bundleExecutions']]) } for bundle in json.loads(response.text) ] data.insert(0, {'id': 'ID', 'name': 'NAME', 'replications': '#REP', 'starting': '#STR', 'executions': '#RUN'}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) has_error = False for row in data: has_error |= '!' in row['id'] log.screen('''\ {id: <{id_width}}{padding}\ {name: <{name_width}}{padding}\ {replications: >{replications_width}}{padding}\ {starting: >{starting_width}}{padding}\ {executions: >{executions_width}}'''.format(**dict(row, **column_widths)).rstrip()) if has_error: log.screen('There are errors: use `conduct events` or `conduct logs` for further information') return True
def load(args): """`conduct load` command""" print('Retrieving bundle...') bundle_name, bundle_url = get_url(args.bundle) bundle_file, bundle_headers = urlretrieve(bundle_url) configuration_file, configuration_headers, configuration_name = (None, None, None) if args.configuration is not None: print('Retrieving configuration...') configuration_name, configuration_url = get_url(args.configuration) configuration_file, configuration_headers = urlretrieve(configuration_url) bundle_conf = ConfigFactory.parse_string(bundle_utils.conf(bundle_file)) overlay_bundle_conf = None if configuration_file is None else \ ConfigFactory.parse_string(bundle_utils.conf(configuration_file)) with_bundle_configurations = partial(apply_to_configurations, bundle_conf, overlay_bundle_conf) url = conduct_url.url('bundles', args) files = get_payload(args.api_version, bundle_name, bundle_file, with_bundle_configurations) if configuration_file is not None: files.append(('configuration', (configuration_name, open(configuration_file, 'rb')))) print('Loading bundle to ConductR...') response = requests.post(url, files=files) conduct_logging.raise_for_status_inc_3xx(response) if args.verbose: conduct_logging.pretty_json(response.text) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) print('Bundle loaded.') print('Start bundle with: conduct run{} {}'.format(args.cli_parameters, bundle_id)) print('Unload bundle with: conduct unload{} {}'.format(args.cli_parameters, bundle_id)) print('Print ConductR info with: conduct info{}'.format(args.cli_parameters))
def run(args): """`conduct run` command""" log = logging.getLogger(__name__) if args.affinity is not None and args.api_version == '1': log.error('Affinity feature is only available for v1.1 onwards of ConductR') return elif args.affinity is not None: path = 'bundles/{}?scale={}&affinity={}'.format(args.bundle, args.scale, args.affinity) else: path = 'bundles/{}?scale={}'.format(args.bundle, args.scale) url = conduct_url.url(path, args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.put(url, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) log.info('Bundle run request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], args.scale, args) log.info('Stop bundle with: conduct stop{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) return True
def stop(args): """`conduct stop` command""" log = logging.getLogger(__name__) path = 'bundles/{}?scale=0'.format(args.bundle) url = conduct_url.url(path, args) response = requests.put(url, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) log.info('Bundle stop request sent.') if not args.no_wait: bundle_scale.wait_for_scale(response_json['bundleId'], 0, args) log.info('Unload bundle with: conduct unload{} {}'.format(args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format(args.cli_parameters)) return True
def display_bundle_id(bundle_id): return bundle_id if args.long_ids else bundle_utils.short_id(bundle_id)
def info(args): """`conduct info` command""" url = conduct_url.url('bundles', args) response = requests.get(url) conduct_logging.raise_for_status_inc_3xx(response) if args.verbose: conduct_logging.pretty_json(response.text) data = [ { 'id': ('! ' if bundle.get('hasError', False) else '') + (bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId'])), 'name': bundle['attributes']['bundleName'], 'replications': len(bundle['bundleInstallations']), 'starting': sum([not execution['isStarted'] for execution in bundle['bundleExecutions']]), 'executions': sum([execution['isStarted'] for execution in bundle['bundleExecutions']]) } for bundle in json.loads(response.text) ] data.insert(0, {'id': 'ID', 'name': 'NAME', 'replications': '#REP', 'starting': '#STR', 'executions': '#RUN'}) padding = 2 column_widths = dict(calc_column_widths(data), **{'padding': ' ' * padding}) has_error = False for row in data: has_error |= '!' in row['id'] print('''\ {id: <{id_width}}{padding}\ {name: <{name_width}}{padding}\ {replications: >{replications_width}}{padding}\ {starting: >{starting_width}}{padding}\ {executions: >{executions_width}}'''.format(**dict(row, **column_widths))) if has_error: print('There are errors: use `conduct events` or `conduct logs` for further information')
def info(args): """`conduct info` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = [{ 'id': ('! ' if bundle.get('hasError', False) else '') + (bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId'])), 'name': bundle['attributes']['bundleName'], 'replications': len(bundle['bundleInstallations']), 'starting': sum([ not execution['isStarted'] for execution in bundle['bundleExecutions'] ]), 'executions': sum([ execution['isStarted'] for execution in bundle['bundleExecutions'] ]) } for bundle in json.loads(response.text)] data.insert( 0, { 'id': 'ID', 'name': 'NAME', 'replications': '#REP', 'starting': '#STR', 'executions': '#RUN' }) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) has_error = False for row in data: has_error |= '!' in row['id'] log.screen('''\ {id: <{id_width}}{padding}\ {name: <{name_width}}{padding}\ {replications: >{replications_width}}{padding}\ {starting: >{starting_width}}{padding}\ {executions: >{executions_width}}'''.format( **dict(row, **column_widths)).rstrip()) if has_error: log.screen( 'There are errors: use `conduct events` or `conduct logs` for further information' ) return True
def display_bundle_id(args, bundle): bundle_id = bundle['bundleId'] if args.long_ids else bundle_utils.short_id( bundle['bundleId']) has_error_display = '! ' if bundle.get('hasError', False) else '' return '{}{}'.format(has_error_display, bundle_id)
def service_names(args): """`conduct service-names` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) response = conduct_request.get(args.dcos_mode, conductr_host(args), url, timeout=DEFAULT_HTTP_TIMEOUT) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) def execution_status(bundle_executions): for execution in bundle_executions: if execution['isStarted']: return 'Running' return 'Starting' def get_service_name_from_service_uri(service_uri): paths = urlparse(service_uri).path.split('/') if len(paths) > 1: return paths[1] else: return '' data_from_service_uri = [ ( { 'service_name': get_service_name_from_service_uri(service_uri), 'service_uri': service_uri, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id( bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': execution_status(bundle['bundleExecutions']) } ) for bundle in json.loads(response.text) if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'services' in endpoint for service_uri in endpoint['services'] ] data_from_service_name = [ ( { 'service_name': endpoint['serviceName'], 'service_uri': None, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id( bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': execution_status(bundle['bundleExecutions']) } ) for bundle in json.loads(response.text) if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'serviceName' in endpoint ] data = data_from_service_uri + data_from_service_name data = sorted([entry for entry in data if entry['service_name']], key=lambda line: line['service_name']) service_endpoints = {} for service in data: url = urlparse(service['service_uri']) if not (url.path == '' or url.path == '/'): try: service_endpoints[url.path] |= {service['service_uri']} except KeyError: service_endpoints[url.path] = {service['service_uri']} duplicate_endpoints = [service for (service, endpoint) in service_endpoints.items() if len(endpoint) > 1] \ if len(service_endpoints) > 0 else [] data.insert(0, {'service_name': 'SERVICE NAME', 'bundle_id': 'BUNDLE ID', 'bundle_name': 'BUNDLE NAME', 'status': 'STATUS'}) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) for row in data: log.screen( '{service_name: <{service_name_width}}{padding}' '{bundle_id: <{bundle_id_width}}{padding}' '{bundle_name: <{bundle_name_width}}{padding}' '{status: <{status_width}}'.format(**dict(row, **column_widths)).rstrip()) if len(duplicate_endpoints) > 0: log.screen('') log.warning('Multiple endpoints found for the following services: {}'.format(', '.join(duplicate_endpoints))) log.warning('Service resolution for these services is undefined.') return True
def load_v1(args): log = logging.getLogger(__name__) log.info('Retrieving bundle...') custom_settings = args.custom_settings resolve_cache_dir = args.resolve_cache_dir bundle_name, bundle_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.bundle) configuration_name, configuration_file = (None, None) if args.configuration is not None: log.info('Retrieving configuration...') configuration_name, configuration_file = resolver.resolve_bundle( custom_settings, resolve_cache_dir, args.configuration) bundle_conf = ConfigFactory.parse_string(bundle_utils.conf(bundle_file)) overlay_bundle_conf = None if configuration_file is None else \ ConfigFactory.parse_string(bundle_utils.conf(configuration_file)) with_bundle_configurations = partial(apply_to_configurations, bundle_conf, overlay_bundle_conf) url = conduct_url.url('bundles', args) files = get_payload(bundle_name, bundle_file, with_bundle_configurations) if configuration_file is not None: files.append(('configuration', (configuration_name, open(configuration_file, 'rb')))) log.info('Loading bundle to ConductR...') # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.post(url, files=files, timeout=LOAD_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) if not args.no_wait: bundle_installation.wait_for_installation(response_json['bundleId'], args) log.info('Bundle loaded.') log.info('Start bundle with: conduct run{} {}'.format( args.cli_parameters, bundle_id)) log.info('Unload bundle with: conduct unload{} {}'.format( args.cli_parameters, bundle_id)) log.info('Print ConductR info with: conduct info{}'.format( args.cli_parameters)) if not log.is_info_enabled() and log.is_quiet_enabled(): log.quiet(response_json['bundleId']) return True
def get_service_names_from_bundles(args, bundles): def execution_status(bundle_executions): for execution in bundle_executions: if execution['isStarted']: return 'Running' return 'Starting' def get_service_name_from_service_uri(service_uri): paths = urlparse(service_uri).path.split('/') if len(paths) > 1: return paths[1] else: return '' data_from_service_uri = [({ 'service_name': get_service_name_from_service_uri(service_uri), 'service_uri': service_uri, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': execution_status(bundle['bundleExecutions']) }) for bundle in bundles if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'services' in endpoint for service_uri in endpoint['services']] data_from_service_name = [({ 'service_name': endpoint['serviceName'], 'service_uri': None, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': execution_status(bundle['bundleExecutions']) }) for bundle in bundles if bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig']['endpoints'].items() if 'serviceName' in endpoint] data = data_from_service_uri + data_from_service_name data = sorted([entry for entry in data if entry['service_name']], key=lambda line: line['service_name']) service_endpoints = {} for service in data: url = urlparse(service['service_uri']) if not (url.path == '' or url.path == '/'): try: service_endpoints[url.path] |= {service['service_uri']} except KeyError: service_endpoints[url.path] = {service['service_uri']} duplicate_endpoints = [service for (service, endpoint) in service_endpoints.items() if len(endpoint) > 1] \ if len(service_endpoints) > 0 else [] return data, duplicate_endpoints
def load_v1(args): log = logging.getLogger(__name__) log.info('Retrieving bundle..') custom_settings = args.custom_settings resolve_cache_dir = args.resolve_cache_dir validate_cache_dir_permissions(resolve_cache_dir, log) bundle_file_name, bundle_file = resolver.resolve_bundle(custom_settings, resolve_cache_dir, args.bundle) configuration_file_name, configuration_file = (None, None) if args.configuration is not None: log.info('Retrieving configuration..') configuration_file_name, configuration_file = resolver.resolve_bundle_configuration(custom_settings, resolve_cache_dir, args.configuration) bundle_conf = ConfigFactory.parse_string(bundle_utils.conf(bundle_file)) overlay_bundle_conf = None if configuration_file is None else \ ConfigFactory.parse_string(bundle_utils.conf(configuration_file)) with_bundle_configurations = partial(apply_to_configurations, bundle_conf, overlay_bundle_conf) url = conduct_url.url('bundles', args) files = get_payload(bundle_file_name, bundle_file, with_bundle_configurations) if configuration_file is not None: files.append(('configuration', (configuration_file_name, open(configuration_file, 'rb')))) # TODO: Delete the bundle configuration file. # Currently, this results into a permission error on Windows. # Therefore, the deletion is disabled for now. # Issue: https://github.com/typesafehub/conductr-cli/issues/175 # if configuration_file and os.path.exists(configuration_file): # os.remove(configuration_file) log.info('Loading bundle to ConductR..') multipart = create_multipart(log, files) response = conduct_request.post(args.dcos_mode, conductr_host(args), url, data=multipart, auth=args.conductr_auth, verify=args.server_verification_file, headers={'Content-Type': multipart.content_type}) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json['bundleId'] if args.long_ids else bundle_utils.short_id(response_json['bundleId']) if not args.no_wait: bundle_installation.wait_for_installation(response_json['bundleId'], args) cleanup_old_bundles(resolve_cache_dir, bundle_file_name, excluded=bundle_file) log.info('Bundle loaded.') if not args.disable_instructions: log.info('Start bundle with: {} run{} {}'.format(args.command, args.cli_parameters, bundle_id)) log.info('Unload bundle with: {} unload{} {}'.format(args.command, args.cli_parameters, bundle_id)) log.info('Print ConductR info with: {} info{}'.format(args.command, args.cli_parameters)) if not log.is_info_enabled() and log.is_quiet_enabled(): log.quiet(response_json['bundleId']) return True
def services(args): """`conduct services` command""" log = logging.getLogger(__name__) url = conduct_url.url('bundles', args) # At the time when this comment is being written, we need to pass the Host header when making HTTP request due to # a bug with requests python library not working properly when IPv6 address is supplied: # https://github.com/kennethreitz/requests/issues/3002 # The workaround for this problem is to explicitly set the Host header when making HTTP request. # This fix is benign and backward compatible as the library would do this when making HTTP request anyway. response = requests.get(url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args)) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) data = sorted([({ 'service': service, 'bundle_id': bundle['bundleId'] if args.long_ids else bundle_utils.short_id(bundle['bundleId']), 'bundle_name': bundle['attributes']['bundleName'], 'status': 'Running' if execution['isStarted'] else 'Starting' }) for bundle in json.loads(response.text) for execution in bundle['bundleExecutions'] for endpoint_name, endpoint in bundle['bundleConfig'] ['endpoints'].items() if 'services' in endpoint for service in endpoint['services']], key=lambda line: line['service']) service_endpoints = {} for service in data: url = urlparse(service['service']) if not (url.path == '' or url.path == '/'): try: service_endpoints[url.path] |= {service['service']} except KeyError: service_endpoints[url.path] = {service['service']} duplicate_endpoints = [service for (service, endpoint) in service_endpoints.items() if len(endpoint) > 1] \ if len(service_endpoints) > 0 else [] data.insert( 0, { 'service': 'SERVICE', 'bundle_id': 'BUNDLE ID', 'bundle_name': 'BUNDLE NAME', 'status': 'STATUS' }) padding = 2 column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding}) for row in data: log.screen('{service: <{service_width}}{padding}' '{bundle_id: <{bundle_id_width}}{padding}' '{bundle_name: <{bundle_name_width}}{padding}' '{status: <{status_width}}'.format( **dict(row, **column_widths)).rstrip()) if len(duplicate_endpoints) > 0: log.screen('') log.warning( 'Multiple endpoints found for the following services: {}'.format( ', '.join(duplicate_endpoints))) log.warning('Service resolution for these services is undefined.') return True
def load_v1(args): log = logging.getLogger(__name__) log.info('Retrieving bundle..') custom_settings = args.custom_settings bundle_resolve_cache_dir = args.bundle_resolve_cache_dir configuration_cache_dir = args.configuration_resolve_cache_dir validate_cache_dir_permissions(bundle_resolve_cache_dir, configuration_cache_dir, log) initial_bundle_file_name, bundle_file = resolver.resolve_bundle( custom_settings, bundle_resolve_cache_dir, args.bundle, args.offline_mode) configuration_file_name, configuration_file = (None, None) if args.configuration is not None: log.info('Retrieving configuration..') configuration_file_name, configuration_file = \ resolver.resolve_bundle_configuration(custom_settings, configuration_cache_dir, args.configuration, args.offline_mode) bundle_conf_text = bundle_utils.conf(bundle_file) bundle_conf = ConfigFactory.parse_string(bundle_conf_text) bundle_file_name, bundle_open_file = open_bundle(initial_bundle_file_name, bundle_file, bundle_conf_text) overlay_bundle_conf = None if configuration_file is None else \ ConfigFactory.parse_string(bundle_utils.conf(configuration_file)) with_bundle_configurations = partial(apply_to_configurations, bundle_conf, overlay_bundle_conf) url = conduct_url.url('bundles', args) files = get_payload(bundle_file_name, bundle_open_file, with_bundle_configurations) if configuration_file is not None: open_configuration_file, config_digest = bundle_utils.digest_extract_and_open( configuration_file) files.append(('configuration', (configuration_file_name, open_configuration_file))) # TODO: Delete the bundle configuration file. # Currently, this results into a permission error on Windows. # Therefore, the deletion is disabled for now. # Issue: https://github.com/typesafehub/conductr-cli/issues/175 # if configuration_file and os.path.exists(configuration_file): # os.remove(configuration_file) log.info('Loading bundle to ConductR..') multipart = create_multipart(log, files) response = conduct_request.post( args.dcos_mode, conductr_host(args), url, data=multipart, auth=args.conductr_auth, verify=args.server_verification_file, headers={'Content-Type': multipart.content_type}) validation.raise_for_status_inc_3xx(response) if log.is_verbose_enabled(): log.verbose(validation.pretty_json(response.text)) response_json = json.loads(response.text) bundle_id = response_json[ 'bundleId'] if args.long_ids else bundle_utils.short_id( response_json['bundleId']) if not args.no_wait: bundle_installation.wait_for_installation(response_json['bundleId'], args) cleanup_old_bundles(bundle_resolve_cache_dir, bundle_file_name, excluded=bundle_file) log.info('Bundle loaded.') if not args.disable_instructions: log.info('Start bundle with: {} run{} {}'.format( args.command, args.cli_parameters, bundle_id)) log.info('Unload bundle with: {} unload{} {}'.format( args.command, args.cli_parameters, bundle_id)) log.info('Print ConductR info with: {} info{}'.format( args.command, args.cli_parameters)) log.info('Print bundle info with: {} info{} {}'.format( args.command, args.cli_parameters, bundle_id)) if not log.is_info_enabled() and log.is_quiet_enabled(): log.quiet(response_json['bundleId']) return True