"""Interface for managing file delivery via s3.""" import io import os import boto3 import botocore.exceptions import config from config import TIKTOK_S3_BASE_FOLDERNAME from config import DEFAULT_AWS_REGION from config import TIKTOK_S3_BUCKET_NAME from src.common.exceptions import exceptions from src.common.connectors import qa_s3_delivery_upload tik_tok_s3_client = None def write_file( file_bytes: bytes, subdir: str, step_function_execution_id: str): """Check the env of execution, and depending on it chooses which function to call. If the environment is 'prod', it will call `write_to_tiktok` to upload files to the TikTok S3 bucket. Otherwise, it will upload the file to our QA upload S3 bucket. Args: file_bytes: The file to transfer subdir: The subdirectory to store the file in step_function_execution_id: The execution ID of the step function Returns: bool: if files were all successfully put on S3 """ env = os.environ['ENVIRONMENT'] if env == 'qa' or env == 'dev': _write_to_qa_bucket(file_bytes, subdir, step_function_execution_id) else: _write_to_tiktok(file_bytes, subdir, step_function_execution_id) def _write_to_tiktok( file_bytes: bytes, subdir: str, step_function_execution_id: str): """Upload arbitrary files in byte format to S3. Args: file_bytes: The file to transfer subdir: The subdirectory to store the file in step_function_execution_id: The execution ID of the step function Returns: bool: if files were all successfully put on S3 """ global tik_tok_s3_client if tik_tok_s3_client is None: tik_tok_s3_client = _get_tiktok_s3_client() try: tik_tok_s3_client.Bucket(TIKTOK_S3_BUCKET_NAME).upload_fileobj( io.BytesIO(file_bytes), f'{TIKTOK_S3_BASE_FOLDERNAME}/{step_function_execution_id}/{subdir}', ) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'SlowDown': raise exceptions.RetryableException('S3 is throttling requests: SlowDown error') raise e def _write_to_qa_bucket( file_bytes: bytes, subdir: str, step_function_execution_id: str): """Upload arbitrary files in byte format to S3. Args: file_bytes: The file to transfer subdir: The subdirectory to store the file in step_function_execution_id: The execution ID of the step function Returns: bool: if files were all successfully put on S3 """ result = qa_s3_delivery_upload.write_sr_delivery_upload_xml( file_bytes, subdir, step_function_execution_id ) return result def _get_tiktok_s3_client(): """Get the S3 client for TikTok bucket.""" return boto3.resource( 's3', aws_access_key_id=config.secrets_manager_client.get_cred('TIKTOK_FINGERPRINT_DELIVERY_USER_NAME'), aws_secret_access_key=config.secrets_manager_client.get_cred('TIKTOK_FINGERPRINT_DELIVERY_PASSWORD'), region_name=DEFAULT_AWS_REGION )