Пример #1
0
def regenerate_bundle_batch():
    """
    Submit a batch of requests to regenerate operator bundle images.

    :rtype: flask.Response
    :raise ValidationError: if required parameters are not supplied
    """
    payload = flask.request.get_json()
    Batch.validate_batch_request_params(payload)

    batch = Batch(annotations=payload.get('annotations'))
    db.session.add(batch)

    requests = []
    # Iterate through all the build requests and verify that the requests are valid before
    # committing them and scheduling the tasks
    for build_request in payload['build_requests']:
        try:
            request = RequestRegenerateBundle.from_json(build_request, batch)
        except ValidationError as e:
            # Rollback the transaction if any of the build requests are invalid
            db.session.rollback()
            raise ValidationError(
                f'{str(e).rstrip(".")}. This occurred on the build request in '
                f'index {payload["build_requests"].index(build_request)}.')
        db.session.add(request)
        requests.append(request)

    db.session.commit()
    messaging.send_messages_for_new_batch_of_requests(requests)

    request_jsons = []
    # This list will be used for the log message below and avoids the need of having to iterate
    # through the list of requests another time
    request_id_strs = []
    for build_request, request in zip(payload['build_requests'], requests):
        request_jsons.append(request.to_json())
        request_id_strs.append(str(request.id))

        error_callback = failed_request_callback.s(request.id)
        handle_regenerate_bundle_request.apply_async(
            args=[
                build_request['from_bundle_image'],
                build_request.get('organization'),
                request.id,
            ],
            link_error=error_callback,
            queue=_get_user_queue(),
        )

    flask.current_app.logger.debug(
        'Successfully scheduled the batch %d with requests: %s',
        batch.id,
        ', '.join(request_id_strs),
    )
    return flask.jsonify(request_jsons), 201
Пример #2
0
def get_builds():
    """
    Retrieve the paginated build requests.

    :rtype: flask.Response
    """
    batch_id = flask.request.args.get('batch')
    state = flask.request.args.get('state')
    verbose = str_to_bool(flask.request.args.get('verbose'))
    max_per_page = flask.current_app.config['IIB_MAX_PER_PAGE']

    # Create an alias class to load the polymorphic classes
    poly_request = with_polymorphic(Request, '*')
    query = poly_request.query.options(*get_request_query_options(
        verbose=verbose))
    if state:
        RequestStateMapping.validate_state(state)
        state_int = RequestStateMapping.__members__[state].value
        query = query.join(Request.state)
        query = query.filter(RequestState.state == state_int)

    if batch_id is not None:
        batch_id = Batch.validate_batch(batch_id)
        query = query.filter_by(batch_id=batch_id)

    pagination_query = query.order_by(
        Request.id.desc()).paginate(max_per_page=max_per_page)
    requests = pagination_query.items

    query_params = {}
    if state:
        query_params['state'] = state
    if verbose:
        query_params['verbose'] = verbose
    if batch_id:
        query_params['batch'] = batch_id

    response = {
        'items': [request.to_json(verbose=verbose) for request in requests],
        'meta': pagination_metadata(pagination_query, **query_params),
    }
    return flask.jsonify(response)
