"""Amazon Eventbridge Scheduler connector.""" import functools import json import boto3 import botocore def get_scheduler_client(): """Get Scheduler client. Returns: boto3.client.scheduler: scheduler client. """ return boto3.client('scheduler') def scheduler_client_wrap(func): """Wrap shared boto3 scheduler client. Creates a new client if one isn't passed in. Keeps it at one client per scheduler connector function call. """ @functools.wraps(func) def wrapper(*args, **kwargs): client = kwargs.pop('client', None) if client: return func(*args, client=client, **kwargs) else: return func(*args, client=get_scheduler_client(), **kwargs) return wrapper @scheduler_client_wrap def get_event_schedule(schedule_name, scheduler_group, client=None): """Get scheduled event. Args: schedule_name (str or int): name of the schedule to get. Returns: dict with all schedule information or None. """ try: return client.get_schedule( GroupName=scheduler_group, Name=f'{schedule_name}' ) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] != 'ResourceNotFoundException': raise error @scheduler_client_wrap def create_event_schedule( schedule_name, schedule_datetime, target_arn, payload, scheduler_group, scheduler_role_arn, description='', client=None ): """Create scheduled event. Args: schedule_name (str or int): name of the schedule to create. schedule_datetime (str): datetime string to process event at. target_arn (str): arn of the schedules target. payload (dict): body to be sent to target. description (str): desciption of the schedule. Returns: dict: { ScheduledArn: string } """ return client.create_schedule( Name=f'{schedule_name}', GroupName=scheduler_group, ScheduleExpression=f'at({schedule_datetime.replace("Z", "")})', ScheduleExpressionTimezone='Etc/UTC', Description=f'{description}', FlexibleTimeWindow={'Mode': 'OFF'}, State='ENABLED', Target={ 'Arn': target_arn, 'Input': json.dumps(payload), 'RetryPolicy': { 'MaximumEventAgeInSeconds': 300, 'MaximumRetryAttempts': 3 }, 'RoleArn': scheduler_role_arn, }, ActionAfterCompletion='DELETE', ) @scheduler_client_wrap def update_event_schedule( schedule_name, schedule_datetime, target_arn, payload, scheduler_group, scheduler_role_arn, description='', client=None ): """Update scheduled event. Args: schedule_name (str or int): name of the schedule to update. schedule_datetime (str): datetime string to process event at. target_arn (str): arn of the schedules target. payload (dict): body to be sent to target. description (str): desciption of the schedule. Returns: dict: { ScheduledArn: string } """ return client.update_schedule( Name=f'{schedule_name}', GroupName=scheduler_group, ScheduleExpression=f'at({schedule_datetime.replace("Z", "")})', ScheduleExpressionTimezone='Etc/UTC', Description=f'{description}', FlexibleTimeWindow={'Mode': 'OFF'}, State='ENABLED', Target={ 'Arn': target_arn, 'Input': json.dumps(payload), 'RetryPolicy': { 'MaximumEventAgeInSeconds': 300, 'MaximumRetryAttempts': 3 }, 'RoleArn': scheduler_role_arn, }, ActionAfterCompletion='DELETE', ) @scheduler_client_wrap def upsert_event_schedule( schedule_name, schedule_datetime, target_arn, payload, scheduler_group, scheduler_role_arn, description='', client=None ): """Check if a schedule with the given name exists. If data exists, update the schedule. If data does not exist, create a new schedule. Args: schedule_name (str or int): name of the schedule to update. schedule_datetime (str): datetime string to process event at. target_arn (str): arn of the schedules target. input (dict): body to be sent to target. description (str): desciption of the schedule. Returns: dict: { ScheduledArn: string } """ existing = get_event_schedule( schedule_name, scheduler_group, client=client) if existing: return update_event_schedule( schedule_name, schedule_datetime, target_arn, payload, scheduler_group, scheduler_role_arn, description, client=client) else: return create_event_schedule( schedule_name, schedule_datetime, target_arn, payload, scheduler_group, scheduler_role_arn, description, client=client) @scheduler_client_wrap def delete_event_schedule( schedule_name, scheduler_group, client=None): """Delete scheduled event. Args: schedule_name (str or int): name of the schedule to delete. Returns: Empty dict or None. """ try: return client.delete_schedule( GroupName=scheduler_group, Name=f'{schedule_name}' ) except botocore.exceptions.ClientError as error: if error.response['Error']['Code'] != 'ResourceNotFoundException': raise error