Пример #1
0
def invalidate_operation(operation_id):
    """
    DELETE /imports/images/{operation_id}

    :param operation_id:
    :return:
    """
    try:
        with session_scope() as db_session:
            record = (db_session.query(ImageImportOperation).filter_by(
                account=ApiRequestContextProxy.namespace(),
                uuid=operation_id).one_or_none())
            if record:
                if record.status not in [
                        ImportState.invalidated,
                        ImportState.complete,
                        ImportState.processing,
                ]:
                    record.status = ImportState.invalidated
                    db_session.flush()

                resp = record.to_json()
            else:
                raise api_exceptions.ResourceNotFound(resource=operation_id,
                                                      detail={})

        return resp, 200
    except Exception as ex:
        return make_response_error(ex, in_httpcode=500), 500
Пример #2
0
def finalize_import_operation(
    db_session,
    account: str,
    operation_id: str,
    import_manifest: ImportManifest,
    final_state: ImportState = ImportState.processing,
) -> InternalImportManifest:
    """
    Finalize the import operation itself

    :param db_session:
    :param account:
    :param operation_id:
    :param import_manifest:
    :return:
    """
    record = (db_session.query(ImageImportOperation).filter_by(
        account=account, uuid=operation_id).one_or_none())
    if not record:
        raise api_exceptions.ResourceNotFound(resource=operation_id, detail={})

    if record.status != ImportState.pending:
        raise api_exceptions.ConflictingRequest(
            message=
            "Invalid operation status. Must be in pending state to finalize",
            detail={"status": record.status.value},
        )

    check_required_content(import_manifest)

    try:
        content_records = verify_import_manifest_content(
            db_session, operation_id, import_manifest)
    except ValueError as ex:
        raise api_exceptions.BadRequest(
            message=
            "One or more referenced content digests not found for the operation id",
            detail={"digest": ex.args[0]},
        )

    try:
        internal_manifest = internal_manifest_from_external(
            import_manifest, content_records)

        # Update the status
        record.status = final_state
        # Queue presence should be gated by the image record, not here
        # queue_import_task(account, operation_id, internal_manifest)
    except:
        logger.debug_exception(
            "Failed to queue task message. Setting failed status")
        record.status = ImportState.failed
        raise

    db_session.flush()

    return internal_manifest
Пример #3
0
def content_upload(operation_id, content_type, request):
    """
    Generic handler for multiple types of content uploads. Still operates at the API layer

    :param operation_id:
    :param content_type:
    :param request:
    :return:
    """
    try:
        with session_scope() as db_session:
            record = (db_session.query(ImageImportOperation).filter_by(
                account=ApiRequestContextProxy.namespace(),
                uuid=operation_id).one_or_none())
            if not record:
                raise api_exceptions.ResourceNotFound(resource=operation_id,
                                                      detail={})

            if not record.status.is_active():
                raise api_exceptions.ConflictingRequest(
                    message="import operation status does not allow uploads",
                    detail={"status": record.status},
                )

            if not request.content_length:
                raise api_exceptions.BadRequest(
                    message="Request must contain content-length header",
                    detail={})
            elif request.content_length > MAX_UPLOAD_SIZE:
                raise api_exceptions.BadRequest(
                    message=
                    "too large. Max size of 100MB supported for content",
                    detail={"content-length": request.content_length},
                )

            digest, created_at = save_import_content(db_session, operation_id,
                                                     request.data,
                                                     content_type)

        resp = {
            "digest": digest,
            "created_at": datetime_to_rfc3339(created_at)
        }

        return resp, 200
    except api_exceptions.AnchoreApiError as ex:
        return (
            make_response_error(ex, in_httpcode=ex.__response_code__),
            ex.__response_code__,
        )
    except Exception as ex:
        logger.exception("Unexpected error in api processing")
        return make_response_error(ex, in_httpcode=500), 500
Пример #4
0
def get_operation(operation_id):
    """
    GET /imports/images/{operation_id}

    :param operation_id:
    :return:
    """
    try:
        with session_scope() as db_session:
            record = (db_session.query(ImageImportOperation).filter_by(
                account=ApiRequestContextProxy.namespace(),
                uuid=operation_id).one_or_none())
            if record:
                resp = record.to_json()
            else:
                raise api_exceptions.ResourceNotFound(resource=operation_id,
                                                      detail={})

        return resp, 200
    except Exception as ex:
        return make_response_error(ex, in_httpcode=500), 500
Пример #5
0
def update_operation(operation_id, operation):
    """
    PUT /imports/images/{operation_id}

    Will only update the status, no other fields

    :param operation_id:
    :param operation: content of operation to update
    :return:
    """
    if not operation.get("status"):
        raise api_exceptions.BadRequest("status field required", detail={})

    try:
        with session_scope() as db_session:
            record = (db_session.query(ImageImportOperation).filter_by(
                account=ApiRequestContextProxy.namespace(),
                uuid=operation_id).one_or_none())
            if record:
                if record.status.is_active():
                    record.status = ImportState(operation.get("status"))
                    db_session.flush()
                else:
                    raise api_exceptions.BadRequest(
                        "Cannot update status for import in terminal state",
                        detail={"status": record.status},
                    )
                resp = record.to_json()
            else:
                raise api_exceptions.ResourceNotFound(resource=operation_id,
                                                      detail={})

        return resp, 200
    except api_exceptions.AnchoreApiError as err:
        return (
            make_response_error(err, in_httpcode=err.__response_code__),
            err.__response_code__,
        )
    except Exception as ex:
        return make_response_error(ex, in_httpcode=500), 500