Пример #3
0
def add_rm_batch():
    """
    Submit a batch of requests to add or remove operators from an index image.

    Note: Any duplicate bundle will be removed from payload when adding operators.

    :rtype: flask.Response
    :raise ValidationError: if required parameters are not supplied
    """
    payload = flask.request.get_json()
    Batch.validate_batch_request_params(payload)

    batch = Batch(annotations=payload.get('annotations'))
    db.session.add(batch)

    requests = []
    # Iterate through all the build requests and verify that the requests are valid before
    # committing them and scheduling the tasks
    for build_request in payload['build_requests']:
        try:
            if build_request.get('operators'):
                # Check for the validity of a RM request
                request = RequestRm.from_json(build_request, batch)
            elif build_request.get('bundles'):
                build_request_uniq = copy.deepcopy(build_request)
                build_request_uniq['bundles'] = _get_unique_bundles(build_request_uniq['bundles'])
                # Check for the validity of an Add request
                request = RequestAdd.from_json(build_request_uniq, batch)
            else:
                raise ValidationError('Build request is not a valid Add/Rm request.')
        except ValidationError as e:
            raise ValidationError(
                f'{str(e).rstrip(".")}. This occurred on the build request in '
                f'index {payload["build_requests"].index(build_request)}.'
            )
        db.session.add(request)
        requests.append(request)

    db.session.commit()
    messaging.send_messages_for_new_batch_of_requests(requests)

    request_jsons = []
    # This list will be used for the log message below and avoids the need of having to iterate
    # through the list of requests another time
    processed_request_ids = []
    for build_request, request in zip(payload['build_requests'], requests):
        request_jsons.append(request.to_json())

        overwrite_from_index = build_request.get('overwrite_from_index')
        celery_queue = _get_user_queue(serial=overwrite_from_index)
        if isinstance(request, RequestAdd):
            args = _get_add_args(build_request, request, overwrite_from_index, celery_queue)
        elif isinstance(request, RequestRm):
            args = _get_rm_args(build_request, request, overwrite_from_index)

        safe_args = _get_safe_args(args, build_request)

        error_callback = failed_request_callback.s(request.id)
        try:
            if isinstance(request, RequestAdd):
                handle_add_request.apply_async(
                    args=args,
                    link_error=error_callback,
                    argsrepr=repr(safe_args),
                    queue=celery_queue,
                )
            else:
                handle_rm_request.apply_async(
                    args=args,
                    link_error=error_callback,
                    argsrepr=repr(safe_args),
                    queue=celery_queue,
                )
        except kombu.exceptions.OperationalError:
            unprocessed_requests = [r for r in requests if str(r.id) not in processed_request_ids]
            handle_broker_batch_error(unprocessed_requests)

        processed_request_ids.append(str(request.id))

    flask.current_app.logger.debug(
        'Successfully scheduled the batch %d with requests: %s',
        batch.id,
        ', '.join(processed_request_ids),
    )
    return flask.jsonify(request_jsons), 201
Пример #4
0
def get_builds():
    """
    Retrieve the paginated build requests.

    :rtype: flask.Response
    """
    batch_id = flask.request.args.get('batch')
    state = flask.request.args.get('state')
    verbose = str_to_bool(flask.request.args.get('verbose'))
    max_per_page = flask.current_app.config['IIB_MAX_PER_PAGE']
    request_type = flask.request.args.get('request_type')
    user = flask.request.args.get('user')
    index_image = flask.request.args.get('index_image')

    query_params = {}

    # Create an alias class to load the polymorphic classes
    poly_request = with_polymorphic(Request, '*')
    query = poly_request.query.options(*get_request_query_options(
        verbose=verbose))
    if state:
        query_params['state'] = state
        RequestStateMapping.validate_state(state)
        state_int = RequestStateMapping.__members__[state].value
        query = query.join(Request.state)
        query = query.filter(RequestState.state == state_int)

    if batch_id is not None:
        query_params['batch'] = batch_id
        batch_id = Batch.validate_batch(batch_id)
        query = query.filter_by(batch_id=batch_id)

    if request_type:
        query_params['request_type'] = request_type
        RequestTypeMapping.validate_type(request_type)
        request_type = request_type.replace('-', '_')
        request_type_int = RequestTypeMapping.__members__[request_type].value
        query = query.filter(Request.type == request_type_int)

    if user:
        # join with the user table and then filter on username
        # request table only has the user_id
        query_params['user'] = user
        query = query.join(Request.user).filter(User.username == user)

    if index_image:
        query_params['index_image'] = index_image
        # Get the image id of the image to be searched
        image_result = Image.query.filter_by(
            pull_specification=index_image).first()
        if image_result:
            # join with the Request* tables to get the response as image_ids are stored there
            query = (query.outerjoin(
                RequestCreateEmptyIndex,
                Request.id == RequestCreateEmptyIndex.id).outerjoin(
                    RequestAdd, Request.id == RequestAdd.id).outerjoin(
                        RequestMergeIndexImage,
                        Request.id == RequestMergeIndexImage.id).outerjoin(
                            RequestRm, Request.id == RequestRm.id))

            query = query.filter(
                or_(
                    RequestCreateEmptyIndex.index_image_id == image_result.id,
                    RequestAdd.index_image_id == image_result.id,
                    RequestMergeIndexImage.index_image_id == image_result.id,
                    RequestRm.index_image_id == image_result.id,
                ))
        # if index_image is not found in image table, then raise an error
        else:
            raise ValidationError(f'{index_image} is not a valid index image')

    pagination_query = query.order_by(
        Request.id.desc()).paginate(max_per_page=max_per_page)
    requests = pagination_query.items

    response = {
        'items': [request.to_json(verbose=verbose) for request in requests],
        'meta': pagination_metadata(pagination_query, **query_params),
    }
    return flask.jsonify(response)