PageRenderTime 35ms CodeModel.GetById 2ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/boto-2.5.2/tests/unit/cloudformation/test_connection.py

#
Python | 620 lines | 615 code | 4 blank | 1 comment | 0 complexity | e3dab4143337681ff1e725ff18a7f912 MD5 | raw file
  1#!/usr/bin/env python
  2import unittest
  3import httplib
  4from datetime import datetime
  5try:
  6    import json
  7except ImportError:
  8    import simplejson as json
  9
 10from mock import Mock
 11
 12from tests.unit import AWSMockServiceTestCase
 13from boto.cloudformation.connection import CloudFormationConnection
 14
 15
 16SAMPLE_TEMPLATE = r"""
 17{
 18  "AWSTemplateFormatVersion" : "2010-09-09",
 19  "Description" : "Sample template",
 20  "Parameters" : {
 21    "KeyName" : {
 22      "Description" : "key pair",
 23      "Type" : "String"
 24    }
 25  },
 26  "Resources" : {
 27    "Ec2Instance" : {
 28      "Type" : "AWS::EC2::Instance",
 29      "Properties" : {
 30        "KeyName" : { "Ref" : "KeyName" },
 31        "ImageId" : "ami-7f418316",
 32        "UserData" : { "Fn::Base64" : "80" }
 33      }
 34    }
 35  },
 36  "Outputs" : {
 37    "InstanceId" : {
 38      "Description" : "InstanceId of the newly created EC2 instance",
 39      "Value" : { "Ref" : "Ec2Instance" }
 40    }
 41}
 42"""
 43
 44class CloudFormationConnectionBase(AWSMockServiceTestCase):
 45    connection_class = CloudFormationConnection
 46
 47    def setUp(self):
 48        super(CloudFormationConnectionBase, self).setUp()
 49        self.stack_id = u'arn:aws:cloudformation:us-east-1:18:stack/Name/id'
 50
 51
 52class TestCloudFormationCreateStack(CloudFormationConnectionBase):
 53    def default_body(self):
 54        return json.dumps(
 55            {u'CreateStackResponse':
 56                 {u'CreateStackResult': {u'StackId': self.stack_id},
 57                  u'ResponseMetadata': {u'RequestId': u'1'}}})
 58
 59    def test_create_stack_has_correct_request_params(self):
 60        self.set_http_response(status_code=200)
 61        api_response = self.service_connection.create_stack(
 62            'stack_name', template_url='http://url',
 63            template_body=SAMPLE_TEMPLATE,
 64            parameters=[('KeyName', 'myKeyName')],
 65            notification_arns=['arn:notify1', 'arn:notify2'],
 66            disable_rollback=True,
 67            timeout_in_minutes=20, capabilities=['CAPABILITY_IAM']
 68        )
 69        self.assertEqual(api_response, self.stack_id)
 70        # These are the parameters that are actually sent to the CloudFormation
 71        # service.
 72        self.assert_request_parameters({
 73            'AWSAccessKeyId': 'aws_access_key_id',
 74            'Action': 'CreateStack',
 75            'Capabilities.member.1': 'CAPABILITY_IAM',
 76            'ContentType': 'JSON',
 77            'DisableRollback': 'true',
 78            'NotificationARNs.member.1': 'arn:notify1',
 79            'NotificationARNs.member.2': 'arn:notify2',
 80            'Parameters.member.1.ParameterKey': 'KeyName',
 81            'Parameters.member.1.ParameterValue': 'myKeyName',
 82            'SignatureMethod': 'HmacSHA256',
 83            'SignatureVersion': 2,
 84            'StackName': 'stack_name',
 85            'Version': '2010-05-15',
 86            'TimeoutInMinutes': 20,
 87            'TemplateBody': SAMPLE_TEMPLATE,
 88            'TemplateURL': 'http://url',
 89        }, ignore_params_values=['Timestamp'])
 90
 91    # The test_create_stack_has_correct_request_params verified all of the
 92    # params needed when making a create_stack service call.  The rest of the
 93    # tests for create_stack only verify specific parts of the params sent
 94    # to CloudFormation.
 95
 96    def test_create_stack_with_minimum_args(self):
 97        # This will fail in practice, but the API docs only require stack_name.
 98        self.set_http_response(status_code=200)
 99        api_response = self.service_connection.create_stack('stack_name')
