From 93e4d4aa9adc837ca1ff4a60fdfd765441933ff0 Mon Sep 17 00:00:00 2001 From: gruebel Date: Fri, 1 Nov 2019 09:52:06 +0100 Subject: [PATCH] Add events.create_event_bus --- IMPLEMENTATION_COVERAGE.md | 4 +-- moto/events/models.py | 42 ++++++++++++++++++++++++++++++++ moto/events/responses.py | 8 ++++++ tests/test_events/test_events.py | 37 ++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index cf9f40f80..ab66bf016 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -2713,9 +2713,9 @@ - [ ] upgrade_elasticsearch_domain ## events -48% implemented +51% implemented - [ ] activate_event_source -- [ ] create_event_bus +- [X] create_event_bus - [ ] create_partner_event_source - [ ] deactivate_event_source - [ ] delete_event_bus diff --git a/moto/events/models.py b/moto/events/models.py index e69062b2c..b1d9bf25a 100644 --- a/moto/events/models.py +++ b/moto/events/models.py @@ -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,18 @@ class Rule(BaseModel): self.targets.pop(index) +class EventBus(BaseModel): + def __init__(self, region_name, name): + self.region = region_name + self.name = name + + @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 + ) + + class EventsBackend(BaseBackend): ACCOUNT_ID = re.compile(r"^(\d{1,12}|\*)$") STATEMENT_ID = re.compile(r"^[a-zA-Z0-9-_]{1,64}$") @@ -66,12 +79,19 @@ class EventsBackend(BaseBackend): 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]) @@ -264,6 +284,28 @@ class EventsBackend(BaseBackend): policy_json = json.dumps(policy) return {"Policy": policy_json, "Name": "default", "Arn": arn} + 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] + available_regions = boto3.session.Session().get_available_regions("events") events_backends = {region: EventsBackend(region) for region in available_regions} diff --git a/moto/events/responses.py b/moto/events/responses.py index 39c5c75dc..f4a6dcce9 100644 --- a/moto/events/responses.py +++ b/moto/events/responses.py @@ -255,3 +255,11 @@ class EventsHandler(BaseResponse): def describe_event_bus(self): return json.dumps(self.events_backend.describe_event_bus()) + + 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 diff --git a/tests/test_events/test_events.py b/tests/test_events/test_events.py index d5bfdf782..ebd224da1 100644 --- a/tests/test_events/test_events.py +++ b/tests/test_events/test_events.py @@ -1,6 +1,7 @@ import random import boto3 import json +import sure # noqa from moto.events import mock_events from botocore.exceptions import ClientError @@ -220,3 +221,39 @@ def test_put_events(): with assert_raises(ClientError): client.put_events(Entries=[event] * 20) + + +@mock_events +def test_create_event_bus(): + client = boto3.client("events", "us-east-1") + response = client.create_event_bus(Name="test-bus") + + response["EventBusArn"].should.equal( + "arn:aws:events:us-east-1:123456789012:event-bus/test-bus" + ) + + +@mock_events +def test_create_event_bus_errors(): + client = boto3.client("events", "us-east-1") + response = client.create_event_bus(Name="test-bus") + + client.create_event_bus.when.called_with(Name="test-bus").should.throw( + ClientError, "Event bus test-bus already exists." + ) + + # the 'default' name is already used for the account's default event bus. + client.create_event_bus.when.called_with(Name="default").should.throw( + ClientError, "Event bus default already exists." + ) + + # non partner event buses can't contain the '/' character + client.create_event_bus.when.called_with(Name="test/test-bus").should.throw( + ClientError, "Event bus name must not contain '/'." + ) + + client.create_event_bus.when.called_with( + Name="aws.partner/test/test-bus", EventSourceName="aws.partner/test/test-bus" + ).should.throw( + ClientError, "Event source aws.partner/test/test-bus does not exist." + )