cloudformation: fix get_template_summary() related error (#4425)
This commit is contained in:
parent
9d552c39ea
commit
080e7eba84
@ -11,7 +11,7 @@ class UnformattedGetAttTemplateException(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class ValidationError(BadRequest):
|
class ValidationError(BadRequest):
|
||||||
def __init__(self, name_or_id, message=None):
|
def __init__(self, name_or_id=None, message=None):
|
||||||
if message is None:
|
if message is None:
|
||||||
message = "Stack with id {0} does not exist".format(name_or_id)
|
message = "Stack with id {0} does not exist".format(name_or_id)
|
||||||
|
|
||||||
|
@ -745,24 +745,25 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
if change_set is None:
|
if change_set is None:
|
||||||
raise ValidationError(stack_name)
|
raise ValidationError(stack_name)
|
||||||
|
|
||||||
|
stack = self.stacks[change_set.stack_id]
|
||||||
|
# TODO: handle execution errors and implement rollback
|
||||||
if change_set.change_set_type == "CREATE":
|
if change_set.change_set_type == "CREATE":
|
||||||
change_set.stack._add_stack_event(
|
stack._add_stack_event(
|
||||||
"CREATE_IN_PROGRESS", resource_status_reason="User Initiated"
|
"CREATE_IN_PROGRESS", resource_status_reason="User Initiated"
|
||||||
)
|
)
|
||||||
change_set.apply()
|
change_set.apply()
|
||||||
change_set.stack._add_stack_event("CREATE_COMPLETE")
|
stack._add_stack_event("CREATE_COMPLETE")
|
||||||
else:
|
else:
|
||||||
change_set.stack._add_stack_event("UPDATE_IN_PROGRESS")
|
stack._add_stack_event("UPDATE_IN_PROGRESS")
|
||||||
change_set.apply()
|
change_set.apply()
|
||||||
change_set.stack._add_stack_event("UPDATE_COMPLETE")
|
stack._add_stack_event("UPDATE_COMPLETE")
|
||||||
|
|
||||||
# set the execution status of the changeset
|
# set the execution status of the changeset
|
||||||
change_set.execution_status = "EXECUTE_COMPLETE"
|
change_set.execution_status = "EXECUTE_COMPLETE"
|
||||||
|
|
||||||
# set the status of the stack
|
# set the status of the stack
|
||||||
self.stacks[
|
stack.status = f"{change_set.change_set_type}_COMPLETE"
|
||||||
change_set.stack_id
|
stack.template = change_set.template
|
||||||
].status = f"{change_set.change_set_type}_COMPLETE"
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def describe_stacks(self, name_or_stack_id):
|
def describe_stacks(self, name_or_stack_id):
|
||||||
|
@ -324,7 +324,12 @@ class CloudFormationResponse(BaseResponse):
|
|||||||
stack_body = self._get_param("TemplateBody")
|
stack_body = self._get_param("TemplateBody")
|
||||||
|
|
||||||
if stack_name:
|
if stack_name:
|
||||||
stack_body = self.cloudformation_backend.get_stack(stack_name).template
|
stack = self.cloudformation_backend.get_stack(stack_name)
|
||||||
|
if stack.status == "REVIEW_IN_PROGRESS":
|
||||||
|
raise ValidationError(
|
||||||
|
message="GetTemplateSummary cannot be called on REVIEW_IN_PROGRESS stacks.",
|
||||||
|
)
|
||||||
|
stack_body = stack.template
|
||||||
elif template_url:
|
elif template_url:
|
||||||
stack_body = self._get_stack_from_s3_url(template_url)
|
stack_body = self._get_stack_from_s3_url(template_url)
|
||||||
|
|
||||||
|
@ -862,42 +862,61 @@ def test_get_template_summary():
|
|||||||
s3 = boto3.client("s3", 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 = boto3.resource("s3", region_name="us-east-1")
|
||||||
|
|
||||||
|
# json template
|
||||||
conn = boto3.client("cloudformation", region_name="us-east-1")
|
conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
result = conn.get_template_summary(TemplateBody=json.dumps(dummy_template3))
|
result = conn.get_template_summary(TemplateBody=json.dumps(dummy_template3))
|
||||||
|
|
||||||
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
||||||
result["Version"].should.equal("2010-09-09")
|
result["Version"].should.equal("2010-09-09")
|
||||||
result["Description"].should.equal("Stack 3")
|
result["Description"].should.equal("Stack 3")
|
||||||
|
|
||||||
|
# existing stack
|
||||||
conn.create_stack(StackName="test_stack", TemplateBody=json.dumps(dummy_template3))
|
conn.create_stack(StackName="test_stack", TemplateBody=json.dumps(dummy_template3))
|
||||||
|
|
||||||
result = conn.get_template_summary(StackName="test_stack")
|
result = conn.get_template_summary(StackName="test_stack")
|
||||||
|
|
||||||
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
||||||
result["Version"].should.equal("2010-09-09")
|
result["Version"].should.equal("2010-09-09")
|
||||||
result["Description"].should.equal("Stack 3")
|
result["Description"].should.equal("Stack 3")
|
||||||
|
|
||||||
|
# json template from s3
|
||||||
s3_conn.create_bucket(Bucket="foobar")
|
s3_conn.create_bucket(Bucket="foobar")
|
||||||
s3_conn.Object("foobar", "template-key").put(Body=json.dumps(dummy_template3))
|
s3_conn.Object("foobar", "template-key").put(Body=json.dumps(dummy_template3))
|
||||||
|
|
||||||
key_url = s3.generate_presigned_url(
|
key_url = s3.generate_presigned_url(
|
||||||
ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"}
|
ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"}
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.create_stack(StackName="stack_from_url", TemplateURL=key_url)
|
conn.create_stack(StackName="stack_from_url", TemplateURL=key_url)
|
||||||
result = conn.get_template_summary(TemplateURL=key_url)
|
result = conn.get_template_summary(TemplateURL=key_url)
|
||||||
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
||||||
result["Version"].should.equal("2010-09-09")
|
result["Version"].should.equal("2010-09-09")
|
||||||
result["Description"].should.equal("Stack 3")
|
result["Description"].should.equal("Stack 3")
|
||||||
|
|
||||||
|
# yaml template
|
||||||
conn = boto3.client("cloudformation", region_name="us-east-1")
|
conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
result = conn.get_template_summary(TemplateBody=dummy_template_yaml)
|
result = conn.get_template_summary(TemplateBody=dummy_template_yaml)
|
||||||
|
|
||||||
result["ResourceTypes"].should.equal(["AWS::EC2::Instance"])
|
result["ResourceTypes"].should.equal(["AWS::EC2::Instance"])
|
||||||
result["Version"].should.equal("2010-09-09")
|
result["Version"].should.equal("2010-09-09")
|
||||||
result["Description"].should.equal("Stack1 with yaml template")
|
result["Description"].should.equal("Stack1 with yaml template")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_cloudformation
|
||||||
|
def test_get_template_summary_for_stack_createed_by_changeset_execution():
|
||||||
|
conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
conn.create_change_set(
|
||||||
|
StackName="stack_from_changeset",
|
||||||
|
TemplateBody=json.dumps(dummy_template3),
|
||||||
|
ChangeSetName="test_changeset",
|
||||||
|
ChangeSetType="CREATE",
|
||||||
|
)
|
||||||
|
with pytest.raises(
|
||||||
|
ClientError,
|
||||||
|
match="GetTemplateSummary cannot be called on REVIEW_IN_PROGRESS stacks",
|
||||||
|
):
|
||||||
|
conn.get_template_summary(StackName="stack_from_changeset")
|
||||||
|
conn.execute_change_set(ChangeSetName="test_changeset")
|
||||||
|
result = conn.get_template_summary(StackName="stack_from_changeset")
|
||||||
|
result["ResourceTypes"].should.equal(["AWS::EC2::VPC"])
|
||||||
|
result["Version"].should.equal("2010-09-09")
|
||||||
|
result["Description"].should.equal("Stack 3")
|
||||||
|
|
||||||
|
|
||||||
@mock_cloudformation
|
@mock_cloudformation
|
||||||
def test_boto3_create_stack_with_ref_yaml():
|
def test_boto3_create_stack_with_ref_yaml():
|
||||||
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
Loading…
Reference in New Issue
Block a user