100        self.assertEqual(api_response, self.stack_id)
101        self.assert_request_parameters({
102            'AWSAccessKeyId': 'aws_access_key_id',
103            'Action': 'CreateStack',
104            'ContentType': 'JSON',
105            'DisableRollback': 'false',
106            'SignatureMethod': 'HmacSHA256',
107            'SignatureVersion': 2,
108            'StackName': 'stack_name',
109            'Version': '2010-05-15',
110        }, ignore_params_values=['Timestamp'])
111
112    def test_create_stack_fails(self):
113        self.set_http_response(status_code=400, reason='Bad Request',
114                               body='Invalid arg.')
115        with self.assertRaises(self.service_connection.ResponseError):
116            api_response = self.service_connection.create_stack(
117                'stack_name', template_body=SAMPLE_TEMPLATE,
118                parameters=[('KeyName', 'myKeyName')])
119
120
121class TestCloudFormationUpdateStack(CloudFormationConnectionBase):
122    def default_body(self):
123        return json.dumps(
124            {u'UpdateStackResponse':
125                 {u'UpdateStackResult': {u'StackId': self.stack_id},
126                  u'ResponseMetadata': {u'RequestId': u'1'}}})
127
128    def test_update_stack_all_args(self):
129        self.set_http_response(status_code=200)
130        api_response = self.service_connection.update_stack(
131            'stack_name', template_url='http://url',
132            template_body=SAMPLE_TEMPLATE,
133            parameters=[('KeyName', 'myKeyName')],
134            notification_arns=['arn:notify1', 'arn:notify2'],
135            disable_rollback=True,
136            timeout_in_minutes=20
137        )
138        self.assert_request_parameters({
139            'AWSAccessKeyId': 'aws_access_key_id',
140            'Action': 'UpdateStack',
141            'ContentType': 'JSON',
142            'DisableRollback': 'true',
143            'NotificationARNs.member.1': 'arn:notify1',
144            'NotificationARNs.member.2': 'arn:notify2',
145            'Parameters.member.1.ParameterKey': 'KeyName',
146            'Parameters.member.1.ParameterValue': 'myKeyName',
147            'SignatureMethod': 'HmacSHA256',
148            'SignatureVersion': 2,
149            'StackName': 'stack_name',
150            'Version': '2010-05-15',
151            'TimeoutInMinutes': 20,
152            'TemplateBody': SAMPLE_TEMPLATE,
153            'TemplateURL': 'http://url',
154        }, ignore_params_values=['Timestamp'])
155
156    def test_update_stack_with_minimum_args(self):
157        self.set_http_response(status_code=200)
158        api_response = self.service_connection.update_stack('stack_name')
159        self.assertEqual(api_response, self.stack_id)
160        self.assert_request_parameters({
161            'AWSAccessKeyId': 'aws_access_key_id',
162            'Action': 'UpdateStack',
163            'ContentType': 'JSON',
164            'DisableRollback': 'false',
165            'SignatureMethod': 'HmacSHA256',
166            'SignatureVersion': 2,
167            'StackName': 'stack_name',
168            'Version': '2010-05-15',
169        }, ignore_params_values=['Timestamp'])
170
171    def test_update_stack_fails(self):
172        self.set_http_response(status_code=400, reason='Bad Request',
173                               body='Invalid arg.')
174        with self.assertRaises(self.service_connection.ResponseError):
175            api_response = self.service_connection.update_stack(
176                'stack_name', template_body=SAMPLE_TEMPLATE,
177                parameters=[('KeyName', 'myKeyName')])
178
179
180class TestCloudFormationDeleteStack(CloudFormationConnectionBase):
181    def default_body(self):
182        return json.dumps(
183            {u'DeleteStackResponse':
184                 {u'ResponseMetadata': {u'RequestId': u'1'}}})
185
186    def test_delete_stack(self):
187        self.set_http_response(status_code=200)
188        api_response = self.service_connection.delete_stack('stack_name')
189        self.assertEqual(api_response, json.loads(self.default_body()))
190        self.assert_request_parameters({
191            'AWSAccessKeyId': 'aws_access_key_id',
192            'Action': 'DeleteStack',
193            'ContentType': 'JSON',
194            'SignatureMethod': 'HmacSHA256',
195            'SignatureVersion': 2,
196            'StackName': 'stack_name',
197            'Version': '2010-05-15',
198        }, ignore_params_values=['Timestamp'])
199
200    def test_delete_stack_fails(self):
201        self.set_http_response(status_code=400)
202        with self.assertRaises(self.service_connection.ResponseError):
203            api_response = self.service_connection.delete_stack('stack_name')
204
205
206class TestCloudFormationDescribeStackResource(CloudFormationConnectionBase):
207    def default_body(self):
208        return json.dumps('fake server response')
209
210    def test_describe_stack_resource(self):
211        self.set_http_response(status_code=200)
212        api_response = self.service_connection.describe_stack_resource(
213            'stack_name', 'resource_id')
214        self.assertEqual(api_response, 'fake server response')
215        self.assert_request_parameters({
216            'AWSAccessKeyId': 'aws_access_key_id',
217            'Action': 'DescribeStackResource',
218            'ContentType': 'JSON',
219            'LogicalResourceId': 'resource_id',
220            'SignatureMethod': 'HmacSHA256',
221            'SignatureVersion': 2,
222            'StackName': 'stack_name',
223            'Version': '2010-05-15',
224        }, ignore_params_values=['Timestamp'])
225
226    def test_describe_stack_resource_fails(self):
227        self.set_http_response(status_code=400)
228        with self.assertRaises(self.service_connection.ResponseError):
229            api_response = self.service_connection.describe_stack_resource(
230                'stack_name', 'resource_id')
231
232
233class TestCloudFormationGetTemplate(CloudFormationConnectionBase):
234    def default_body(self):
235        return json.dumps('fake server response')
236
237    def test_get_template(self):
238        self.set_http_response(status_code=200)
239        api_response = self.service_connection.get_template('stack_name')
240        self.assertEqual(api_response, 'fake server response')
241        self.assert_request_parameters({
242            'AWSAccessKeyId': 'aws_access_key_id',
243            'Action': 'GetTemplate',
244            'ContentType': 'JSON',
245            'SignatureMethod': 'HmacSHA256',
246            'SignatureVersion': 2,
247            'StackName': 'stack_name',
248            'Version': '2010-05-15',
249        }, ignore_params_values=['Timestamp'])
250
251
252    def test_get_template_fails(self):
253        self.set_http_response(status_code=400)
254        with self.assertRaises(self.service_connection.ResponseError):
255            api_response = self.service_connection.get_template('stack_name')
256
257
258class TestCloudFormationGetStackevents(CloudFormationConnectionBase):
259    def default_body(self):
260        return """
261            <DescribeStackEventsResult>
262              <StackEvents>
263                <member>
264                  <EventId>Event-1-Id</EventId>
265                  <StackId>arn:aws:cfn:us-east-1:1:stack</StackId>
266                  <StackName>MyStack</StackName>
267                  <LogicalResourceId>MyStack</LogicalResourceId>
268                  <PhysicalResourceId>MyStack_One</PhysicalResourceId>
269                  <ResourceType>AWS::CloudFormation::Stack</ResourceType>
270                  <Timestamp>2010-07-27T22:26:28Z</Timestamp>
271                  <ResourceStatus>CREATE_IN_PROGRESS</ResourceStatus>
272                  <ResourceStatusReason>User initiated</ResourceStatusReason>
273                </member>
274                <member>
275                  <EventId>Event-2-Id</EventId>
276                  <StackId>arn:aws:cfn:us-east-1:1:stack</StackId>
277                  <StackName>MyStack</StackName>
278                  <LogicalResourceId>MySG1</LogicalResourceId>
279                  <PhysicalResourceId>MyStack_SG1</PhysicalResourceId>
280                  <ResourceType>AWS::SecurityGroup</ResourceType>
281                  <Timestamp>2010-07-27T22:28:28Z</Timestamp>
282                  <ResourceStatus>CREATE_COMPLETE</ResourceStatus>
283                </member>
284              </StackEvents>
285            </DescribeStackEventsResult>
286        """
287
288    def test_describe_stack_events(self):
289        self.set_http_response(status_code=200)
290        first, second = self.service_connection.describe_stack_events('stack_name', next_token='next_token')
291        self.assertEqual(first.event_id, 'Event-1-Id')
292        self.assertEqual(first.logical_resource_id, 'MyStack')
293        self.assertEqual(first.physical_resource_id, 'MyStack_One')
294        self.assertEqual(first.resource_properties, None)
295        self.assertEqual(first.resource_status, 'CREATE_IN_PROGRESS')
296        self.assertEqual(first.resource_status_reason, 'User initiated')
297        self.assertEqual(first.resource_type, 'AWS::CloudFormation::Stack')
298        self.assertEqual(first.stack_id, 'arn:aws:cfn:us-east-1:1:stack')
299        self.assertEqual(first.stack_name, 'MyStack')
300        self.assertIsNotNone(first.timestamp)
301
302        self.assertEqual(second.event_id, 'Event-2-Id')
303        self.assertEqual(second.logical_resource_id, 'MySG1')
304        self.assertEqual(second.physical_resource_id, 'MyStack_SG1')
305        self.assertEqual(second.resource_properties, None)
306        self.assertEqual(second.resource_status, 'CREATE_COMPLETE')
307        self.assertEqual(second.resource_status_reason, None)
308        self.assertEqual(second.resource_type, 'AWS::SecurityGroup')
309        self.assertEqual(second.stack_id, 'arn:aws:cfn:us-east-1:1:stack')
310        self.assertEqual(second.stack_name, 'MyStack')
311        self.assertIsNotNone(second.timestamp)
312
313        self.assert_request_parameters({
314            'AWSAccessKeyId': 'aws_access_key_id',
315            'Action': 'DescribeStackEvents',
316            'NextToken': 'next_token',
317            'SignatureMethod': 'HmacSHA256',
318            'SignatureVersion': 2,
319            'StackName': 'stack_name',
320            'Version': '2010-05-15',
321        }, ignore_params_values=['Timestamp'])
322
323
324class TestCloudFormationDescribeStackResources(CloudFormationConnectionBase):
325    def default_body(self):
326        return """
327            <DescribeStackResourcesResult>
328              <StackResources>
329                <member>
330                  <StackId>arn:aws:cfn:us-east-1:1:stack</StackId>
331                  <StackName>MyStack</StackName>
332                  <LogicalResourceId>MyDBInstance</LogicalResourceId>
333                  <PhysicalResourceId>MyStack_DB1</PhysicalResourceId>
334                  <ResourceType>AWS::DBInstance</ResourceType>
335                  <Timestamp>2010-07-27T22:27:28Z</Timestamp>
336                  <ResourceStatus>CREATE_COMPLETE</ResourceStatus>
337                </member>
338                <member>
339                  <StackId>arn:aws:cfn:us-east-1:1:stack</StackId>
340                  <StackName>MyStack</StackName>
341                  <LogicalResourceId>MyAutoScalingGroup</LogicalResourceId>
342                  <PhysicalResourceId>MyStack_ASG1</PhysicalResourceId>
343                  <ResourceType>AWS::AutoScalingGroup</ResourceType>
344                  <Timestamp>2010-07-27T22:28:28Z</Timestamp>
345                  <ResourceStatus>CREATE_IN_PROGRESS</ResourceStatus>
346                </member>
347              </StackResources>
348            </DescribeStackResourcesResult>
349        """
350
351    def test_describe_stack_resources(self):
352        self.set_http_response(status_code=200)
353        first, second = self.service_connection.describe_stack_resources(
354            'stack_name', 'logical_resource_id', 'physical_resource_id')
355        self.assertEqual(first.description, None)
356        self.assertEqual(first.logical_resource_id, 'MyDBInstance')
357        self.assertEqual(first.physical_resource_id, 'MyStack_DB1')
358        self.assertEqual(first.resource_status, 'CREATE_COMPLETE')
359        self.assertEqual(first.resource_status_reason, None)
360        self.assertEqual(first.resource_type, 'AWS::DBInstance')
361        self.assertEqual(first.stack_id, 'arn:aws:cfn:us-east-1:1:stack')
362        self.assertEqual(first.stack_name, 'MyStack')
363        self.assertIsNotNone(first.timestamp)
364
365        self.assertEqual(second.description, None)
366        self.assertEqual(second.logical_resource_id, 'MyAutoScalingGroup')
367        self.assertEqual(second.physical_resource_id, 'MyStack_ASG1')
368        self.assertEqual(second.resource_status, 'CREATE_IN_PROGRESS')
369        self.assertEqual(second.resource_status_reason, None)
370        self.assertEqual(second.resource_type, 'AWS::AutoScalingGroup')
371        self.assertEqual(second.stack_id, 'arn:aws:cfn:us-east-1:1:stack')
372        self.assertEqual(second.stack_name, 'MyStack')
373        self.assertIsNotNone(second.timestamp)
374
375        self.assert_request_parameters({
376            'AWSAccessKeyId': 'aws_access_key_id',
377            'Action': 'DescribeStackResources',
378            'LogicalResourceId': 'logical_resource_id',
379            'PhysicalResourceId': 'physical_resource_id',
380            'SignatureMethod': 'HmacSHA256',
381            'SignatureVersion': 2,
382            'StackName': 'stack_name',
383            'Version': '2010-05-15',
384        }, ignore_params_values=['Timestamp'])
385
386
387class TestCloudFormationDescribeStacks(CloudFormationConnectionBase):
388    def default_body(self):
389        return """
390          <DescribeStacksResponse>
391            <DescribeStacksResult>
392              <Stacks>
393                <member>
394                  <StackId>arn:aws:cfn:us-east-1:1:stack</StackId>
395                  <StackStatus>CREATE_COMPLETE</StackStatus>
396                  <StackName>MyStack</StackName>
397                  <StackStatusReason/>
398                  <Description>My Description</Description>
399                  <CreationTime>2012-05-16T22:55:31Z</CreationTime>
400                  <Capabilities>
401                    <member>CAPABILITY_IAM</member>
402                  </Capabilities>
403                  <DisableRollback>false</DisableRollback>
404                  <Parameters>
405                    <member>
406                      <ParameterValue>MyValue</ParameterValue>
407                      <ParameterKey>MyKey</ParameterKey>
408                    </member>
409                  </Parameters>
410                  <Outputs>
411                    <member>
412                      <OutputValue>http://url/</OutputValue>
413                      <Description>Server URL</Description>
414                      <OutputKey>ServerURL</OutputKey>
415                    </member>
416                  </Outputs>
417                </member>
418              </Stacks>
419            </DescribeStacksResult>
420            <ResponseMetadata>
421              <RequestId>12345</RequestId>
422            </ResponseMetadata>
423        </DescribeStacksResponse>
424        """
425
426    def test_describe_stacks(self):
427        self.set_http_response(status_code=200)
428        stack = self.service_connection.describe_stacks('MyStack')[0]
429        self.assertEqual(stack.creation_time,
430                         datetime(2012, 5, 16, 22, 55, 31))
431        self.assertEqual(stack.description, 'My Description')
432        self.assertEqual(stack.disable_rollback, True)
433        self.assertEqual(stack.notification_arns, [])
434        self.assertEqual(stack.stack_id, 'arn:aws:cfn:us-east-1:1:stack')
435        self.assertEqual(stack.stack_status, 'CREATE_COMPLETE')
436        self.assertEqual(stack.stack_name, 'MyStack')
437        self.assertEqual(stack.stack_name_reason, None)
438        self.assertEqual(stack.timeout_in_minutes, None)
439
440        self.assertEqual(len(stack.outputs), 1)
441        self.assertEqual(stack.outputs[0].description, 'Server URL')
442        self.assertEqual(stack.outputs[0].key, 'ServerURL')
443        self.assertEqual(stack.outputs[0].value, 'http://url/')
444
445        self.assertEqual(len(stack.parameters), 1)
446        self.assertEqual(stack.parameters[0].key, 'MyKey')
447        self.assertEqual(stack.parameters[0].value, 'MyValue')
448
449        self.assertEqual(len(stack.capabilities), 1)
450        self.assertEqual(stack.capabilities[0].value, 'CAPABILITY_IAM')
451
452        self.assert_request_parameters({
453            'AWSAccessKeyId': 'aws_access_key_id',
454            'Action': 'DescribeStacks',
455            'SignatureMethod': 'HmacSHA256',
456            'SignatureVersion': 2,
457            'StackName': 'MyStack',
458            'Version': '2010-05-15',
459        }, ignore_params_values=['Timestamp'])
460
461
462class TestCloudFormationListStackResources(CloudFormationConnectionBase):
463    def default_body(self):
464        return """
465            <ListStackResourcesResponse>
466              <ListStackResourcesResult>
467                <StackResourceSummaries>
468                  <member>
469                    <ResourceStatus>CREATE_COMPLETE</ResourceStatus>
470                    <LogicalResourceId>SampleDB</LogicalResourceId>
471                    <LastUpdatedTimestamp>2011-06-21T20:25:57Z</LastUpdatedTimestamp>
472                    <PhysicalResourceId>My-db-ycx</PhysicalResourceId>
473                    <ResourceType>AWS::RDS::DBInstance</ResourceType>
474                  </member>
475                  <member>
476                    <ResourceStatus>CREATE_COMPLETE</ResourceStatus>
477                    <LogicalResourceId>CPUAlarmHigh</LogicalResourceId>
478                    <LastUpdatedTimestamp>2011-06-21T20:29:23Z</LastUpdatedTimestamp>
479                    <PhysicalResourceId>MyStack-CPUH-PF</PhysicalResourceId>
480                    <ResourceType>AWS::CloudWatch::Alarm</ResourceType>
481                  </member>
482                </StackResourceSummaries>
483              </ListStackResourcesResult>
484              <ResponseMetadata>
485                <RequestId>2d06e36c-ac1d-11e0-a958-f9382b6eb86b</RequestId>
486              </ResponseMetadata>
487            </ListStackResourcesResponse>
488        """
489
490    def test_list_stack_resources(self):
491        self.set_http_response(status_code=200)
492        resources = self.service_connection.list_stack_resources('MyStack',
493                                                              next_token='next_token')
494        self.assertEqual(len(resources), 2)
495        self.assertEqual(resources[0].last_updated_timestamp,
496                         datetime(2011, 6, 21, 20, 25, 57))
497        self.assertEqual(resources[0].logical_resource_id, 'SampleDB')
498        self.assertEqual(resources[0].physical_resource_id, 'My-db-ycx')
499        self.assertEqual(resources[0].resource_status, 'CREATE_COMPLETE')
500        self.assertEqual(resources[0].resource_status_reason, None)
501        self.assertEqual(resources[0].resource_type, 'AWS::RDS::DBInstance')
502
503        self.assertEqual(resources[1].last_updated_timestamp,
504                         datetime(2011, 6, 21, 20, 29, 23))
505        self.assertEqual(resources[1].logical_resource_id, 'CPUAlarmHigh')
506        self.assertEqual(resources[1].physical_resource_id, 'MyStack-CPUH-PF')
507        self.assertEqual(resources[1].resource_status, 'CREATE_COMPLETE')
508        self.assertEqual(resources[1].resource_status_reason, None)
509        self.assertEqual(resources[1].resource_type, 'AWS::CloudWatch::Alarm')
510
511        self.assert_request_parameters({
512            'AWSAccessKeyId': 'aws_access_key_id',
513            'Action': 'ListStackResources',
514            'NextToken': 'next_token',
515            'SignatureMethod': 'HmacSHA256',
516            'SignatureVersion': 2,
517            'StackName': 'MyStack',
518            'Version': '2010-05-15',
519        }, ignore_params_values=['Timestamp'])
520
521
522class TestCloudFormationListStacks(CloudFormationConnectionBase):
523    def default_body(self):
524        return """
525            <ListStacksResponse>
526             <ListStacksResult>
527              <StackSummaries>
528                <member>
529                    <StackId>arn:aws:cfn:us-east-1:1:stack/Test1/aa</StackId>
530                    <StackStatus>CREATE_IN_PROGRESS</StackStatus>
531                    <StackName>vpc1</StackName>
532                    <CreationTime>2011-05-23T15:47:44Z</CreationTime>
533                    <TemplateDescription>My Description.</TemplateDescription>
534                </member>
535              </StackSummaries>
536             </ListStacksResult>
537            </ListStacksResponse>
538        """
539
540    def test_list_stacks(self):
541        self.set_http_response(status_code=200)
542        stacks = self.service_connection.list_stacks(['CREATE_IN_PROGRESS'],
543                                                  next_token='next_token')
544        self.assertEqual(len(stacks), 1)
545        self.assertEqual(stacks[0].stack_id,
546                         'arn:aws:cfn:us-east-1:1:stack/Test1/aa')
547        self.assertEqual(stacks[0].stack_status, 'CREATE_IN_PROGRESS')
548        self.assertEqual(stacks[0].stack_name, 'vpc1')
549        self.assertEqual(stacks[0].creation_time,
550                         datetime(2011, 5, 23, 15, 47, 44))
551        self.assertEqual(stacks[0].deletion_time, None)
552        self.assertEqual(stacks[0].template_description, 'My Description.')
553
554        self.assert_request_parameters({
555            'AWSAccessKeyId': 'aws_access_key_id',
556            'Action': 'ListStacks',
557            'NextToken': 'next_token',
558            'SignatureMethod': 'HmacSHA256',
559            'SignatureVersion': 2,
560            'StackStatusFilter.member.1': 'CREATE_IN_PROGRESS',
561            'Version': '2010-05-15',
562        }, ignore_params_values=['Timestamp'])
563
564
565class TestCloudFormationValidateTemplate(CloudFormationConnectionBase):
566    def default_body(self):
567        return """
568            <ValidateTemplateResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
569              <ValidateTemplateResult>
570                <Description>My Description.</Description>
571                <Parameters>
572                  <member>
573                    <NoEcho>false</NoEcho>
574                    <ParameterKey>InstanceType</ParameterKey>
575                    <Description>Type of instance to launch</Description>
576                    <DefaultValue>m1.small</DefaultValue>
577                  </member>
578                  <member>
579                    <NoEcho>false</NoEcho>
580                    <ParameterKey>KeyName</ParameterKey>
581                    <Description>EC2 KeyPair</Description>
582                  </member>
583                </Parameters>
584              </ValidateTemplateResult>
585              <ResponseMetadata>
586                <RequestId>0be7b6e8-e4a0-11e0-a5bd-9f8d5a7dbc91</RequestId>
587              </ResponseMetadata>
588            </ValidateTemplateResponse>
589        """
590
591    def test_validate_template(self):
592        self.set_http_response(status_code=200)
593        template = self.service_connection.validate_template(template_body=SAMPLE_TEMPLATE,
594                                                          template_url='http://url')
595        self.assertEqual(template.description, 'My Description.')
596        self.assertEqual(len(template.template_parameters), 2)
597        param1, param2 = template.template_parameters
598        self.assertEqual(param1.default_value, 'm1.small')
599        self.assertEqual(param1.description, 'Type of instance to launch')
600        self.assertEqual(param1.no_echo, True)
601        self.assertEqual(param1.parameter_key, 'InstanceType')
602
603        self.assertEqual(param2.default_value, None)
604        self.assertEqual(param2.description, 'EC2 KeyPair')
605        self.assertEqual(param2.no_echo, True)
606        self.assertEqual(param2.parameter_key, 'KeyName')
607
608        self.assert_request_parameters({
609            'AWSAccessKeyId': 'aws_access_key_id',
610            'Action': 'ValidateTemplate',
611            'SignatureMethod': 'HmacSHA256',
612            'SignatureVersion': 2,
613            'TemplateBody': SAMPLE_TEMPLATE,
614            'TemplateUrl': 'http://url',
615            'Version': '2010-05-15',
616        }, ignore_params_values=['Timestamp'])
617
618
619if __name__ == '__main__':
620    unittest.main()