Пример #1
0
def submit_context_for_building(user: str, project: str,
                                controller: Controller,
                                build_context: BinaryIO,
                                quiet_build: bool) -> str:
    metadata = {
        'user': user,
        'project': project,
    }
    status_json_strings = controller.create_snapshot(metadata, build_context)
    errors = []
    snapshot_id: str = None
    for json_str in status_json_strings:
        data = json.loads(json_str)
        if 'stream' in data:
            if not quiet_build:
                print(data['stream'], end='', flush=True)
        if 'error' in data:
            errors.append(data['error'].rstrip())
        if 'id' in data:
            snapshot_id = data['id']
    if errors or not snapshot_id:
        log_error('The snapshot was not successfully created.')
        pull_access_denied = False
        for error in errors:
            if error.startswith('pull access denied'):
                pull_access_denied = True
            print(error)
        exc_message = 'We did not receive a snapshot ID.'
        if pull_access_denied:
            raise CLIException(exc_message) \
                from PullAccessDeniedException()
        else:
            raise CLIException(exc_message)
    return snapshot_id
Пример #2
0
 def print(self, configuration):
     log_error(self.message)
     cause = self.__cause__
     if cause:
         print(cause)
         if configuration.debug:
             traceback.print_exception(type(cause), cause,
                                       cause.__traceback__)
Пример #3
0
    def run(self):
        user = self.configuration.user
        if self.all_of_them_plz:
            if self.instance_ids is not None:
                raise CLIException('Can\'t specify both a list of instances '
                                   'and --all-of-them-plz')
            user_in_message = 'all users' if self.ignore_ownership else user
            log_warning(
                f'Killing all instances running jobs of {user_in_message} '
                'for all projects')
            if not self.oh_yeah:
                answer = input('Are you sure? (yeah/Nope): ')
                if answer != 'yeah':
                    raise CLIException('Cancelled by user')
        else:
            if self.instance_ids is None or len(self.instance_ids) == 0:
                raise CLIException(
                    'You must specify a list of instance IDs with the -i '
                    'option. Use `plz list` to get instance IDs')
            if self.including_idle:
                raise CLIException(
                    'Option --including-idle only makes sense together with '
                    '--all-of-them-plz')
            # The way the API likes it in this case
            self.including_idle = None
            log_info('Killing instances: ' + ' '.join(self.instance_ids))
        if not self.all_of_them_plz and not self.instance_ids:
            raise CLIException('No instance IDs specified')

        try:
            were_there_instances_to_kill = self.controller.kill_instances(
                instance_ids=self.instance_ids,
                force_if_not_idle=self.force_if_not_idle,
                ignore_ownership=self.ignore_ownership,
                including_idle=self.including_idle,
                user=user)
        except ProviderKillingInstancesException as e:
            fails = e.failed_instance_ids_to_messages
            log_error('Error terminating instances: \n' + ''.join([
                f'{instance_id}: {message}\n'
                for instance_id, message in fails.items()
            ]))
            raise CLIException(
                'Couldn\'t terminate all instances. You can use '
                '--force-if-not-idle for non-idle instances')

        if not were_there_instances_to_kill:
            log_warning(
                'Request to kill all instances, yet no instances were found.')
            if not self.including_idle:
                log_warning('Maybe you forgot --including-idle ?')

        log_info('It was a clean job')
Пример #4
0
 def get_execution_id_from_start_response(
         response_dicts: Iterator[dict]) -> Tuple[str, bool]:
     execution_id: Optional[str] = None
     ok = True
     for data in response_dicts:
         if 'id' in data:
             execution_id = data['id']
         elif 'status' in data:
             print('Instance status:', data['status'].rstrip())
         elif 'error' in data:
             ok = False
             log_error(data['error'].rstrip())
     if not execution_id:
         raise CLIException('We did not receive an execution ID.')
     return execution_id, ok
