Esempio n. 1
0
def show(clusters, args, _):
    """Prints info for the token with the given token name."""
    guard_no_cluster(clusters)
    as_json = args.get('json')
    as_yaml = args.get('yaml')
    token_name = args.get('token')[0]
    include_services = not args.get('no-services')

    query_result = query_token(clusters,
                               token_name,
                               include_services=include_services)

    if as_json or as_yaml:
        display_data(args, query_result)
    else:
        for cluster_name, entities in sorted(query_result['clusters'].items()):
            services = entities['services'] if include_services else []
            print(
                tabulate_token(cluster_name, entities['token'], token_name,
                               services, entities['etag']))
            print()

    if query_result['count'] > 0:
        return 0
    else:
        if not as_json and not as_yaml:
            print_no_data(clusters)
        return 1
Esempio n. 2
0
def create_or_update_token(clusters, args, _, action):
    """Creates (or updates) a Waiter token"""
    guard_no_cluster(clusters)
    logging.debug('args: %s' % args)
    token_name_from_args = args.pop('token', None)
    json_file = args.pop('json', None)
    if json_file:
        if len(args) > 0:
            raise Exception(
                'You cannot specify both a token JSON file and token field flags at the same time.'
            )

        token_fields = load_json_file(json_file)
        if not token_fields:
            raise Exception(f'Unable to load token JSON from {json_file}.')
    else:
        token_fields = args

    token_name_from_json = token_fields.pop('token', None)
    if token_name_from_args and token_name_from_json:
        raise Exception(
            'You cannot specify the token name both as an argument and in the token JSON file.'
        )

    token_name = token_name_from_args or token_name_from_json
    if not token_name:
        raise Exception(
            'You must specify the token name either as an argument or in a token JSON file via --json.'
        )

    if len(clusters) > 1:
        default_for_create = [
            c for c in clusters if c.get('default-for-create', False)
        ]
        num_default_create_clusters = len(default_for_create)
        if num_default_create_clusters == 0:
            raise Exception(
                'You must either specify a cluster via --cluster or set "default-for-create" to true for '
                'one of your configured clusters.')
        elif num_default_create_clusters > 1:
            raise Exception(
                'You have "default-for-create" set to true for more than one cluster.'
            )
        else:
            cluster = default_for_create[0]
            query_result = query_token(clusters, token_name)
            if query_result['count'] > 0:
                cluster_names_with_token = list(
                    query_result['clusters'].keys())
                if cluster['name'] not in cluster_names_with_token:
                    cluster = next(c for c in clusters
                                   if c['name'] == cluster_names_with_token[0])
                    logging.debug(f'token already exists in: {cluster}')
    else:
        cluster = clusters[0]

    return create_or_update(cluster, token_name, token_fields, action)
Esempio n. 3
0
def create_or_update_token(clusters, args, _, action):
    """Creates (or updates) a Waiter token"""
    guard_no_cluster(clusters)
    logging.debug('args: %s' % args)
    token_name_from_args = args.pop('token', None)
    json_file = args.pop('json', None)
    yaml_file = args.pop('yaml', None)
    input_file = args.pop('input', None)

    if input_file or json_file or yaml_file:
        token_fields_from_json = load_data({'data': input_file,
                                            'json': json_file,
                                            'yaml': yaml_file})
    else:
        token_fields_from_json = {}

    token_fields_from_args = args
    shared_keys = set(token_fields_from_json).intersection(token_fields_from_args)
    if shared_keys:
        raise Exception(f'You cannot specify the same parameter in both an input file '
                        f'and token field flags at the same time ({", ".join(shared_keys)}).')

    token_fields = {**token_fields_from_json, **token_fields_from_args}
    token_name_from_json = token_fields.pop('token', None)
    if token_name_from_args and token_name_from_json:
        raise Exception('You cannot specify the token name both as an argument and in the input file.')

    token_name = token_name_from_args or token_name_from_json
    if not token_name:
        raise Exception('You must specify the token name either as an argument or in an input file via '
                        '--json or --yaml.')

    if len(clusters) > 1:
        default_for_create = [c for c in clusters if c.get('default-for-create', False)]
        num_default_create_clusters = len(default_for_create)
        if num_default_create_clusters == 0:
            raise Exception('You must either specify a cluster via --cluster or set "default-for-create" to true for '
                            'one of your configured clusters.')
        elif num_default_create_clusters > 1:
            raise Exception('You have "default-for-create" set to true for more than one cluster.')
        else:
            cluster = default_for_create[0]
            query_result = query_token(clusters, token_name)
            if query_result['count'] > 0:
                cluster_names_with_token = list(query_result['clusters'].keys())
                if cluster['name'] not in cluster_names_with_token:
                    cluster = next(c for c in clusters if c['name'] == cluster_names_with_token[0])
                    logging.debug(f'token already exists in: {cluster}')
    else:
        cluster = clusters[0]

    return create_or_update(cluster, token_name, token_fields, action)
