"""VEVO Data Ingestion Workflow.""" from datetime import datetime from botocore.exceptions import ClientError from garcon import task from garcon_contrib.dynamo_feed_status import garcon_feed_status from snowflake_connector.etl_connector import SQLLoader from feed_ingestion.flows.vevo import config from feed_ingestion.tasks import check_status from feed_ingestion.tasks import s3_tasks from feed_ingestion.util.aws.assume_role import get_s3_client_assume_role from feed_ingestion.util.aws.s3 import get_list_of_files_and_directories # Load SQL templates sql_loader = SQLLoader(__file__) @task.decorate(timeout=1000) def bootstrap(activity, date, licensor): """Bootstrap workflow by getting the correct configurations. Args: activity (ActivityWorker): The activity worker. date (str): Reporting date (YYYY-MM-DD). licensor (str): The licensor name. Returns: dict: Context. """ date_obj = (datetime.strptime( date, '%Y-%m-%d') if date else datetime.today()) sme_version_switch_date = datetime.strptime( config.s3['sme']['v2_switch_date'], '%Y-%m-%d' ) filename_theorchard_prefix = config.filename_theorchard_prefix.format( date=date_obj) filename_sme = config.filename_sme.format(date=date_obj) activity.logger.info('Bootstrap flow: {}'.format(date_obj)) drop_path = config.s3[licensor]['drop'].format(date=date_obj) if licensor == 'sme' and date_obj >= sme_version_switch_date: drop_path = drop_path.replace('v1', 'v2') archive_path = config.s3[licensor]['archive'].format(date=date_obj) temp_staging_raw_table = config.temp_staging_raw_table.format( licensor=licensor, date=date_obj) return dict( feed_name='_'.join([config.feed_name, licensor]), licensor=licensor, date=date_obj.strftime('%Y-%m-%d'), filename_theorchard_prefix=filename_theorchard_prefix, filename_sme=filename_sme, drop_path=drop_path, archive_path=archive_path, temp_staging_raw_table=temp_staging_raw_table, staging_raw_table=config.staging_raw_table, secrets_path=config.secrets_path ) @task.decorate(timeout=3600) @check_status() def grab_drop_files( activity, feed_name, date, drop_path, filename_prefix, archive_path): """Copy The Orchard file from the drop location into the archive folder. Args: activity (ActivityWorker): The activity worker. feed_name (str): The name of the feed. date (str): Reporting date (YYYY-MM-DD). drop_path (str): Source S3 path to the archive location. filename_prefix (str): Destination S3 path to the archive location. archive_path (str): Name of zipped archive. """ s3_drop_path = f's3://{config.drop_bucket}/{drop_path}{filename_prefix}' files = get_list_of_files_and_directories(s3_drop_path) # todo remove all the loggers (added for investigation purposes) activity.logger.info('s3_drop_path = ' + s3_drop_path) activity.logger.info('Found files:\n' + ', '.join(files)) if files: source_key_name = files[0] filename = source_key_name.split('/')[-1] activity.logger.info('Filename: ' + filename) result = s3_tasks.copy_file( activity=activity, source_bucket_name=config.drop_bucket, source_key_name=source_key_name, destination_bucket_name=config.data_bucket, destination_key_name=f'{archive_path}{filename}', replace=True) activity.logger.info(result) if result.get(filename): return { 's3_drop_path': f's3://{config.drop_bucket}/{source_key_name}'} activity.logger.info({'stop': True}) garcon_feed_status.set_overall_status( feed_name, date, garcon_feed_status.STATUS_NOT_AVAILABLE) garcon_feed_status.set_missing_files( feed_name, date, [filename_prefix]) return {'stop': True} @task.decorate(timeout=3600) @check_status() def grab_drop_files_sme( activity, feed_name, date, drop_path, filename, archive_path): """Copy SME file from the drop location into the archive folder. Args: activity (ActivityWorker): The activity worker. feed_name (str): The name of the feed. date (str): Reporting date (YYYY-MM-DD). drop_path (str): Source S3 path to the archive location. filename (str): Destination S3 path to the archive location. archive_path (str): Name of zipped archive. """ sme_s3_client = get_s3_client_assume_role(config.sme_role_arn) copy_source = { 'Bucket': config.drop_bucket_sme, 'Key': '{s3_path}{filename}'.format( s3_path=drop_path, filename=filename) } archive_path = '{s3_path}{filename}'.format( s3_path=archive_path, filename=filename) try: sme_s3_client.copy( copy_source, config.data_bucket, archive_path) except ClientError as err: if err.response['Error']['Code'] == '404': msg = (f"Cannot find {copy_source.get('Key')} object on S3") activity.logger.error(msg) garcon_feed_status.set_overall_status( feed_name, date, garcon_feed_status.STATUS_NOT_AVAILABLE) return {'stop': True, 'message': msg} raise err activity.logger.info(f'File {filename} uploaded') return { 's3_drop_path': f's3://{config.data_bucket}/{archive_path}'}