def process_and_select_resource(service, logger, resource_name, resource, context, task, task_assumed_role): parameters = task.get(TASK_PARAMETERS, {}) if parameters.get(PARAM_RESIZE_MODE) == RESIZE_BY_SPECIFIED_TYPE: return resource tags = resource.get("Tags", {}) scale_up_str = parameters.get(PARAM_TAGFILTER_SCALE_UP) scale_up_filter = TagFilterExpression( scale_up_str) if scale_up_str is not None else None if scale_up_filter is not None and scale_up_filter.is_match(tags): return resource scale_down_str = parameters.get(PARAM_TAGFILTER_SCALE_DOWN) scale_down_filter = TagFilterExpression( scale_down_str) if scale_down_str is not None else None if scale_down_filter is not None and scale_down_filter.is_match(tags): return resource logger.debug( "Instance {} is not selected as tags {} do not match scale-up filter \"{}\" or scale-down filter \"{}\"", resource["InstanceId"], tags, scale_up_str, scale_down_str) return None
def __init__(self, action_arguments, action_parameters): ActionEc2EventBase.__init__(self, action_arguments, action_parameters) self.instance = self._resources_ self.instance_id = self.instance["InstanceId"] self._ec2_client = None self._ec2_service = None self.instance_type_index = -1 self.result = { "account": self._account_, "region": self._region_, "instance": self.instance_id, "task": self._task_ } # instance type, list if alternatives must be retried if the type is not available self.new_instance_types = [ s.strip() for s in self.get(PARAM_INSTANCE_TYPES, []) ] self.resize_mode = self.get(PARAM_RESIZE_MODE) self.instance_type_index = -1 self.scaling_range = [ t.strip() for t in self.get(PARAM_SCALING_RANGE, []) ] self.next_type_in_range = self.get( PARAM_TRY_NEXT_IN_RANGE, True) if self.resize_mode == RESIZE_BY_STEP else True self.scale_up_str = self.get(PARAM_TAGFILTER_SCALE_UP) self.scale_up_tagfilter = TagFilterExpression( self.scale_up_str) if self.scale_up_str is not None else None self.scale_down_str = self.get(PARAM_TAGFILTER_SCALE_DOWN) self.scale_down_tagfilter = TagFilterExpression( self.scale_down_str) if self.scale_down_str is not None else None self.assumed_instance_type = self.get(PARAM_ASSUMED_TYPE) self.scaling_range_index = None self.scale_up = None self.scale_down = None self.original_type = None self.new_instance_type = None self.result = { "account": self._account_, "region": self._region_, "instance": self.instance_id, "task": self._task_ }
def check_copy_snapshot(self, snapshot_id, source_snapshot, destination): ec2_destination = Ec2(region=destination) self.logger.test("Checking copied snapshot") snapshot_copy = ec2_destination.get_snapshot(snapshot_id) self.assertIsNotNone(snapshot_copy, "Snapshot copy does exist") snapshot_tags = snapshot_copy.get("Tags", {}) self.assertTrue( TagFilterExpression("copied-tag=copied-value").is_match( snapshot_tags), "Source snapshot tag copied") self.assertFalse( TagFilterExpression("not-copied-tag=*").is_match(snapshot_tags), "Source snapshot tag not copied") self.logger.test("[X] Expected source snapshot tag copied") snapshot_placeholders = { copy_snapshot.TAG_PLACEHOLDER_SOURCE_REGION: source_snapshot["Region"], copy_snapshot.TAG_PLACEHOLDER_SOURCE_SNAPSHOT_ID: source_snapshot["SnapshotId"], copy_snapshot.TAG_PLACEHOLDER_SOURCE_VOLUME: source_snapshot["VolumeId"], copy_snapshot.TAG_PLACEHOLDER_OWNER_ACCOUNT: source_snapshot["AwsAccount"] } self.assertTrue( testing.tags.verify_placeholder_tags(snapshot_tags, snapshot_placeholders), "All placeholder tags set on snapshot {}".format(snapshot_id)) self.logger.test("[X] Placeholder tags created") self.assertTrue( TagFilterExpression("{}={}".format( actions.marker_snapshot_tag_source_source_volume_id(), source_snapshot["VolumeId"])).is_match(snapshot_tags), "Source volume tag set") self.logger.test("[X] Source volume tag created") self.assertTrue( TagFilterExpression("{}={}".format( copy_snapshot.Ec2CopySnapshotAction. marker_tag_source_snapshot_id(), source_snapshot["SnapshotId"])).is_match(snapshot_tags), "Source snapshot tag set") self.logger.test("[X] Source snapshot tag created") self.assertEqual( ec2_destination.get_snapshot_create_volume_permission_users( snapshot_id), ["123456789012"], "Create volume permissions set") self.logger.test("[X] Volume create permission set") self.assertEqual(snapshot_copy["Description"], source_snapshot["Description"], "Description is copied") self.logger.test("[X] Description is copied")
def test_create_snapshots_volume_with_tagfilter(self): try: parameters = { create_snapshot_action.PARAM_BACKUP_DATA_DEVICES: True, create_snapshot_action.PARAM_BACKUP_ROOT_DEVICE: False, create_snapshot_action.PARAM_VOLUME_TAG_FILTER: "Backup=True", } test_method = inspect.stack()[0][3] from datetime import timedelta self.logger.test("Running task") self.task_runner.run(parameters, task_name=test_method, complete_check_polling_interval=15) self.assertTrue(self.task_runner.success(), "Task executed successfully") self.logger.test("[X] Task completed") self.logger.test("Checking data snapshot") volume_snapshots = getattr(self.task_runner.results[0], "ActionStartResult", {}).get("volumes", {}) self.created_snapshots = [volume_snapshots[i]["snapshot"] for i in volume_snapshots] self.assertEqual(1, len(volume_snapshots), "[X] Volume snapshots created") snapshot = self.ec2.get_snapshot(self.created_snapshots[0]) snapshot_volume_tags = self.ec2.get_volume_tags(snapshot["VolumeId"]) self.assertTrue(TagFilterExpression("Backup=True").is_match(snapshot_volume_tags), "Snapshot is for selected data volume") self.logger.test("[X] Snapshot is for selected data volumes") finally: self.delete_snapshots()
def setup_tag_filtering(t_name): # get optional tag filter no_select_by_tags = self.action_properties.get( actions.ACTION_NO_TAG_SELECT, False) if no_select_by_tags: tag_filter_string = tagging.tag_filter_set.WILDCARD_CHAR else: tag_filter_string = self.task.get(handlers.TASK_TAG_FILTER) # set if only a single task is required for selecting the resources, it is used to optimise the select select_tag = None if tag_filter_string is None: self._logger.debug(DEBUG_SELECT_BY_TASK_NAME, self._resource_name, self._task_tag, t_name) select_tag = self._task_tag elif tag_filter_string == tagging.tag_filter_set.WILDCARD_CHAR: self._logger.debug(DEBUG_SELECT_ALL_RESOURCES, self._resource_name) else: self._logger.debug(DEBUG_TAG_FILTER_USED_TO_SELECT_RESOURCES, self._resource_name) # build the tag expression that us used to filter the resources tag_filter_expression = TagFilterExpression(tag_filter_string) # the keys of the used tags tag_filter_expression_tag_keys = list( tag_filter_expression.get_filter_keys()) # if there is only a single tag then we can optimize by just filtering on that specific tag if len(tag_filter_expression_tag_keys) == 1 and \ tagging.tag_filter_set.WILDCARD_CHAR not in tag_filter_expression_tag_keys[0]: select_tag = tag_filter_expression_tag_keys[0] return select_tag, tag_filter_string
def check_snapshot(snap_id, source_volume_id): checked_snapshot = self.ec2.get_snapshot(snap_id) self.assertIsNotNone(checked_snapshot, "Snapshot does exist") self.logger.test("[X] Snapshot was created") snapshot_tags = checked_snapshot.get("Tags", {}) self.assertTrue(TagFilterExpression("InstanceTag=Instance0").is_match(snapshot_tags), "Instance tag copied") self.logger.test("[X] Instance tags copied") source_volume = self.ec2.get_volume(source_volume_id) assert (source_volume is not None) device = source_volume.get("Attachments", [{}])[0].get("Device", "") if source_volume_id in self.data_volumes: volume_tags = source_volume.get("Tags", {}) self.assertTrue( TagFilterExpression("VolumeTag={}".format(volume_tags.get("VolumeTag", ""))).is_match(snapshot_tags), "Volume tag copied") self.logger.test("[X] Volume tags copied") snapshot_placeholders = { create_snapshot_action.TAG_PLACEHOLDER_VOLUME_ID: source_volume_id, create_snapshot_action.TAG_PLACEHOLDER_INSTANCE_ID: self.instance_id, create_snapshot_action.TAG_PLACEHOLDER_DEVICE: device } self.assertTrue(testing.tags.verify_placeholder_tags(snapshot_tags, snapshot_placeholders), "All placeholder tags set on snapshot {}".format(snap_id)) self.logger.test("[X] Placeholder tags created") self.assertTrue(TagFilterExpression( "{}={}".format(actions.marker_snapshot_tag_source_source_volume_id(), source_volume_id)).is_match( snapshot_tags), "Source volume tag set") self.logger.test("[X] Source volume tags created") self.assertTrue(self.ec2.get_snapshot_create_volume_permission_users(snap_id) == ["123456789012"], "Create volume permissions set") self.logger.test("[X] Volume create permissions set") expected_name = "snapshot-{}-{}-{}".format(self.task_runner.action_stack_name, self.instance_id, source_volume_id) self.assertEqual(expected_name, snapshot_tags["Name"], "Name has been set") self.logger.test("[X] Snapshot name set") description = checked_snapshot.get("Description", "") self.assertTrue( all([p in description for p in [source_volume_id, self.instance_id, region(), self.task_runner.task_name]]), "Description is set") self.logger.test("[X] Snapshot description set")
def delete_instance_snapshots_by_tags(self, tag_filter_expression): delete_filter = TagFilterExpression(tag_filter_expression) snapshots = [] for s in self.rds_service.describe(services.rds_service.DB_SNAPSHOTS, region=self.region, tags=True): if delete_filter.is_match(s.get("Tags")): snapshots.append(s["DBSnapshotIdentifier"]) self.delete_instance_snapshots(snapshots)
def delete_snapshots_by_tags(self, tag_filter_expression): delete_filter = TagFilterExpression(tag_filter_expression) snapshots = [] for s in self.ec2_service.describe(services.ec2_service.SNAPSHOTS, region=self.region, tags=True, OwnerIds=["self"]): if delete_filter.is_match(s.get("Tags")): snapshots.append(s["SnapshotId"]) self.delete_snapshots(snapshots)
def delete_images_by_tags(self, tag_filter_expression): delete_filter = TagFilterExpression(tag_filter_expression) images = [] for s in self.ec2_service.describe(services.ec2_service.IMAGES, region=self.region, tags=True, Owners=["self"]): if delete_filter.is_match(s.get("Tags")): images.append(s["ImageId"]) self.delete_images(images)
def verify_placeholder_tags(tags, action_placeholders=None, exclude_tags=None): checked_tags = [(tagging.TAG_VAL_ACCOUNT, services.get_aws_account()), (tagging.TAG_VAL_AUTOMATOR_STACK, os.getenv(handlers.ENV_STACK_NAME, "\.*")), (tagging.TAG_VAL_DATE, DATE), (tagging.TAG_VAL_DATE_TIME, DATETIME), (tagging.TAG_VAL_DAY, DD), (tagging.TAG_VAL_HOUR, HOUR), (tagging.TAG_VAL_ISO_DATE, ISO_DATE), (tagging.TAG_VAL_ISO_DATETIME, ISO_DATETIME), (tagging.TAG_VAL_ISO_TIME, ISO_TIME), (tagging.TAG_VAL_ISO_WEEKDAY, ISO_WEEKDAY), (tagging.TAG_VAL_MINUTE, MN), (tagging.TAG_VAL_MONTH, MM), (tagging.TAG_VAL_MONTH_NAME, MONTH_NAME_SHORT), (tagging.TAG_VAL_MONTH_NAME_LONG, MONTH_NAME_LONG), (tagging.TAG_VAL_REGION, REGIONS), (tagging.TAG_VAL_SECOND, SS), (tagging.TAG_VAL_TASK_TAG, TAG_NAME), (tagging.TAG_VAL_TASK, TASK), (tagging.TAG_VAL_TASK_ID, TASK_ID), (tagging.TAG_VAL_TIME, TIME), (tagging.TAG_VAL_TIMEZONE, TIMEZONE), (tagging.TAG_VAL_WEEKDAY, WEEK_NAME_SHORT), (tagging.TAG_VAL_WEEKDAY_LONG, WEEK_NAME_LONG), (tagging.TAG_VAL_YEAR, YYYY), (tags.get("tag-" + tagging.TAG_VAL_TASK), TASK)] if exclude_tags is not None: for e in exclude_tags: for c in checked_tags: if c[0] == e: checked_tags.remove(c) break expression = "&".join([ "(tag-{}=\\^{}$)".format(e[0], (e[1] if e[1] else "").replace( "(", "%(").replace(")", "%)").replace(" ", "\\s")) for e in checked_tags ]) expression += "&!{}=*".format(NAME_OF_TAG_TO_DELETE) if action_placeholders is not None: action_tags = [(p, action_placeholders[p]) for p in action_placeholders] expression += "&" + "&".join([ "(tag-{}={})".format(e[0], (e[1] if e[1] else "").replace( "(", "%(").replace(")", "%)").replace( " ", "\\s" if e[1] and e[1][0] == '\\' else " ")) for e in action_tags ]) return TagFilterExpression(expression).is_match(tags)
def is_selected_resource(aws_service, resource, used_role, taskname, tags_filter, does_resource_supports_tags): # No tags then just use filter method if any if not does_resource_supports_tags: self._logger.debug(DEBUG_RESOURCE_NO_TAGS, resource) return filter_by_action_filter(srv=aws_service, used_role=used_role, r=resource) tags = resource.get("Tags", {}) # name of the tag that holds the list of tasks for this resource tagname = self._task_tag if tags_filter is None: # test if name of the task is in list of tasks in tag value if (tagname not in tags) or (taskname not in tagging.split_task_list( tags[tagname])): self._logger.debug( DEBUG_RESOURCE_NOT_SELECTED, safe_json(resource, indent=2), taskname, ','.join( ["'{}'='{}'".format(t, tags[t]) for t in tags])) return None self._logger.debug(DEBUG_SELECTED_BY_TASK_NAME_IN_TAG_VALUE, safe_json(resource, indent=2), tagname, taskname) else: # using a tag filter, * means any tag if tags_filter != tagging.tag_filter_set.WILDCARD_CHAR: # test if there are any tags matching the tag filter if not TagFilterExpression(tags_filter).is_match(tags): self._logger.debug( DEBUG_RESOURCE_NOT_SELECTED_TAG_FILTER, safe_json(resource, indent=2), taskname, ','.join([ "'{}'='{}'".format(t, tags[t]) for t in tags ])) return None self._logger.debug(DEBUG_SELECTED_BY_TAG_FILTER, safe_json(resource, indent=2), tags, tag_filter_str, taskname) else: self._logger.debug(DEBUG_SELECTED_WILDCARD_TAG_FILTER, safe_json(resource, indent=2), taskname) return filter_by_action_filter(srv=aws_service, used_role=used_role, r=resource) return filter_by_action_filter(srv=aws_service, used_role=used_role, r=resource)
def test_helper_functions(self): self.assertEqual(TagFilterExpression("A=B&CD=!XYZ").get_filters(), ["A=B", "CD=!XYZ"]) self.assertEqual(TagFilterExpression("(A=B&CD=!XYZ)|(A=Z|CD=EFG)").get_filters(), ["A=B", "CD=!XYZ", "A=Z", "CD=EFG"]) self.assertEqual(TagFilterExpression("A&*=!XYZ").get_filters(), ["A", "*=!XYZ"]) self.assertEqual(TagFilterExpression("A=B&CD=!XYZ").get_filter_keys(), {"A", "CD"}) self.assertEqual(TagFilterExpression("(A=B&CD=!XYZ)|(A=Z|CD=EFG)").get_filter_keys(), {"A", "CD"}) self.assertEqual(TagFilterExpression("A&*=!XYZ").get_filter_keys(), {"A", "*"})
def __init__(self, arguments, action_parameters): ActionBase.__init__(self, arguments, action_parameters) self.instance = self._resources_ self.instance_id = self.instance["InstanceId"] self._ec2_client = None # tags on the instance self.tags_on_instance = self.instance.get("Tags", {}) self.volumes = { dev["Ebs"]["VolumeId"]: dev["DeviceName"] for dev in self.instance["BlockDeviceMappings"] } self.root_volume = None for dev in self.volumes: if self.volumes[dev] == self.instance["RootDeviceName"]: self.root_volume = dev self.accounts_with_create_permissions = self.get( PARAM_ACCOUNTS_VOLUME_CREATE_PERMISSIONS, []) self.tag_shared_snapshots = self.get(PARAM_TAG_SHARED_SNAPSHOTS, False) self.copied_instance_tagfilter = TagFilterSet( self.get(PARAM_COPIED_INSTANCE_TAGS, "")) self.copied_volume_tagfilter = TagFilterSet( self.get(PARAM_COPIED_VOLUME_TAGS, "")) self.backup_root_device = self.get(PARAM_BACKUP_ROOT_DEVICE, True) self.backup_data_devices = self.get(PARAM_BACKUP_DATA_DEVICES, True) self.set_snapshot_name = self.get(PARAM_SET_SNAPSHOT_NAME, True) volume_tag_filter = self.get(PARAM_VOLUME_TAG_FILTER, None) self.volume_tag_filter = TagFilterExpression( volume_tag_filter) if volume_tag_filter not in ["", None] else None self._all_volume_tags = None self.result = { "account": self._account_, "region": self._region_, "instance": self.instance_id, "task": self._task_, "volumes": {}, "snapshots": {} }
def _new_tags_triggers_task(self, task): # get the changed tags and the new tak values changed_tag_keys = set( self._event.get("detail", {}).get("changed-tag-keys", [])) tags = self._event.get("detail", {}).get("tags", {}) task_tag_filter_str = task.get(handlers.TASK_TAG_FILTER, None) if task_tag_filter_str is None: # if there is no tag filtering to select resources check if the task that holds the actions is updates task_tag_name = os.getenv(handlers.ENV_AUTOMATOR_TAG_NAME, "") if task_tag_name not in changed_tag_keys: self._logger.debug("Value of task tag {} is not changed", task_tag_name) return False # check if the new value does include the name of this task task_tag_value = tags.get(task_tag_name, "") if not task[handlers.TASK_NAME] in tagging.split_task_list( task_tag_value): self._logger.debug( "Task name \"{}\" not in value \"{}\" of task task {}", task[handlers.TASK_NAME], task_tag_value, task_tag_name) return False return True # there is a tag filter task_tag_filter = TagFilterExpression(task_tag_filter_str) # test if the new tasks match the filter if not task_tag_filter.is_match(tags): self._logger.debug("Tags {} do not match tag filter {}", tags, task_tag_filter_str) return False self._logger.debug("Tags {} do match tag filter {}", tags, task_tag_filter_str) return True
def set_ec2_instance_tags_with_event_loop_check(self, instance_ids, tags_to_set, client=None, region=None): def get_instances(): ec2 = services.create_service("ec2", session=self._session_, service_retry_strategy=get_default_retry_strategy("ec2", context=self._context_)) return list(ec2.describe(services.ec2_service.INSTANCES, InstanceIds=instance_ids, region=region if region is not None else self._region_, tags=True, select="Reservations[*].Instances[].{Tags:Tags,InstanceId:InstanceId}")) def get_ec2_client(): if client is not None: return client methods = ["create_tags", "delete_tags"] return get_client_with_retries("ec2", methods=methods, region=region, session=self._session_, logger=self._logger_) try: if len(tags_to_set) > 0: tagged_instances = instance_ids[:] # before setting the tags check if these tags won't trigger a new execution of the task causing a loop task_events = self.get(ACTION_PARAM_EVENTS, {}) task_change_events = task_events.get(handlers.ec2_tag_event_handler.EC2_TAG_EVENT_SOURCE, {}).get( handlers.TAG_CHANGE_EVENT, []) if handlers.ec2_tag_event_handler.EC2_CHANGED_INSTANCE_TAGS_EVENT in task_change_events: tag_name = os.getenv(handlers.ENV_AUTOMATOR_TAG_NAME) tag_filter_str = self.get(ACTION_PARAM_TAG_FILTER, None) tag_filter = TagFilterExpression(tag_filter_str) if tag_filter_str not in ["", None, "None"] else None for instance in get_instances(): # tags currently on instance instance_tags = instance.get("Tags", {}) # tags that have updated values when setting the tags deleted_tags = {t: tags_to_set[t] for t in tags_to_set if tags_to_set[t] == tagging.TAG_DELETE and t in instance_tags} new_tags = {t: tags_to_set[t] for t in tags_to_set if t not in instance_tags and tags_to_set[t] != tagging.TAG_DELETE} updated_tags = {t: tags_to_set[t] for t in tags_to_set if tags_to_set[t] != tagging.TAG_DELETE and t in instance_tags and instance_tags[t] != tags_to_set[t]} updated_tags.update(new_tags) # if there are updates if any([len(t) > 0 for t in [new_tags, updated_tags, deleted_tags]]): # this will be the new set of tags for the instance updated_instance_tags = copy.deepcopy(instance_tags) for t in deleted_tags: del updated_instance_tags[t] for t in updated_tags: updated_instance_tags[t] = updated_tags[t] # test if we have a tag filter and if the filter matches the new tags if tag_filter is not None: updated_tags_used_in_filter = set(updated_tags).intersection(tag_filter.get_filter_keys()) # tags updated that are in the tag filter if len(updated_tags_used_in_filter) > 0: # test if updated tags trigger the task if tag_filter.is_match(updated_instance_tags): self._logger_.warning(WARN_LOOP_TAG_TAGFILTER, tags_to_set, tag_filter_str, instance["InstanceId"]) tagged_instances.remove(instance["InstanceId"]) # if no tag filter then check if the tag with the Ops Automator tasks does contain the name of the task else: task_list = updated_instance_tags.get(tag_name, "") if tag_name in updated_tags and self._task_ in tagging.split_task_list(task_list): self._logger_.warning(WARN_LOOP_TAG, tags_to_set, task_list, tag_name, instance["InstanceId"]) tagged_instances.remove(instance["InstanceId"]) if len(tagged_instances) > 0: tagging.set_ec2_tags(ec2_client=get_ec2_client(), resource_ids=tagged_instances, tags=tags_to_set) except Exception as ex: self._logger_.error(ERR_SET_TAGS, ','.join(instance_ids), str(ex))
def handle_request(self, use_custom_select=True): """ Handled the cloudwatch rule timer event :return: Started tasks, if any, information """ try: self._logger.info("Handling CloudWatch event {}", safe_json(self._event, indent=3)) result = [] start = datetime.now() dt = self._event_time() config_task = None source_resource_tags = None try: # for all events tasks in configuration for config_task in TaskConfiguration( context=self._context, logger=self._logger).get_tasks(): self._logger.debug_enabled = config_task.get( handlers.TASK_DEBUG, False) if not self._event_triggers_task(task=config_task): continue # tasks that can react to events with a wider resource scope than the actual resource causing the event may # have a filter that can is used to filter based on the tags of the resource event_source_tag_filter = config_task.get( handlers.TASK_EVENT_SOURCE_TAG_FILTER, None) if event_source_tag_filter is not None: if source_resource_tags is None: # get the tags for the source resource of the event session = services.get_session( self._role_executing_triggered_task, logger=self._logger) if session is None: self._logger.error( ERR_NO_SESSION_FOR_GETTING_TAGS) continue try: source_resource_tags = self._source_resource_tags( session, config_task) except Exception as ex: self._logger.error( ERR_GETTING_EVENT_SOURCE_RESOURCE_TAGS, ex) continue self._logger.debug( "Tags for event source resource are {}", source_resource_tags) # apply filter to source resource tags if not TagFilterExpression( event_source_tag_filter).is_match( source_resource_tags): self._logger.debug( "Tags of source resource do not match tag filter {}", event_source_tag_filter) continue task_name = config_task[handlers.TASK_NAME] result.append(task_name) select_parameters = self._select_parameters( self._event_name(), config_task) if select_parameters is None: continue self._logger.debug(DEBUG_EVENT, task_name, self._event_name(), select_parameters, self._event_account(), self._event_region(), safe_json(config_task, indent=3)) # create an event for lambda function that scans for resources for this task lambda_event = { handlers.HANDLER_EVENT_ACTION: handlers.HANDLER_ACTION_SELECT_RESOURCES, handlers.HANDLER_EVENT_CUSTOM_SELECT: use_custom_select, handlers.HANDLER_SELECT_ARGUMENTS: { handlers.HANDLER_EVENT_REGIONS: [self._event_region()], handlers.HANDLER_EVENT_ACCOUNT: self._event_account(), handlers.HANDLER_EVENT_RESOURCE_NAME: config_task[handlers.TASK_RESOURCE_TYPE], }, handlers.HANDLER_EVENT_SOURCE: "{}:{}:{}".format(self._handled_event_source, self._handled_detail_type, self._event_name()), handlers.HANDLER_EVENT_TASK: config_task, handlers.HANDLER_EVENT_TASK_DT: dt } for i in select_parameters: lambda_event[handlers.HANDLER_SELECT_ARGUMENTS][ i] = select_parameters[i] if self._event_resources() is not None: self._logger.debug( DEBUG_EVENT_RESOURCES, safe_json(self._event_resources(), indent=3)) lambda_event[ handlers. HANDLER_SELECT_RESOURCES] = self._event_resources( ) if not handlers.running_local(self._context): # start lambda function to scan for task resources payload = str.encode(safe_json(lambda_event)) client = get_client_with_retries("lambda", ["invoke"], context=self._context, logger=self._logger) client.invoke_with_retries( FunctionName=self._context.function_name, InvocationType="Event", LogType="None", Payload=payload) else: # or if not running in lambda environment pass event to main task handler lambda_handler(lambda_event, None) return safe_dict({ "datetime": datetime.now().isoformat(), "running-time": (datetime.now() - start).total_seconds(), "event-datetime": dt, "started-tasks": result }) except ValueError as ex: self._logger.error(ERR_HANDLING_EVENT_IN_BASE_HANDLER, ex, safe_json(config_task, indent=2)) finally: self._logger.flush()
def test_is_match(self): tags1 = {"A": "B"} tags2 = {"CD": "EFG"} tags3 = copy.copy(tags1) tags3.update(copy.copy(tags2)) self.assertTrue(TagFilterExpression("A=B").is_match(tags1)) self.assertTrue(TagFilterExpression("A=B").is_match(tags3)) self.assertFalse(TagFilterExpression("A=B").is_match(tags2)) self.assertTrue(TagFilterExpression("A=B&CD=EFG").is_match(tags3)) self.assertTrue(TagFilterExpression("A=!B|CD=EFG").is_match(tags3)) self.assertFalse(TagFilterExpression("A=!B|CD=EFG").is_match(tags1)) self.assertFalse(TagFilterExpression("A=!B|CD=!EFG").is_match(tags3)) self.assertFalse(TagFilterExpression("A=!B&CD=!EFG").is_match(tags3)) self.assertFalse(TagFilterExpression("!A&CD=EFG").is_match(tags3)) self.assertTrue(TagFilterExpression("!A=B|CD=EFG").is_match(tags3)) self.assertFalse(TagFilterExpression("A=B&!CD=EFG").is_match(tags3)) self.assertFalse(TagFilterExpression("!A=B|!CD=E*").is_match(tags3)) self.assertFalse(TagFilterExpression("!A=B|!CD=E*").is_match(tags1)) self.assertTrue(TagFilterExpression("(A=X|A=B").is_match(tags1)) self.assertFalse(TagFilterExpression("(A=X|A=B").is_match(tags2)) self.assertTrue(TagFilterExpression("(A=X|A=Y|CD=*").is_match(tags3)) self.assertTrue(TagFilterExpression("(A=B&CD=!XYZ").is_match(tags3)) self.assertTrue(TagFilterExpression("(A=B&CD=XYZ)|(A=Z|CD=EFG)").is_match(tags3)) self.assertFalse(TagFilterExpression("A=B&!CD=E*").is_match(tags3)) self.assertFalse(TagFilterExpression("A=B&!CD=!E*").is_match(tags3)) self.assertTrue(TagFilterExpression("A=B|!CD=!E*").is_match(tags3)) self.assertTrue(TagFilterExpression("A=1,2,3").is_match({"A": "1,2,3"})) self.assertTrue(TagFilterExpression("A=*").is_match({"A": "1,2,3"}))