def get_build_logs(request_id): """ Retrieve the logs for the build request. :param int request_id: the request ID that was passed in through the URL. :rtype: flask.Response :raise NotFound: if the request is not found or there are no logs for the request :raise Gone: if the logs for the build request have been removed due to expiration """ request_log_dir = flask.current_app.config['IIB_REQUEST_LOGS_DIR'] if not request_log_dir: raise NotFound() request = Request.query.get_or_404(request_id) log_file_path = os.path.join(request_log_dir, f'{request_id}.log') if not os.path.exists(log_file_path): expired = request.logs_expiration < datetime.utcnow() if expired: raise Gone( f'The logs for the build request {request_id} no longer exist') finalized = request.state.state_name in RequestStateMapping.get_final_states( ) if finalized: raise NotFound() # The request may not have been initiated yet. Return empty logs until it's processed. return flask.Response('', mimetype='text/plain') with open(log_file_path) as f: return flask.Response(f.read(), mimetype='text/plain')
def _get_batch_state_change_envelope(batch, new_batch=False): """ Generate a batch state change ``Envelope`` object. No message will be generated if IIB is not configured to send batch state change messages or no batch state change message is needed . :param iib.web.models.Batch batch: the batch that changed states :param bool new_batch: if ``True``, a new batch message will be generated; if ``False``, IIB will generate a batch state change message if the batch is no longer ``in_progress`` :return: the ``Envelope`` for the batch state change or ``None`` :rtype: Envelope or None """ batch_address = current_app.config.get( 'IIB_MESSAGING_BATCH_STATE_DESTINATION') if not batch_address: current_app.logger.debug( 'No batch state change message will be generated since the configuration ' '"IIB_MESSAGING_BATCH_STATE_DESTINATION" is not set') return if new_batch: # Avoid querying the database for the batch state since we know it's a new batch batch_state = 'in_progress' else: batch_state = batch.state if new_batch or batch_state in RequestStateMapping.get_final_states(): current_app.logger.debug( 'Preparing to send a state change message for batch %d', batch.id) batch_username = getattr(batch.user, 'username', None) content = { 'batch': batch.id, 'annotations': batch.annotations, 'requests': [{ 'id': request.id, 'organization': getattr(request, 'organization', None), 'request_type': request.type_name, } for request in batch.requests], 'state': batch_state, 'user': batch_username, } properties = { 'batch': batch.id, 'state': batch_state, 'user': batch_username, } return json_to_envelope(batch_address, content, properties)
def get_build_logs(request_id): """ Retrieve the logs for the build request. :param int request_id: the request ID that was passed in through the URL. :rtype: flask.Response :raise NotFound: if the request is not found or there are no logs for the request :raise Gone: if the logs for the build request have been removed due to expiration :raise ValidationError: if the request has not completed yet """ request_log_dir = flask.current_app.config['IIB_REQUEST_LOGS_DIR'] s3_bucket_name = flask.current_app.config['IIB_AWS_S3_BUCKET_NAME'] if not s3_bucket_name and not request_log_dir: raise NotFound() request = Request.query.get_or_404(request_id) finalized = request.state.state_name in RequestStateMapping.get_final_states( ) if not finalized: raise ValidationError( f'The request {request_id} is not complete yet.' ' logs will be available once the request is complete.') # If S3 bucket is configured, fetch the log file from the S3 bucket. # Else, check if logs are stored on the system itself and return them. # Otherwise, raise an IIBError. if s3_bucket_name: log_file = _get_artifact_file_from_s3_bucket( 'request_logs', f'{request_id}.log', request_id, request.temporary_data_expiration, s3_bucket_name, ) return flask.Response(log_file.read(), mimetype='text/plain') local_log_file_path = os.path.join(request_log_dir, f'{request_id}.log') if not os.path.exists(local_log_file_path): expired = request.temporary_data_expiration < datetime.utcnow() if expired: raise Gone( f'The logs for the build request {request_id} no longer exist') flask.current_app.logger.warning( ' Please make sure either an S3 bucket is configured or the logs are' ' stored locally in a directory by specifying IIB_REQUEST_LOGS_DIR' ) raise IIBError( 'IIB is done processing the request and could not find logs.') with open(local_log_file_path) as f: return flask.Response(f.read(), mimetype='text/plain')
def get_related_bundles(request_id): """ Retrieve the related bundle images from the bundle CSV for a regenerate-bundle request. :param int request_id: the request ID that was passed in through the URL. :rtype: flask.Response :raise NotFound: if the request is not found or there are no related bundles for the request :raise Gone: if the related bundles for the build request have been removed due to expiration """ request_related_bundles_dir = flask.current_app.config['IIB_REQUEST_RELATED_BUNDLES_DIR'] if not request_related_bundles_dir: raise NotFound() request = Request.query.get_or_404(request_id) if request.type != RequestTypeMapping.regenerate_bundle.value: raise ValidationError( f'The request {request_id} is of type {request.type_name}. ' 'This endpoint is only valid for requests of type regenerate-bundle.' ) finalized = request.state.state_name in RequestStateMapping.get_final_states() if not finalized: raise ValidationError( f'The request {request_id} is not complete yet.' ' related_bundles will be available once the request is complete.' ) related_bundles_file_path = os.path.join( request_related_bundles_dir, f'{request_id}_related_bundles.json' ) if not os.path.exists(related_bundles_file_path): expired = request.temporary_data_expiration < datetime.utcnow() if expired: raise Gone(f'The related_bundles for the build request {request_id} no longer exist') raise IIBError( 'IIB is done processing the request and cannot find related_bundles. Please make ' f'sure the iib_organizaiton_customizations for organization {request.organization}' ' has related_bundles customization type set' ) with open(related_bundles_file_path) as f: return flask.Response(f.read(), mimetype='application/json')
def get_related_bundles(request_id): """ Retrieve the related bundle images from the bundle CSV for a regenerate-bundle request. :param int request_id: the request ID that was passed in through the URL. :rtype: flask.Response :raise NotFound: if the request is not found or there are no related bundles for the request :raise Gone: if the related bundles for the build request have been removed due to expiration :raise ValidationError: if the request is of invalid type or is not completed yet """ request_related_bundles_dir = flask.current_app.config[ 'IIB_REQUEST_RELATED_BUNDLES_DIR'] s3_bucket_name = flask.current_app.config['IIB_AWS_S3_BUCKET_NAME'] if not s3_bucket_name and not request_related_bundles_dir: raise NotFound() request = Request.query.get_or_404(request_id) if request.type != RequestTypeMapping.regenerate_bundle.value: raise ValidationError( f'The request {request_id} is of type {request.type_name}. ' 'This endpoint is only valid for requests of type regenerate-bundle.' ) finalized = request.state.state_name in RequestStateMapping.get_final_states( ) if not finalized: raise ValidationError( f'The request {request_id} is not complete yet.' ' related_bundles will be available once the request is complete.') # If S3 bucket is configured, fetch the related bundles file from the S3 bucket. # Else, check if related bundles are stored on the system itself and return them. # Otherwise, raise an IIBError. if s3_bucket_name: log_file = _get_artifact_file_from_s3_bucket( 'related_bundles', f'{request_id}_related_bundles.json', request_id, request.temporary_data_expiration, s3_bucket_name, ) return flask.Response(log_file.read(), mimetype='application/json') related_bundles_file_path = os.path.join( request_related_bundles_dir, f'{request_id}_related_bundles.json') if not os.path.exists(related_bundles_file_path): expired = request.temporary_data_expiration < datetime.utcnow() if expired: raise Gone( f'The related_bundles for the build request {request_id} no longer exist' ) if request.organization: raise IIBError( 'IIB is done processing the request and cannot find related_bundles. Please make ' f'sure the iib_organization_customizations for organization {request.organization}' ' has related_bundles customization type set') flask.current_app.logger.warning( ' Please make sure either an S3 bucket is configured or the logs are' ' stored locally in a directory by specifying IIB_REQUEST_LOGS_DIR' ) raise IIBError( 'IIB is done processing the request and could not find related_bundles.' ) with open(related_bundles_file_path) as f: return flask.Response(f.read(), mimetype='application/json')