Esempio n. 1
0
def unload(args):
    """`conduct unload` command"""

    log = logging.getLogger(__name__)
    path = 'bundles/{}'.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.delete(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))

    log.info('Bundle unload request sent.')

    response_json = json.loads(response.text)
    if not args.no_wait:
        bundle_installation.wait_for_uninstallation(response_json['bundleId'],
                                                    args)

    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
Esempio n. 2
0
def get_scale(bundle_id, args):
    bundles_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(bundles_url,
                            headers=conduct_url.request_headers(args))
    response.raise_for_status()
    bundles = json.loads(response.text)
    matching_bundles = [
        bundle for bundle in bundles if bundle['bundleId'] == bundle_id
    ]
    if matching_bundles:
        matching_bundle = matching_bundles[0]
        if 'bundleExecutions' in matching_bundle:
            started_executions = [
                bundle_execution
                for bundle_execution in matching_bundle['bundleExecutions']
                if bundle_execution['isStarted']
            ]
            return len(started_executions)

    return 0
Esempio n. 3
0
def logs(args):
    """`conduct logs` command"""

    log = logging.getLogger(__name__)
    request_url = conduct_url.url(
        'bundles/{}/logs?count={}'.format(quote_plus(args.bundle), args.lines),
        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(request_url,
                            timeout=DEFAULT_HTTP_TIMEOUT,
                            headers=conduct_url.request_headers(args))
    validation.raise_for_status_inc_3xx(response)

    data = [{
        'time': validation.format_timestamp(event['timestamp'], args),
        'host': event['host'],
        'log': event['message']
    } for event in json.loads(response.text)]
    data.insert(0, {'time': 'TIME', 'host': 'HOST', 'log': 'LOG'})

    padding = 2
    column_widths = dict(screen_utils.calc_column_widths(data),
                         **{'padding': ' ' * padding})

    for row in data:
        log.screen('''\
{time: <{time_width}}{padding}\
{host: <{host_width}}{padding}\
{log: <{log_width}}{padding}'''.format(**dict(row, **column_widths)).rstrip())

    return True
Esempio n. 4
0
def wait_for_condition(bundle_id, condition, condition_name, args):
    log = logging.getLogger(__name__)
    start_time = datetime.now()

    installed_bundles = count_installations(bundle_id, args)
    if condition(installed_bundles):
        log.info('Bundle {} is {}'.format(bundle_id, condition_name))
        return
    else:
        log.info('Bundle {} waiting to be {}'.format(bundle_id, condition_name))
        bundle_events_url = conduct_url.url('bundles/events', args)
        sse_events = sse_client.get_events(bundle_events_url, headers=conduct_url.request_headers(args))
        for event in sse_events:
            elapsed = (datetime.now() - start_time).total_seconds()
            if elapsed > args.wait_timeout:
                raise WaitTimeoutError('Bundle {} waiting to be {}'.format(bundle_id, condition_name))

            if event.event and event.event.startswith('bundleInstallation'):
                installed_bundles = count_installations(bundle_id, args)
                if condition(installed_bundles):
                    log.info('Bundle {} {}'.format(bundle_id, condition_name))
                    return
                else:
                    log.info('Bundle {} still waiting to be {}'.format(bundle_id, condition_name))

        raise WaitTimeoutError('Bundle {} still waiting to be {}'.format(bundle_id, condition_name))
Esempio n. 5
0
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
Esempio n. 6
0
def wait_for_scale(bundle_id, expected_scale, args):
    log = logging.getLogger(__name__)
    start_time = datetime.now()

    bundle_scale = get_scale(bundle_id, args)
    if bundle_scale == expected_scale:
        log.info('Bundle {} expected scale {} is met'.format(bundle_id, expected_scale))
        return
    else:
        log.info('Bundle {} waiting to reach expected scale {}'.format(bundle_id, expected_scale))
        bundle_events_url = conduct_url.url('bundles/events', args)
        sse_events = sse_client.get_events(bundle_events_url, headers=conduct_url.request_headers(args))
        for event in sse_events:
            elapsed = (datetime.now() - start_time).total_seconds()
            if elapsed > args.wait_timeout:
                raise WaitTimeoutError('Bundle {} waiting to reach expected scale {}'.format(bundle_id, expected_scale))

            if event.event and event.event.startswith('bundleExecution'):
                bundle_scale = get_scale(bundle_id, args)
                if bundle_scale == expected_scale:
                    log.info('Bundle {} expected scale {} is met'.format(bundle_id, expected_scale))
                    return
                else:
                    log.info('Bundle {} has scale {}, expected {}'.format(bundle_id, bundle_scale, expected_scale))

        raise WaitTimeoutError('Bundle {} waiting to reach expected scale {}'.format(bundle_id, expected_scale))
Esempio n. 7
0
def logs(args):
    """`conduct logs` command"""

    log = logging.getLogger(__name__)
    request_url = conduct_url.url('bundles/{}/logs?count={}'.format(quote_plus(args.bundle), args.lines), 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(request_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=conduct_url.request_headers(args))
    validation.raise_for_status_inc_3xx(response)

    data = [
        {
            'time': validation.format_timestamp(event['timestamp'], args),
            'host': event['host'],
            'log': event['message']
        } for event in json.loads(response.text)
    ]
    data.insert(0, {'time': 'TIME', 'host': 'HOST', 'log': 'LOG'})

    padding = 2
    column_widths = dict(screen_utils.calc_column_widths(data), **{'padding': ' ' * padding})

    for row in data:
        log.screen('''\
{time: <{time_width}}{padding}\
{host: <{host_width}}{padding}\
{log: <{log_width}}{padding}'''.format(**dict(row, **column_widths)).rstrip())

    return True
 def test_return_headers(self):
     ip_address = "my-test-ip"
     args = {'ip': ip_address}
     input_args = MagicMock(**args)
     result = conduct_url.request_headers(input_args)
     expected_result = {'Host': ip_address}
     self.assertEqual(result, expected_result)
Esempio n. 9
0
def wait_for_scale(bundle_id, expected_scale, args):
    log = logging.getLogger(__name__)
    start_time = datetime.now()

    bundle_scale = get_scale(bundle_id, args)
    if bundle_scale == expected_scale:
        log.info('Bundle {} expected scale {} is met'.format(
            bundle_id, expected_scale))
        return
    else:
        log.info('Bundle {} waiting to reach expected scale {}'.format(
            bundle_id, expected_scale))
        bundle_events_url = conduct_url.url('bundles/events', args)
        sse_events = sse_client.get_events(
            bundle_events_url, headers=conduct_url.request_headers(args))
        for event in sse_events:
            elapsed = (datetime.now() - start_time).total_seconds()
            if elapsed > args.wait_timeout:
                raise WaitTimeoutError(
                    'Bundle {} waiting to reach expected scale {}'.format(
                        bundle_id, expected_scale))

            if event.event and event.event.startswith('bundleExecution'):
                bundle_scale = get_scale(bundle_id, args)
                if bundle_scale == expected_scale:
                    log.info('Bundle {} expected scale {} is met'.format(
                        bundle_id, expected_scale))
                    return
                else:
                    log.info('Bundle {} has scale {}, expected {}'.format(
                        bundle_id, bundle_scale, expected_scale))

        raise WaitTimeoutError(
            'Bundle {} waiting to reach expected scale {}'.format(
                bundle_id, expected_scale))
Esempio n. 10
0
 def test_return_headers(self):
     ip_address = "my-test-ip"
     args = {'ip': ip_address}
     input_args = MagicMock(**args)
     result = conduct_url.request_headers(input_args)
     expected_result = {'Host': ip_address}
     self.assertEqual(result, expected_result)
Esempio n. 11
0
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
Esempio n. 12
0
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
Esempio n. 13
0
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 count_installations(bundle_id, args):
    bundles_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(bundles_url, headers=conduct_url.request_headers(args))
    response.raise_for_status()
    bundles = json.loads(response.text)
    matching_bundles = [bundle for bundle in bundles if bundle['bundleId'] == bundle_id]
    if matching_bundles:
        matching_bundle = matching_bundles[0]
        if 'bundleInstallations' in matching_bundle:
            return len(matching_bundle['bundleInstallations'])

    return 0
Esempio n. 15
0
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
Esempio n. 16
0
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
Esempio n. 17
0
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
Esempio n. 18
0
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
Esempio n. 19
0
 def test_return_none(self):
     args = {'ip': None}
     input_args = MagicMock(**args)
     result = conduct_url.request_headers(input_args)
     self.assertIsNone(result)
Esempio n. 20
0
 def test_return_none(self):
     args = {'ip': None}
     input_args = MagicMock(**args)
     result = conduct_url.request_headers(input_args)
     self.assertIsNone(result)
Esempio n. 21
0
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
Esempio n. 22
0
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