Esempio n. 4
0
def tokens(clusters, args, _):
    """Prints info for the tokens owned by the given user."""
    guard_no_cluster(clusters)
    as_json = args.get('json')
    user = args.get('user')
    query_result = query_tokens(clusters, user)
    if as_json:
        print(json.dumps(query_result))
    else:
        print_as_table(query_result)

    if query_result['count'] > 0:
        return 0
    else:
        if not as_json:
            print_no_data(clusters)
        return 1
Esempio n. 5
0
def ping(clusters, args, _):
    """Pings the token with the given token name."""
    guard_no_cluster(clusters)
    token_name_or_service_id = args.get('token-or-service-id')
    is_service_id = args.get('is-service-id', False)
    if is_service_id:
        query_result = query_service(clusters, token_name_or_service_id)
    else:
        query_result = query_token(clusters, token_name_or_service_id)

    if query_result['count'] == 0:
        print_no_data(clusters)
        return 1

    timeout = args.get('timeout', None)
    wait_for_request = args.get('wait', True)
    http_util.set_retries(0)
    cluster_data_pairs = sorted(query_result['clusters'].items())
    clusters_by_name = {c['name']: c for c in clusters}
    overall_success = True
    for cluster_name, data in cluster_data_pairs:
        cluster = clusters_by_name[cluster_name]
        if is_service_id:
            success = ping_service_on_cluster(cluster,
                                              token_name_or_service_id,
                                              timeout, wait_for_request)
        else:
            token_data = data['token']
            token_etag = data['etag']
            token_cluster_name = token_data['cluster'].upper()
            if len(clusters) == 1 or token_explicitly_created_on_cluster(
                    cluster, token_cluster_name):
                success = ping_token_on_cluster(cluster,
                                                token_name_or_service_id,
                                                timeout, wait_for_request,
                                                token_etag)
            else:
                print(
                    f'Not pinging token {terminal.bold(token_name_or_service_id)} '
                    f'in {terminal.bold(cluster_name)} '
                    f'because it was created in {terminal.bold(token_cluster_name)}.'
                )
                success = True
        overall_success = overall_success and success
    return 0 if overall_success else 1
Esempio n. 6
0
def tokens(clusters, args, _):
    """Prints info for the tokens owned by the given user."""
    guard_no_cluster(clusters)
    as_json = args.get('json')
    as_yaml = args.get('yaml')
    user = args.get('user')

    query_result = query_tokens(clusters, user)
    if as_json or as_yaml:
        display_data(args, query_result)
    else:
        print_as_table(query_result)

    if query_result['count'] > 0:
        return 0
    else:
        if not as_json and not as_yaml:
            print_no_data(clusters)
        return 1
Esempio n. 7
0
def ping(clusters, args, _):
    """Pings the token with the given token name."""
    guard_no_cluster(clusters)
    token_name_or_service_id = args.get('token-or-service-id')
    is_service_id = args.get('is-service-id', False)
    if is_service_id:
        query_result = query_service(clusters, token_name_or_service_id)
    else:
        query_result = query_token(clusters, token_name_or_service_id)

    if query_result['count'] == 0:
        print_no_data(clusters)
        return 1

    timeout = args.get('timeout', None)
    http_util.set_retries(0)
    cluster_data_pairs = sorted(query_result['clusters'].items())
    clusters_by_name = {c['name']: c for c in clusters}
    overall_success = True
    for cluster_name, data in cluster_data_pairs:
        cluster = clusters_by_name[cluster_name]
        if is_service_id:
            health_check_endpoint = data['service']['effective-parameters']['health-check-url']
            success = ping_service_on_cluster(cluster, token_name_or_service_id, health_check_endpoint, timeout)
        else:
            token_data = data['token']
            token_cluster_name = token_data['cluster'].upper()
            if len(clusters) == 1 or token_explicitly_created_on_cluster(cluster, token_cluster_name):
                # We are hard-coding the default health-check-url here to /status; this could
                # alternatively be retrieved from /settings, but we want to skip the extra request
                health_check_endpoint = token_data.get('health-check-url', '/status')
                success = ping_token_on_cluster(cluster, token_name_or_service_id, health_check_endpoint, timeout)
            else:
                print(f'Not pinging token {terminal.bold(token_name_or_service_id)} '
                      f'in {terminal.bold(cluster_name)} '
                      f'because it was created in {terminal.bold(token_cluster_name)}.')
                success = True
        overall_success = overall_success and success
    return 0 if overall_success else 1
