Merge pull request #2536 from edekadigital/add-events-event-bus
Add events event bus
This commit is contained in:
commit
dddb9dd4d2
4 changed files with 403 additions and 35 deletions
|
|
@ -5,6 +5,7 @@ import boto3
|
|||
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
from moto.core import BaseBackend, BaseModel
|
||||
from moto.sts.models import ACCOUNT_ID
|
||||
|
||||
|
||||
class Rule(BaseModel):
|
||||
|
|
@ -54,6 +55,42 @@ class Rule(BaseModel):
|
|||
self.targets.pop(index)
|
||||
|
||||
|
||||
class EventBus(BaseModel):
|
||||
def __init__(self, region_name, name):
|
||||
self.region = region_name
|
||||
self.name = name
|
||||
|
||||
self._permissions = {}
|
||||
|
||||
@property
|
||||
def arn(self):
|
||||
return "arn:aws:events:{region}:{account_id}:event-bus/{name}".format(
|
||||
region=self.region, account_id=ACCOUNT_ID, name=self.name
|
||||
)
|
||||
|
||||
@property
|
||||
def policy(self):
|
||||
if not len(self._permissions):
|
||||
return None
|
||||
|
||||
policy = {"Version": "2012-10-17", "Statement": []}
|
||||
|
||||
for sid, permission in self._permissions.items():
|
||||
policy["Statement"].append(
|
||||
{
|
||||
"Sid": sid,
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::{}:root".format(permission["Principal"])
|
||||
},
|
||||
"Action": permission["Action"],
|
||||
"Resource": self.arn,
|
||||
}
|
||||
)
|
||||
|
||||
return json.dumps(policy)
|
||||
|
||||
|
||||
class EventsBackend(BaseBackend):
|
||||
ACCOUNT_ID = re.compile(r"^(\d{1,12}|\*)$")
|
||||
STATEMENT_ID = re.compile(r"^[a-zA-Z0-9-_]{1,64}$")
|
||||
|
|
@ -65,13 +102,19 @@ class EventsBackend(BaseBackend):
|
|||
self.rules_order = []
|
||||
self.next_tokens = {}
|
||||
self.region_name = region_name
|
||||
self.permissions = {}
|
||||
self.event_buses = {}
|
||||
self.event_sources = {}
|
||||
|
||||
self._add_default_event_bus()
|
||||
|
||||
def reset(self):
|
||||
region_name = self.region_name
|
||||
self.__dict__ = {}
|
||||
self.__init__(region_name)
|
||||
|
||||
def _add_default_event_bus(self):
|
||||
self.event_buses["default"] = EventBus(self.region_name, "default")
|
||||
|
||||
def _get_rule_by_index(self, i):
|
||||
return self.rules.get(self.rules_order[i])
|
||||
|
||||
|
|
@ -221,9 +264,17 @@ class EventsBackend(BaseBackend):
|
|||
def test_event_pattern(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def put_permission(self, action, principal, statement_id):
|
||||
def put_permission(self, event_bus_name, action, principal, statement_id):
|
||||
if not event_bus_name:
|
||||
event_bus_name = "default"
|
||||
|
||||
event_bus = self.describe_event_bus(event_bus_name)
|
||||
|
||||
if action is None or action != "events:PutEvents":
|
||||
raise JsonRESTError("InvalidParameterValue", "Action must be PutEvents")
|
||||
raise JsonRESTError(
|
||||
"ValidationException",
|
||||
"Provided value in parameter 'action' is not supported.",
|
||||
)
|
||||
|
||||
if principal is None or self.ACCOUNT_ID.match(principal) is None:
|
||||
raise JsonRESTError(
|
||||
|
|
@ -235,34 +286,81 @@ class EventsBackend(BaseBackend):
|
|||
"InvalidParameterValue", "StatementId must match ^[a-zA-Z0-9-_]{1,64}$"
|
||||
)
|
||||
|
||||
self.permissions[statement_id] = {"action": action, "principal": principal}
|
||||
event_bus._permissions[statement_id] = {
|
||||
"Action": action,
|
||||
"Principal": principal,
|
||||
}
|
||||
|
||||
def remove_permission(self, statement_id):
|
||||
try:
|
||||
del self.permissions[statement_id]
|
||||
except KeyError:
|
||||
raise JsonRESTError("ResourceNotFoundException", "StatementId not found")
|
||||
def remove_permission(self, event_bus_name, statement_id):
|
||||
if not event_bus_name:
|
||||
event_bus_name = "default"
|
||||
|
||||
def describe_event_bus(self):
|
||||
arn = "arn:aws:events:{0}:000000000000:event-bus/default".format(
|
||||
self.region_name
|
||||
)
|
||||
statements = []
|
||||
for statement_id, data in self.permissions.items():
|
||||
statements.append(
|
||||
{
|
||||
"Sid": statement_id,
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::{0}:root".format(data["principal"])
|
||||
},
|
||||
"Action": data["action"],
|
||||
"Resource": arn,
|
||||
}
|
||||
event_bus = self.describe_event_bus(event_bus_name)
|
||||
|
||||
if not len(event_bus._permissions):
|
||||
raise JsonRESTError(
|
||||
"ResourceNotFoundException", "EventBus does not have a policy."
|
||||
)
|
||||
policy = {"Version": "2012-10-17", "Statement": statements}
|
||||
policy_json = json.dumps(policy)
|
||||
return {"Policy": policy_json, "Name": "default", "Arn": arn}
|
||||
|
||||
if not event_bus._permissions.pop(statement_id, None):
|
||||
raise JsonRESTError(
|
||||
"ResourceNotFoundException",
|
||||
"Statement with the provided id does not exist.",
|
||||
)
|
||||
|
||||
def describe_event_bus(self, name):
|
||||
if not name:
|
||||
name = "default"
|
||||
|
||||
event_bus = self.event_buses.get(name)
|
||||
|
||||
if not event_bus:
|
||||
raise JsonRESTError(
|
||||
"ResourceNotFoundException",
|
||||
"Event bus {} does not exist.".format(name),
|
||||
)
|
||||
|
||||
return event_bus
|
||||
|
||||
def create_event_bus(self, name, event_source_name):
|
||||
if name in self.event_buses:
|
||||
raise JsonRESTError(
|
||||
"ResourceAlreadyExistsException",
|
||||
"Event bus {} already exists.".format(name),
|
||||
)
|
||||
|
||||
if not event_source_name and "/" in name:
|
||||
raise JsonRESTError(
|
||||
"ValidationException", "Event bus name must not contain '/'."
|
||||
)
|
||||
|
||||
if event_source_name and event_source_name not in self.event_sources:
|
||||
raise JsonRESTError(
|
||||
"ResourceNotFoundException",
|
||||
"Event source {} does not exist.".format(event_source_name),
|
||||
)
|
||||
|
||||
self.event_buses[name] = EventBus(self.region_name, name)
|
||||
|
||||
return self.event_buses[name]
|
||||
|
||||
def list_event_buses(self, name_prefix):
|
||||
if name_prefix:
|
||||
return [
|
||||
event_bus
|
||||
for event_bus in self.event_buses.values()
|
||||
if event_bus.name.startswith(name_prefix)
|
||||
]
|
||||
|
||||
return list(self.event_buses.values())
|
||||
|
||||
def delete_event_bus(self, name):
|
||||
if name == "default":
|
||||
raise JsonRESTError(
|
||||
"ValidationException", "Cannot delete event bus default."
|
||||
)
|
||||
|
||||
self.event_buses.pop(name, None)
|
||||
|
||||
|
||||
available_regions = boto3.session.Session().get_available_regions("events")
|
||||
|
|
|
|||
|
|
@ -238,20 +238,68 @@ class EventsHandler(BaseResponse):
|
|||
pass
|
||||
|
||||
def put_permission(self):
|
||||
event_bus_name = self._get_param("EventBusName")
|
||||
action = self._get_param("Action")
|
||||
principal = self._get_param("Principal")
|
||||
statement_id = self._get_param("StatementId")
|
||||
|
||||
self.events_backend.put_permission(action, principal, statement_id)
|
||||
self.events_backend.put_permission(
|
||||
event_bus_name, action, principal, statement_id
|
||||
)
|
||||
|
||||
return ""
|
||||
|
||||
def remove_permission(self):
|
||||
event_bus_name = self._get_param("EventBusName")
|
||||
statement_id = self._get_param("StatementId")
|
||||
|
||||
self.events_backend.remove_permission(statement_id)
|
||||
self.events_backend.remove_permission(event_bus_name, statement_id)
|
||||
|
||||
return ""
|
||||
|
||||
def describe_event_bus(self):
|
||||
return json.dumps(self.events_backend.describe_event_bus())
|
||||
name = self._get_param("Name")
|
||||
|
||||
event_bus = self.events_backend.describe_event_bus(name)
|
||||
response = {
|
||||
"Name": event_bus.name,
|
||||
"Arn": event_bus.arn,
|
||||
}
|
||||
|
||||
if event_bus.policy:
|
||||
response["Policy"] = event_bus.policy
|
||||
|
||||
return json.dumps(response), self.response_headers
|
||||
|
||||
def create_event_bus(self):
|
||||
name = self._get_param("Name")
|
||||
event_source_name = self._get_param("EventSourceName")
|
||||
|
||||
event_bus = self.events_backend.create_event_bus(name, event_source_name)
|
||||
|
||||
return json.dumps({"EventBusArn": event_bus.arn}), self.response_headers
|
||||
|
||||
def list_event_buses(self):
|
||||
name_prefix = self._get_param("NamePrefix")
|
||||
# ToDo: add 'NextToken' & 'Limit' parameters
|
||||
|
||||
response = []
|
||||
for event_bus in self.events_backend.list_event_buses(name_prefix):
|
||||
event_bus_response = {
|
||||
"Name": event_bus.name,
|
||||
"Arn": event_bus.arn,
|
||||
}
|
||||
|
||||
if event_bus.policy:
|
||||
event_bus_response["Policy"] = event_bus.policy
|
||||
|
||||
response.append(event_bus_response)
|
||||
|
||||
return json.dumps({"EventBuses": response}), self.response_headers
|
||||
|
||||
def delete_event_bus(self):
|
||||
name = self._get_param("Name")
|
||||
|
||||
self.events_backend.delete_event_bus(name)
|
||||
|
||||
return "", self.response_headers
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue