From bf3fff6e2c7a93b28a4852a6881e33059b933f34 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Mon, 1 May 2017 11:28:35 -0700 Subject: [PATCH 1/3] Allow yaml templates for cloud formation Fixes #912 --- moto/cloudformation/models.py | 9 ++++++++- tests/test_cloudformation/test_stack_parsing.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index b58d1dcf..824d568a 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from datetime import datetime import json +import yaml import uuid import boto.cloudformation @@ -17,7 +18,7 @@ class FakeStack(BaseModel): self.stack_id = stack_id self.name = name self.template = template - self.template_dict = json.loads(self.template) + self._parse_template() self.parameters = parameters self.region_name = region_name self.notification_arns = notification_arns if notification_arns else [] @@ -70,6 +71,12 @@ class FakeStack(BaseModel): resource_properties=resource_properties, )) + def _parse_template(self): + try: + self.template_dict = json.loads(self.template) + except json.JSONDecodeError: + self.template_dict = yaml.load(self.template) + @property def stack_parameters(self): return self.resource_map.resolved_parameters diff --git a/tests/test_cloudformation/test_stack_parsing.py b/tests/test_cloudformation/test_stack_parsing.py index c2af6363..610b0232 100644 --- a/tests/test_cloudformation/test_stack_parsing.py +++ b/tests/test_cloudformation/test_stack_parsing.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import json +import yaml from mock import patch import sure # noqa @@ -126,6 +127,20 @@ def test_parse_stack_with_name_type_resource(): queue.should.be.a(Queue) +def test_parse_stack_with_yaml_template(): + stack = FakeStack( + stack_id="test_id", + name="test_stack", + template=yaml.dump(name_type_template), + parameters={}, + region_name='us-west-1') + + stack.resource_map.should.have.length_of(1) + list(stack.resource_map.keys())[0].should.equal('Queue') + queue = list(stack.resource_map.values())[0] + queue.should.be.a(Queue) + + def test_parse_stack_with_outputs(): stack = FakeStack( stack_id="test_id", From 94a923ae91227513c939d346af46b45e1446d4da Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Thu, 11 May 2017 06:50:33 -0700 Subject: [PATCH 2/3] adding pyaml dependency --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 37eb78cc..51e1748f 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ install_requires = [ "dicttoxml", "six", "werkzeug", + "pyaml", "pytz", "python-dateutil", ] From 9801d226294cc2493c4a772fbb66d042c4852185 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Thu, 11 May 2017 07:15:07 -0700 Subject: [PATCH 3/3] The name of yaml exceptions is more consistent between Py2->3 --- moto/cloudformation/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index 824d568a..f791406a 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -73,9 +73,9 @@ class FakeStack(BaseModel): def _parse_template(self): try: - self.template_dict = json.loads(self.template) - except json.JSONDecodeError: self.template_dict = yaml.load(self.template) + except yaml.parser.ParserError: + self.template_dict = json.loads(self.template) @property def stack_parameters(self):