Пример #5
0
 def run(self):
     response_dict = self.controller.ping(self.ping_timeout)
     if response_dict.get('plz', None) == 'pong':
         if not self.silent_on_success:
             log_info('Backend is reachable')
         controller_build_timestamp = response_dict['build_timestamp']
         if controller_build_timestamp != self.build_timestamp:
             log_error(
                 'Version mismatch! The controller is running version\n'
                 f'{controller_build_timestamp}\n'
                 'while the cli is running\n'
                 f'{self.build_timestamp}\n'
                 'You can install the controller version with\n'
                 'pip install https://s3-eu-west-1.amazonaws.com/'
                 f'plz.prodo.ai/plz_cli-0.1.{controller_build_timestamp}'
                 '-py3-none-any.whl')
             raise ExitWithStatusCodeException(1)
     else:
         log_error('Backend is unreachable')
         raise ExitWithStatusCodeException(1)
Пример #6
0
    def run(self):
        if self.all_of_them_plz:
            log_warning('Killing all instances for all users and projects')
            if not self.oh_yeah:
                answer = input('Are you sure? (yeah/Nope): ')
                if answer != 'yeah':
                    raise CLIException('Cancelled by user')
            instance_ids_for_controller = None
        else:
            if self.instance_ids is None or len(self.instance_ids) == 0:
                raise CLIException(
                    'You must specify a list of instance IDs with the -i '
                    'option. Use `plz list` to get instance IDs')
            log_info('Killing instances: ' + ' '.join(self.instance_ids))
            instance_ids_for_controller = self.instance_ids
        if not self.all_of_them_plz and not self.instance_ids:
            raise CLIException('No instance IDs specified')

        try:
            were_there_instances_to_kill = self.controller.kill_instances(
                instance_ids=instance_ids_for_controller,
                force_if_not_idle=self.force_if_not_idle)
        except ProviderKillingInstancesException as e:
            fails = e.failed_instance_ids_to_messages
            log_error('Error terminating instances: \n' + ''.join([
                f'{instance_id}: {message}\n'
                for instance_id, message in fails.items()
            ]))
            raise CLIException(
                'Couldn\'t terminate all instances. You can use '
                '--force-if-not-idle for non-idle instances')

        if not were_there_instances_to_kill:
            log_warning(
                'Request to kill all instances, yet no instances were found.')

        log_info('It was a clean job')
Пример #7
0
def main(args=sys.argv[1:]):
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--ping-timeout', type=int, default=5)
    parser.add_argument('-c', '--configuration-path', type=str, default=None)
    subparsers = parser.add_subparsers(title='operations',
                                       dest='operation_name')
    for operation in OPERATIONS:
        subparser = subparsers.add_parser(operation.name(),
                                          help=operation.__doc__)
        operation.prepare_argument_parser(subparser, args)
    options = parser.parse_args(args)

    operation_name = options.operation_name
    if operation_name is None:
        parser.print_help()
        sys.exit(2)

    try:
        configuration_path = options.configuration_path \
                             or os.environ.get('PLZ_CONFIGURATION_PATH', None)
        configuration = Configuration.load(configuration_path, operation_name)
    except ValidationException as e:
        e.print()
        sys.exit(2)

    setup_logger(configuration)

    option_dict = options.__dict__
    del option_dict['operation_name']

    ping_timeout = options.ping_timeout
    if operation_name != 'ping-backend':
        del option_dict['ping_timeout']
    else:
        option_dict['build_timestamp'] = _build_timestamp

    del option_dict['configuration_path']

    operation_classes = [o for o in OPERATIONS if o.name() == operation_name]
    if len(operation_classes) == 0:
        log_error('Internal error: couldn\'t find operation: '
                  f'{operation_name}')
        sys.exit(os.EX_SOFTWARE)
    if len(operation_classes) > 1:
        log_error('Internal error: more than one operation with name: '
                  f'{operation_name}')
        sys.exit(os.EX_SOFTWARE)
    operation = operation_classes[0](configuration=configuration,
                                     **option_dict)
    try:
        if operation_name != 'ping-backend':
            # Ping the backend anyway as to avoid wasting user's time when the
            # backend is down
            PingBackendOperation(configuration,
                                 silent_on_success=True,
                                 ping_timeout=ping_timeout,
                                 build_timestamp=_build_timestamp).run()

        operation.run()
    except KeyboardInterrupt:
        log_error('Interrupted by the user.')
        sys.exit(1)
    except CLIException as e:
        e.print(configuration)
        sys.exit(e.exit_code)
    except ExitWithStatusCodeException as e:
        sys.exit(e.exit_code)