CF - detect changesets without changes (#5058)
This commit is contained in:
parent
96996b6b46
commit
be52b4d7a2
@ -251,6 +251,17 @@ class FakeStack(BaseModel):
|
|||||||
self.creation_time = datetime.utcnow()
|
self.creation_time = datetime.utcnow()
|
||||||
self.status = "CREATE_PENDING"
|
self.status = "CREATE_PENDING"
|
||||||
|
|
||||||
|
def has_template(self, other_template):
|
||||||
|
our_template = (
|
||||||
|
self.template
|
||||||
|
if isinstance(self.template, dict)
|
||||||
|
else json.loads(self.template)
|
||||||
|
)
|
||||||
|
return our_template == json.loads(other_template)
|
||||||
|
|
||||||
|
def has_parameters(self, other_parameters):
|
||||||
|
return self.parameters == other_parameters
|
||||||
|
|
||||||
def _create_resource_map(self):
|
def _create_resource_map(self):
|
||||||
resource_map = ResourceMap(
|
resource_map = ResourceMap(
|
||||||
self.stack_id,
|
self.stack_id,
|
||||||
@ -732,6 +743,16 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
tags=tags,
|
tags=tags,
|
||||||
role_arn=role_arn,
|
role_arn=role_arn,
|
||||||
)
|
)
|
||||||
|
if (
|
||||||
|
change_set_type == "UPDATE"
|
||||||
|
and stack.has_template(template)
|
||||||
|
and stack.has_parameters(parameters)
|
||||||
|
):
|
||||||
|
# Nothing has changed - mark it as such
|
||||||
|
new_change_set.status = "FAILED"
|
||||||
|
new_change_set.execution_status = "UNAVAILABLE"
|
||||||
|
new_change_set.status_reason = "The submitted information didn't contain changes. Submit different information to create a change set."
|
||||||
|
else:
|
||||||
new_change_set.status = "CREATE_COMPLETE"
|
new_change_set.status = "CREATE_COMPLETE"
|
||||||
new_change_set.execution_status = "AVAILABLE"
|
new_change_set.execution_status = "AVAILABLE"
|
||||||
self.change_sets[change_set_id] = new_change_set
|
self.change_sets[change_set_id] = new_change_set
|
||||||
|
@ -1641,6 +1641,83 @@ def test_delete_change_set():
|
|||||||
cf_conn.list_change_sets(StackName="NewStack")["Summaries"].should.have.length_of(0)
|
cf_conn.list_change_sets(StackName="NewStack")["Summaries"].should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_cloudformation
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_change_set_twice__no_changes():
|
||||||
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
|
||||||
|
# Execute once
|
||||||
|
change_set_id = cf_client.create_change_set(
|
||||||
|
StackName="NewStack",
|
||||||
|
TemplateBody=dummy_template_json,
|
||||||
|
ChangeSetName="NewChangeSet",
|
||||||
|
ChangeSetType="CREATE",
|
||||||
|
)["Id"]
|
||||||
|
cf_client.execute_change_set(ChangeSetName=change_set_id, DisableRollback=False)
|
||||||
|
|
||||||
|
# Execute twice
|
||||||
|
change_set_id = cf_client.create_change_set(
|
||||||
|
StackName="NewStack",
|
||||||
|
TemplateBody=dummy_template_json,
|
||||||
|
ChangeSetName="NewChangeSet",
|
||||||
|
ChangeSetType="UPDATE",
|
||||||
|
)["Id"]
|
||||||
|
execution = cf_client.describe_change_set(ChangeSetName=change_set_id)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
execution["ExecutionStatus"].should.equal("UNAVAILABLE")
|
||||||
|
execution["Status"].should.equal("FAILED")
|
||||||
|
execution["StatusReason"].should.equal(
|
||||||
|
"The submitted information didn't contain changes. Submit different information to create a change set."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_cloudformation
|
||||||
|
@mock_ec2
|
||||||
|
@mock_s3
|
||||||
|
def test_create_change_set_twice__using_s3__no_changes():
|
||||||
|
cf_client = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
s3 = boto3.client("s3", region_name="us-east-1")
|
||||||
|
s3_conn = boto3.resource("s3", region_name="us-east-1")
|
||||||
|
s3_conn.create_bucket(Bucket="foobar")
|
||||||
|
|
||||||
|
s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json)
|
||||||
|
key_url_1 = s3.generate_presigned_url(
|
||||||
|
ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"}
|
||||||
|
)
|
||||||
|
|
||||||
|
s3_conn.Object("foobar", "template-key-unchanged").put(Body=dummy_template_json)
|
||||||
|
key_url_2 = s3.generate_presigned_url(
|
||||||
|
ClientMethod="get_object",
|
||||||
|
Params={"Bucket": "foobar", "Key": "template-key-unchanged"},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Execute once
|
||||||
|
change_set_id = cf_client.create_change_set(
|
||||||
|
StackName="NewStack",
|
||||||
|
TemplateURL=key_url_1,
|
||||||
|
ChangeSetName="NewChangeSet",
|
||||||
|
ChangeSetType="CREATE",
|
||||||
|
)["Id"]
|
||||||
|
cf_client.execute_change_set(ChangeSetName=change_set_id, DisableRollback=False)
|
||||||
|
|
||||||
|
# Execute twice
|
||||||
|
change_set_id = cf_client.create_change_set(
|
||||||
|
StackName="NewStack",
|
||||||
|
TemplateURL=key_url_2,
|
||||||
|
ChangeSetName="NewChangeSet",
|
||||||
|
ChangeSetType="UPDATE",
|
||||||
|
)["Id"]
|
||||||
|
execution = cf_client.describe_change_set(ChangeSetName=change_set_id)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
execution["ExecutionStatus"].should.equal("UNAVAILABLE")
|
||||||
|
execution["Status"].should.equal("FAILED")
|
||||||
|
execution["StatusReason"].should.equal(
|
||||||
|
"The submitted information didn't contain changes. Submit different information to create a change set."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@mock_cloudformation
|
@mock_cloudformation
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_delete_stack_by_name():
|
def test_delete_stack_by_name():
|
||||||
|
Loading…
Reference in New Issue
Block a user