Fix events rule ARN for custom event bus (#3809)
* Fix events rule ARN for custom event bus * Fix cloudformation test
This commit is contained in:
parent
57aa83e6c1
commit
9a020e6120
@ -27,23 +27,34 @@ from uuid import uuid4
|
|||||||
class Rule(CloudFormationModel):
|
class Rule(CloudFormationModel):
|
||||||
Arn = namedtuple("Arn", ["service", "resource_type", "resource_id"])
|
Arn = namedtuple("Arn", ["service", "resource_type", "resource_id"])
|
||||||
|
|
||||||
def _generate_arn(self, name):
|
|
||||||
return "arn:aws:events:{region_name}:{account}:rule/{name}".format(
|
|
||||||
region_name=self.region_name, account=ACCOUNT_ID, name=name
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, name, region_name, **kwargs):
|
def __init__(self, name, region_name, **kwargs):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.region_name = region_name
|
self.region_name = region_name
|
||||||
self.arn = kwargs.get("Arn") or self._generate_arn(name)
|
|
||||||
self.event_pattern = kwargs.get("EventPattern")
|
self.event_pattern = kwargs.get("EventPattern")
|
||||||
self.schedule_exp = kwargs.get("ScheduleExpression")
|
self.schedule_exp = kwargs.get("ScheduleExpression")
|
||||||
self.state = kwargs.get("State") or "ENABLED"
|
self.state = kwargs.get("State") or "ENABLED"
|
||||||
self.description = kwargs.get("Description")
|
self.description = kwargs.get("Description")
|
||||||
self.role_arn = kwargs.get("RoleArn")
|
self.role_arn = kwargs.get("RoleArn")
|
||||||
self.event_bus_name = kwargs.get("EventBusName") or "default"
|
self.managed_by = kwargs.get("ManagedBy") # can only be set by AWS services
|
||||||
|
self.event_bus_name = kwargs.get("EventBusName")
|
||||||
|
self.created_by = ACCOUNT_ID
|
||||||
self.targets = []
|
self.targets = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arn(self):
|
||||||
|
event_bus_name = (
|
||||||
|
""
|
||||||
|
if self.event_bus_name == "default"
|
||||||
|
else "{}/".format(self.event_bus_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
return "arn:aws:events:{region}:{account_id}:rule/{event_bus_name}{name}".format(
|
||||||
|
region=self.region_name,
|
||||||
|
account_id=ACCOUNT_ID,
|
||||||
|
event_bus_name=event_bus_name,
|
||||||
|
name=self.name,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -196,6 +207,8 @@ class Rule(CloudFormationModel):
|
|||||||
cls, resource_name, cloudformation_json, region_name
|
cls, resource_name, cloudformation_json, region_name
|
||||||
):
|
):
|
||||||
properties = cloudformation_json["Properties"]
|
properties = cloudformation_json["Properties"]
|
||||||
|
properties.setdefault("EventBusName", "default")
|
||||||
|
|
||||||
event_backend = events_backends[region_name]
|
event_backend = events_backends[region_name]
|
||||||
event_name = resource_name
|
event_name = resource_name
|
||||||
return event_backend.put_rule(name=event_name, **properties)
|
return event_backend.put_rule(name=event_name, **properties)
|
||||||
@ -682,6 +695,11 @@ class EventsBackend(BaseBackend):
|
|||||||
rule.event_bus_name = kwargs.get("EventBusName") or rule.event_bus_name
|
rule.event_bus_name = kwargs.get("EventBusName") or rule.event_bus_name
|
||||||
|
|
||||||
def put_rule(self, name, **kwargs):
|
def put_rule(self, name, **kwargs):
|
||||||
|
if kwargs.get("ScheduleExpression") and kwargs.get("EventBusName") != "default":
|
||||||
|
raise ValidationException(
|
||||||
|
"ScheduleExpression is supported only on the default event bus."
|
||||||
|
)
|
||||||
|
|
||||||
if name in self.rules:
|
if name in self.rules:
|
||||||
self.update_rule(self.rules[name], **kwargs)
|
self.update_rule(self.rules[name], **kwargs)
|
||||||
new_rule = self.rules[name]
|
new_rule = self.rules[name]
|
||||||
@ -932,6 +950,7 @@ class EventsBackend(BaseBackend):
|
|||||||
**{
|
**{
|
||||||
"EventPattern": json.dumps(rule_event_pattern),
|
"EventPattern": json.dumps(rule_event_pattern),
|
||||||
"EventBusName": event_bus.name,
|
"EventBusName": event_bus.name,
|
||||||
|
"ManagedBy": "prod.vhs.events.aws.internal",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.put_targets(
|
self.put_targets(
|
||||||
|
@ -25,7 +25,9 @@ class EventsHandler(BaseResponse):
|
|||||||
"Description": rule.description,
|
"Description": rule.description,
|
||||||
"ScheduleExpression": rule.schedule_exp,
|
"ScheduleExpression": rule.schedule_exp,
|
||||||
"RoleArn": rule.role_arn,
|
"RoleArn": rule.role_arn,
|
||||||
|
"ManagedBy": rule.managed_by,
|
||||||
"EventBusName": rule.event_bus_name,
|
"EventBusName": rule.event_bus_name,
|
||||||
|
"CreatedBy": rule.created_by,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -168,10 +170,7 @@ class EventsHandler(BaseResponse):
|
|||||||
state = self._get_param("State")
|
state = self._get_param("State")
|
||||||
desc = self._get_param("Description")
|
desc = self._get_param("Description")
|
||||||
role_arn = self._get_param("RoleArn")
|
role_arn = self._get_param("RoleArn")
|
||||||
event_bus_name = self._get_param("EventBusName")
|
event_bus_name = self._get_param("EventBusName", "default")
|
||||||
|
|
||||||
if not name:
|
|
||||||
return self.error("ValidationException", "Parameter Name is required.")
|
|
||||||
|
|
||||||
if event_pattern:
|
if event_pattern:
|
||||||
try:
|
try:
|
||||||
|
@ -88,7 +88,6 @@ def test_put_rule():
|
|||||||
"Name": "my-event",
|
"Name": "my-event",
|
||||||
"ScheduleExpression": "rate(5 minutes)",
|
"ScheduleExpression": "rate(5 minutes)",
|
||||||
"EventPattern": '{"source": ["test-source"]}',
|
"EventPattern": '{"source": ["test-source"]}',
|
||||||
"EventBusName": "test-bus",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.put_rule(**rule_data)
|
client.put_rule(**rule_data)
|
||||||
@ -99,10 +98,34 @@ def test_put_rule():
|
|||||||
rules[0]["Name"].should.equal(rule_data["Name"])
|
rules[0]["Name"].should.equal(rule_data["Name"])
|
||||||
rules[0]["ScheduleExpression"].should.equal(rule_data["ScheduleExpression"])
|
rules[0]["ScheduleExpression"].should.equal(rule_data["ScheduleExpression"])
|
||||||
rules[0]["EventPattern"].should.equal(rule_data["EventPattern"])
|
rules[0]["EventPattern"].should.equal(rule_data["EventPattern"])
|
||||||
rules[0]["EventBusName"].should.equal(rule_data["EventBusName"])
|
|
||||||
rules[0]["State"].should.equal("ENABLED")
|
rules[0]["State"].should.equal("ENABLED")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_events
|
||||||
|
def test_put_rule_error_schedule_expression_custom_event_bus():
|
||||||
|
# given
|
||||||
|
client = boto3.client("events", "eu-central-1")
|
||||||
|
event_bus_name = "test-bus"
|
||||||
|
client.create_event_bus(Name=event_bus_name)
|
||||||
|
|
||||||
|
# when
|
||||||
|
with pytest.raises(ClientError) as e:
|
||||||
|
client.put_rule(
|
||||||
|
Name="test-rule",
|
||||||
|
ScheduleExpression="rate(5 minutes)",
|
||||||
|
EventBusName=event_bus_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# then
|
||||||
|
ex = e.value
|
||||||
|
ex.operation_name.should.equal("PutRule")
|
||||||
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||||
|
ex.response["Error"]["Code"].should.contain("ValidationException")
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"ScheduleExpression is supported only on the default event bus."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@mock_events
|
@mock_events
|
||||||
def test_list_rules():
|
def test_list_rules():
|
||||||
client = generate_environment()
|
client = generate_environment()
|
||||||
@ -118,15 +141,51 @@ def test_describe_rule():
|
|||||||
client = generate_environment()
|
client = generate_environment()
|
||||||
response = client.describe_rule(Name=rule_name)
|
response = client.describe_rule(Name=rule_name)
|
||||||
|
|
||||||
assert response is not None
|
response["Name"].should.equal(rule_name)
|
||||||
assert response.get("Name") == rule_name
|
response["Arn"].should.equal(
|
||||||
|
"arn:aws:events:us-west-2:{0}:rule/{1}".format(ACCOUNT_ID, rule_name)
|
||||||
rule_arn = response.get("Arn")
|
|
||||||
assert rule_arn == "arn:aws:events:us-west-2:{account}:rule/{name}".format(
|
|
||||||
account=ACCOUNT_ID, name=rule_name
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_events
|
||||||
|
def test_describe_rule_with_event_bus_name():
|
||||||
|
# given
|
||||||
|
client = boto3.client("events", "eu-central-1")
|
||||||
|
event_bus_name = "test-bus"
|
||||||
|
rule_name = "test-rule"
|
||||||
|
client.create_event_bus(Name=event_bus_name)
|
||||||
|
client.put_rule(
|
||||||
|
Name=rule_name,
|
||||||
|
EventPattern=json.dumps({"account": [ACCOUNT_ID]}),
|
||||||
|
State="DISABLED",
|
||||||
|
Description="test rule",
|
||||||
|
RoleArn="arn:aws:iam::{}:role/test-role".format(ACCOUNT_ID),
|
||||||
|
EventBusName=event_bus_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# when
|
||||||
|
response = client.describe_rule(Name=rule_name, EventBusName=event_bus_name)
|
||||||
|
|
||||||
|
# then
|
||||||
|
response["Arn"].should.equal(
|
||||||
|
"arn:aws:events:eu-central-1:{0}:rule/{1}/{2}".format(
|
||||||
|
ACCOUNT_ID, event_bus_name, rule_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
response["CreatedBy"].should.equal(ACCOUNT_ID)
|
||||||
|
response["Description"].should.equal("test rule")
|
||||||
|
response["EventBusName"].should.equal(event_bus_name)
|
||||||
|
json.loads(response["EventPattern"]).should.equal({"account": [ACCOUNT_ID]})
|
||||||
|
response["Name"].should.equal(rule_name)
|
||||||
|
response["RoleArn"].should.equal(
|
||||||
|
"arn:aws:iam::{}:role/test-role".format(ACCOUNT_ID)
|
||||||
|
)
|
||||||
|
response["State"].should.equal("DISABLED")
|
||||||
|
|
||||||
|
response.should_not.have.key("ManagedBy")
|
||||||
|
response.should_not.have.key("ScheduleExpression")
|
||||||
|
|
||||||
|
|
||||||
@mock_events
|
@mock_events
|
||||||
def test_enable_disable_rule():
|
def test_enable_disable_rule():
|
||||||
rule_name = get_random_rule()["Name"]
|
rule_name = get_random_rule()["Name"]
|
||||||
@ -791,10 +850,11 @@ def test_list_tags_for_resource_error_unknown_arn():
|
|||||||
def test_create_archive():
|
def test_create_archive():
|
||||||
# given
|
# given
|
||||||
client = boto3.client("events", "eu-central-1")
|
client = boto3.client("events", "eu-central-1")
|
||||||
|
archive_name = "test-archive"
|
||||||
|
|
||||||
# when
|
# when
|
||||||
response = client.create_archive(
|
response = client.create_archive(
|
||||||
ArchiveName="test-archive",
|
ArchiveName=archive_name,
|
||||||
EventSourceArn="arn:aws:events:eu-central-1:{}:event-bus/default".format(
|
EventSourceArn="arn:aws:events:eu-central-1:{}:event-bus/default".format(
|
||||||
ACCOUNT_ID
|
ACCOUNT_ID
|
||||||
),
|
),
|
||||||
@ -802,11 +862,31 @@ def test_create_archive():
|
|||||||
|
|
||||||
# then
|
# then
|
||||||
response["ArchiveArn"].should.equal(
|
response["ArchiveArn"].should.equal(
|
||||||
"arn:aws:events:eu-central-1:{}:archive/test-archive".format(ACCOUNT_ID)
|
"arn:aws:events:eu-central-1:{0}:archive/{1}".format(ACCOUNT_ID, archive_name)
|
||||||
)
|
)
|
||||||
response["CreationTime"].should.be.a(datetime)
|
response["CreationTime"].should.be.a(datetime)
|
||||||
response["State"].should.equal("ENABLED")
|
response["State"].should.equal("ENABLED")
|
||||||
|
|
||||||
|
# check for archive rule existence
|
||||||
|
rule_name = "Events-Archive-{}".format(archive_name)
|
||||||
|
response = client.describe_rule(Name=rule_name)
|
||||||
|
|
||||||
|
response["Arn"].should.equal(
|
||||||
|
"arn:aws:events:eu-central-1:{0}:rule/{1}".format(ACCOUNT_ID, rule_name)
|
||||||
|
)
|
||||||
|
response["CreatedBy"].should.equal(ACCOUNT_ID)
|
||||||
|
response["EventBusName"].should.equal("default")
|
||||||
|
json.loads(response["EventPattern"]).should.equal(
|
||||||
|
{"replay-name": [{"exists": False}]}
|
||||||
|
)
|
||||||
|
response["ManagedBy"].should.equal("prod.vhs.events.aws.internal")
|
||||||
|
response["Name"].should.equal(rule_name)
|
||||||
|
response["State"].should.equal("ENABLED")
|
||||||
|
|
||||||
|
response.should_not.have.key("Description")
|
||||||
|
response.should_not.have.key("RoleArn")
|
||||||
|
response.should_not.have.key("ScheduleExpression")
|
||||||
|
|
||||||
|
|
||||||
@mock_events
|
@mock_events
|
||||||
def test_create_archive_custom_event_bus():
|
def test_create_archive_custom_event_bus():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user