Ejemplo n.º 1
0
Archivo: s3.py Proyecto: auspost/gordon
    def __init__(self, bucket_notification_configuration, **kwargs):
        self.settings = kwargs
        self.bucket_notification_configuration = bucket_notification_configuration
        self.events = []

        # Validate all notifications have an id. This important because
        # we'll rely on this id to create/modify/delete notifactions
        if 'id' in self.settings:
            self.id = self.settings['id']
        else:
            raise exceptions.ResourceValidationError(
                ("You need to define an id which identifies the "
                 "notification {}").format(self.settings))

        # Validate that events is present, and that it contains valid values
        if 'events' in self.settings and self.settings['events']:
            for event in self.settings['events']:
                event_match = re.match(r's3\:(\w+|\*)(?:\:(\w+|\*))?', event)
                if event_match:
                    self.events.append([event] + list(event_match.groups()))
                else:
                    raise exceptions.ResourceValidationError(
                        "Invalid event {}".format(event))
        else:
            raise exceptions.ResourceValidationError(
                ("You need to define a list of events for the "
                 "notification {}").format(self.name))

        # Validate that filters are a subset of (prefix, suffix) and keys
        # are not duplicated.
        _filters = self.settings.get('key_filters', {})
        if set(_filters.values()) > set(('prefix', 'suffix')):
            raise exceptions.ResourceValidationError(
                """You can't create filters for '{}'.""".format(
                    ', '.join(_filters)))
        else:
            self.filters = [(k, v) for k, v in six.iteritems(_filters)]

        # Check if a source account has been added for the event.
        if 'source_account' in self.settings and self.settings[
                'source_account']:
            account = self.settings['source_account']
            account_match = re.match("^[0-9]{12}$", account)
            if account_match:
                self.source_account = account
            else:
                raise exceptions.ResourceValidationError(
                    ("The source account for the event must be a "
                     "12 digit number: {}").format(account))
        else:
            self.source_account = troposphere.Ref(troposphere.AWS_ACCOUNT_ID)
Ejemplo n.º 2
0
 def validate(self):
     """Validate that there are no any other resources in the project which
     try to register notifications for the same bucket than this resource"""
     for resource in \
             (r for r in self.project.get_resources() if isinstance(r, self.__class__) and r.bucket == self.bucket):
         raise exceptions.ResourceValidationError(
             ("Both resources '{}' and '{}', registers notifications for "
              "the bucket '{}'. Because AWS API limitations we need you to "
              "register all notifications of one bucket in the same "
              "resource.").format(self, resource, self.bucket))
Ejemplo n.º 3
0
    def _validate_notifications(self):
        # Validate that notifications events don't overlap
        top_events_for_bucket = set()
        sub_events_for_top = defaultdict(list)
        for notification_id, notification in six.iteritems(
                self._notifications):
            for event, top, sub in notification.events:
                if top in top_events_for_bucket or \
                   top in sub_events_for_top or\
                   sub in sub_events_for_top.get(top, []):
                    raise exceptions.ResourceValidationError(
                        ("Event {} overlaps with some other event "
                         "registered for the same bucket.").format(event))
                else:
                    top_events_for_bucket.add(top)
                    sub_events_for_top[top].append(sub)

        # Validate that all key prefix/suffix filters for a bucket
        # don't overlap one to each other.
        all_filters = defaultdict(list)
        for notification_id, notification in six.iteritems(
                self._notifications):
            for name, value in notification.filters:
                all_filters[name].append(value)

        overlap_checks = {'prefix': 'startswith', 'suffix': 'endswith'}
        for filter_type, values in six.iteritems(all_filters):
            check = overlap_checks.get(filter_type)
            # Don't check fields that are Ref instances
            # since Refs aren't bound until apply
            if isinstance(check, Ref):
                continue
            overlaps = [
                sum([int(getattr(v, check)(z)) for z in values])
                for v in values
            ]
            if sum(overlaps) > len(values):
                raise exceptions.ResourceValidationError(
                    "One or more {} filters overlap one to each other {}.".
                    format(filter_type, ', '.join(values)))
Ejemplo n.º 4
0
    def from_dict(cls, data, id, bucket_notification_configuration):
        notification_type = set(
            ('lambda', 'topic', 'queue')) & set(data.keys())

        if len(notification_type) != 1:
            raise exceptions.ResourceValidationError(
                ("You need to define either a lamda, a queue or a topic "
                 "as destination of your notification {}"
                 ).format(bucket_notification_configuration))

        return {
            'lambda': LambdaFunctionNotification,
            'queue': QueueNotification,
            'topic': TopicNotification
        }.get(
            list(notification_type)[0]
        )(id=id,
          bucket_notification_configuration=bucket_notification_configuration,
          **data)
Ejemplo n.º 5
0
Archivo: s3.py Proyecto: auspost/gordon
    def _validate_notifications(self):
        # Validate that all key prefix/suffix filters for a bucket
        # don't overlap one to each other.
        all_filters = defaultdict(list)
        for notification_id, notification in six.iteritems(
                self._notifications):
            for name, value in notification.filters:
                all_filters[name].append(value)

        overlap_checks = {'prefix': 'startswith', 'suffix': 'endswith'}
        for filter_type, values in six.iteritems(all_filters):
            check = overlap_checks.get(filter_type)
            # Don't check fields that are Ref instances
            # since Refs aren't bound until apply
            if isinstance(check, Ref):
                continue
            overlaps = [
                sum([int(getattr(v, check)(z)) for z in values])
                for v in values
            ]
            if sum(overlaps) > len(values):
                raise exceptions.ResourceValidationError(
                    "One or more {} filters overlap one to each other {}.".
                    format(filter_type, ', '.join(values)))