"""Lambda function module.""" import json import config from src.constants import general from src.constants import schema from src.common import common_config from src.common import lambda_exceptions from src.common import s3 from src.common import status from src.common import util from src.common import validators from src.common.constants import errors from marshmallow import ValidationError from owsrequest import request def _log_error(err, filename, bucket): status.send_general_status( function=config.LAMBDA_NAME, status_name=general.ACKNOWLEDGE_ERROR_STATUS, filename=filename, bucket=bucket, errors=err ) def post_asset(data): """Call ows-asset post asset handler. Args: data (dict): Asset details Returns: bool: True if success else raise Exception. """ response = request.process( application=config.APPLICATION_NAME, environment=common_config.ENVIRONMENT, method='POST', service_name=common_config.OWS_ASSETS_SERVICE_NAME, path=common_config.POST_ASSET_PATH, json=data ) if response.status_code == 404: raise lambda_exceptions.PostAssetNotFoundError(response) if response.status_code != 200: raise lambda_exceptions.PostAssetError(response) response_body = response.json() try: validators.validate_config(response_body) except ValidationError as e: raise lambda_exceptions.AssetConfigError(json.dumps(e.messages)) return response_body def get_file_metadata(bucket, key): """Get the file metadata using boto3. Args: bucket (str): the bucket that the file is stored in. key (str): the file Returns: dic: dict with the file's metadata """ s3_obj = s3.head_object(bucket=bucket, key=key) metadata = s3_obj.get('Metadata') if not metadata: raise lambda_exceptions.S3Error( error_code=errors.S3_METADATA_MISSING_CODE, error_params={'filename': key, 'bucket': bucket} ) try: schema.S3Metadata().load(metadata) except ValidationError as e: raise lambda_exceptions.S3Error( error_code=errors.S3_METADATA_VALIDATION_ERROR_CODE, error_params={'filename': key, 'bucket': bucket, 'message': json.dumps(e.messages)} ) return metadata def handler(event, context): """Lambda entry point.""" try: bucket, key = util.extract_triggered_key(event) config.logger.info('triggered {}'.format(key)) metadata = get_file_metadata(bucket, key) status.send_general_status( function=config.LAMBDA_NAME, status_name=general.UPLOAD_COMPLETE_STATUS, filename=key, bucket=bucket ) post_data = { 'asset_type': metadata['asset_type'], 'object_id': metadata['object_id'] if 'object_id' in metadata else None, 'object_type': metadata['object_type'], 'filename': key, 'original_filename': metadata['original_filename'], } post_asset_response = post_asset(post_data) status.send_general_status( function=config.LAMBDA_NAME, status_name=general.ACKNOWLEDGE_COMPLETE_STATUS, filename=key, bucket=bucket ) return { 'bucket': bucket, 'key': key, 'config': post_asset_response['config'] } except lambda_exceptions.LambdaStatusError as error: config.logger.exception(str(error)) _log_error(error.errors, key, bucket) raise except lambda_exceptions.LambdaError as error: config.logger.exception(str(error)) raise except Exception as error: config.logger.exception(str(error)) e = dict() e[errors.ACKNOWLEDGE_ERROR_CODE] = {'message': str(error)} _log_error(e, key, bucket) raise