Esempio n. 8
0
def delete(clusters, args, _):
    """Deletes the token with the given token name."""
    guard_no_cluster(clusters)
    token_name = args.get('token')[0]
    query_result = query_token(clusters, token_name)
    if query_result['count'] == 0:
        print_no_data(clusters)
        return 1

    cluster_data_pairs = sorted(query_result['clusters'].items())
    num_clusters = len(cluster_data_pairs)
    clusters_by_name = {c['name']: c for c in clusters}
    if num_clusters == 1:
        cluster_name = cluster_data_pairs[0][0]
        token_etag = cluster_data_pairs[0][1]['etag']
        cluster = clusters_by_name[cluster_name]
        success = delete_token_on_cluster(cluster, token_name, token_etag)
        return 0 if success else 1
    elif num_clusters > 1:
        overall_success = True
        cluster_names_found = [p[0] for p in cluster_data_pairs]
        print(
            f'Token {terminal.bold(token_name)} exists in {num_clusters} clusters: {", ".join(cluster_names_found)}.'
        )
        for cluster_name, data in cluster_data_pairs:
            if args.get('force', False):
                should_delete = True
            else:
                should_delete = str2bool(
                    input(f'Delete token in {terminal.bold(cluster_name)}? '))
            if should_delete:
                cluster = clusters_by_name[cluster_name]
                success = delete_token_on_cluster(cluster, token_name,
                                                  data['etag'])
                overall_success = overall_success and success
        return 0 if overall_success else 1
Esempio n. 9
0
def _get_existing_token_data(clusters, token_name):
    guard_no_cluster(clusters)
    cluster = get_cluster_with_token(clusters, token_name)
    existing_token_data, existing_token_etag = get_token(cluster, token_name)
    return cluster, existing_token_data, existing_token_etag
Esempio n. 10
0
def kill(clusters, args, _):
    """Kills the service(s) using the given token name."""
    guard_no_cluster(clusters)
    token_name_or_service_id = args.get('token-or-service-id')
    is_service_id = args.get('is-service-id', False)
    if is_service_id:
        query_result = query_service(clusters, token_name_or_service_id)
        num_services = query_result['count']
        if num_services == 0:
            print_no_data(clusters)
            return 1
    else:
        query_result = query_services(clusters, token_name_or_service_id)
        num_services = query_result['count']
        if num_services == 0:
            clusters_text = ' / '.join(
                [terminal.bold(c['name']) for c in clusters])
            print(
                f'There are no services using token {terminal.bold(token_name_or_service_id)} in {clusters_text}.'
            )
            return 1
        elif num_services > 1:
            print(
                f'There are {num_services} services using token {terminal.bold(token_name_or_service_id)}:'
            )

    cluster_data_pairs = sorted(query_result['clusters'].items())
    clusters_by_name = {c['name']: c for c in clusters}
    overall_success = True
    for cluster_name, data in cluster_data_pairs:
        if is_service_id:
            service = data['service']
            service['service-id'] = token_name_or_service_id
            services = [service]
        else:
            services = sorted(
                data['services'],
                key=lambda s: s.get('last-request-time', None) or '',
                reverse=True)

        for service in services:
            service_id = service['service-id']
            cluster = clusters_by_name[cluster_name]
            status_string = service['status']
            status = format_status(status_string)
            inactive = status_string == 'Inactive'
            should_kill = False
            if args.get('force', False) or num_services == 1:
                should_kill = True
            else:
                url = urljoin(cluster['url'], f'apps/{service_id}')
                if is_service_id:
                    active_instances = service['instances']['active-instances']
                    healthy_count = len(
                        [i for i in active_instances if i['healthy?']])
                    unhealthy_count = len(
                        [i for i in active_instances if not i['healthy?']])
                else:
                    healthy_count = service['instance-counts'][
                        'healthy-instances']
                    unhealthy_count = service['instance-counts'][
                        'unhealthy-instances']

                last_request_time = format_last_request_time(service)
                run_as_user = service['service-description']['run-as-user']
                table = [['Status', status], ['Healthy', healthy_count],
                         ['Unhealthy', unhealthy_count], ['URL', url],
                         ['Run as user', run_as_user]]
                table_text = tabulate(table, tablefmt='plain')
                print(
                    f'\n'
                    f'=== {terminal.bold(cluster_name)} / {terminal.bold(service_id)} ===\n'
                    f'\n'
                    f'Last Request: {last_request_time}\n'
                    f'\n'
                    f'{table_text}\n')
                if not inactive:
                    answer = input(
                        f'Kill service in {terminal.bold(cluster_name)}? ')
                    should_kill = str2bool(answer)

            if inactive:
                print(
                    f'Service {terminal.bold(service_id)} on {terminal.bold(cluster_name)} cannot be killed because '
                    f'it is already {status}.')
                should_kill = False

            if should_kill:
                success = kill_service_on_cluster(cluster, service_id,
                                                  args['timeout'])
                overall_success = overall_success and success
    return 0 if overall_success else 1