1# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
2# Copyright (c) 2014 Amazon.com, Inc. or its affiliates.  All Rights Reserved
3#
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the
6# "Software"), to deal in the Software without restriction, including
7# without limitation the rights to use, copy, modify, merge, publish, dis-
8# tribute, sublicense, and/or sell copies of the Software, and to permit
9# persons to whom the Software is furnished to do so, subject to the fol-
10# lowing conditions:
11#
12# The above copyright notice and this permission notice shall be included
13# in all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21# IN THE SOFTWARE.
22
23import boto
24from boto.cloudformation.stack import Stack, StackSummary, StackEvent
25from boto.cloudformation.stack import StackResource, StackResourceSummary
26from boto.cloudformation.template import Template
27from boto.connection import AWSQueryConnection
28from boto.regioninfo import RegionInfo
29from boto.compat import json
30
31
32class CloudFormationConnection(AWSQueryConnection):
33    """
34    AWS CloudFormation
35    AWS CloudFormation enables you to create and manage AWS
36    infrastructure deployments predictably and repeatedly. AWS
37    CloudFormation helps you leverage AWS products such as Amazon EC2,
38    EBS, Amazon SNS, ELB, and Auto Scaling to build highly-reliable,
39    highly scalable, cost effective applications without worrying
40    about creating and configuring the underlying AWS infrastructure.
41
42    With AWS CloudFormation, you declare all of your resources and
43    dependencies in a template file. The template defines a collection
44    of resources as a single unit called a stack. AWS CloudFormation
45    creates and deletes all member resources of the stack together and
46    manages all dependencies between the resources for you.
47
48    For more information about this product, go to the `CloudFormation
49    Product Page`_.
50
51    Amazon CloudFormation makes use of other AWS products. If you need
52    additional technical information about a specific AWS product, you
53    can find the product's technical documentation at
54    `http://aws.amazon.com/documentation/`_.
55    """
56    APIVersion = boto.config.get('Boto', 'cfn_version', '2010-05-15')
57    DefaultRegionName = boto.config.get('Boto', 'cfn_region_name', 'us-east-1')
58    DefaultRegionEndpoint = boto.config.get('Boto', 'cfn_region_endpoint',
59                                            'cloudformation.us-east-1.amazonaws.com')
60
61    valid_states = (
62        'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'CREATE_COMPLETE',
63        'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE',
64        'DELETE_IN_PROGRESS', 'DELETE_FAILED', 'DELETE_COMPLETE',
65        'UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS',
66        'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_IN_PROGRESS',
67        'UPDATE_ROLLBACK_FAILED',
68        'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS',
69        'UPDATE_ROLLBACK_COMPLETE')
70
71    def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
72                 is_secure=True, port=None, proxy=None, proxy_port=None,
73                 proxy_user=None, proxy_pass=None, debug=0,
74                 https_connection_factory=None, region=None, path='/',
75                 converter=None, security_token=None, validate_certs=True,
76                 profile_name=None):
77        if not region:
78            region = RegionInfo(self, self.DefaultRegionName,
79                self.DefaultRegionEndpoint, CloudFormationConnection)
80        self.region = region
81        super(CloudFormationConnection, self).__init__(aws_access_key_id,
82                                    aws_secret_access_key,
83                                    is_secure, port, proxy, proxy_port,
84                                    proxy_user, proxy_pass,
85                                    self.region.endpoint, debug,
86                                    https_connection_factory, path,
87                                    security_token,
88                                    validate_certs=validate_certs,
89                                    profile_name=profile_name)
90
91    def _required_auth_capability(self):
92        return ['hmac-v4']
93
94    def encode_bool(self, v):
95        v = bool(v)
96        return {True: "true", False: "false"}[v]
97
98    def _build_create_or_update_params(self, stack_name, template_body,
99            template_url, parameters, disable_rollback, timeout_in_minutes,
100            notification_arns, capabilities, on_failure, stack_policy_body,
101            stack_policy_url, tags, use_previous_template=None,
102            stack_policy_during_update_body=None,
103            stack_policy_during_update_url=None):
104        """
105        Helper that creates JSON parameters needed by a Stack Create or
106        Stack Update call.
107
108        :type stack_name: string
109        :param stack_name:
110        The name associated with the stack. The name must be unique within your
111            AWS account.
112
113        Must contain only alphanumeric characters (case sensitive) and start
114            with an alpha character. Maximum length of the name is 255
115            characters.
116
117        :type template_body: string
118        :param template_body: Structure containing the template body. (For more
119            information, go to `Template Anatomy`_ in the AWS CloudFormation
120            User Guide.)
121        Conditional: You must pass either `UsePreviousTemplate` or one of
122            `TemplateBody` or `TemplateUrl`. If both `TemplateBody` and
123            `TemplateUrl` are passed, only `TemplateBody` is used.
124            `TemplateBody`.
125
126        :type template_url: string
127        :param template_url: Location of file containing the template body. The
128            URL must point to a template (max size: 307,200 bytes) located in
129            an S3 bucket in the same region as the stack. For more information,
130            go to the `Template Anatomy`_ in the AWS CloudFormation User Guide.
131        Conditional: You must pass either `UsePreviousTemplate` or one of
132            `TemplateBody` or `TemplateUrl`. If both `TemplateBody` and
133            `TemplateUrl` are passed, only `TemplateBody` is used.
134            `TemplateBody`.
135
136        :type parameters: list
137        :param parameters: A list of key/value tuples that specify input
138            parameters for the stack. A 3-tuple (key, value, bool) may be used to
139            specify the `UsePreviousValue` option.
140
141        :type disable_rollback: boolean
142        :param disable_rollback: Set to `True` to disable rollback of the stack
143            if stack creation failed. You can specify either `DisableRollback`
144            or `OnFailure`, but not both.
145        Default: `False`
146
147        :type timeout_in_minutes: integer
148        :param timeout_in_minutes: The amount of time that can pass before the
149            stack status becomes CREATE_FAILED; if `DisableRollback` is not set
150            or is set to `False`, the stack will be rolled back.
151
152        :type notification_arns: list
153        :param notification_arns: The Simple Notification Service (SNS) topic
154            ARNs to publish stack related events. You can find your SNS topic
155            ARNs using the `SNS console`_ or your Command Line Interface (CLI).
156
157        :type capabilities: list
158        :param capabilities: The list of capabilities that you want to allow in
159            the stack. If your template contains certain resources, you must
160            specify the CAPABILITY_IAM value for this parameter; otherwise,
161            this action returns an InsufficientCapabilities error. The
162            following resources require you to specify the capabilities
163            parameter: `AWS::CloudFormation::Stack`_, `AWS::IAM::AccessKey`_,
164            `AWS::IAM::Group`_, `AWS::IAM::InstanceProfile`_,
165            `AWS::IAM::Policy`_, `AWS::IAM::Role`_, `AWS::IAM::User`_, and
166            `AWS::IAM::UserToGroupAddition`_.
167
168        :type on_failure: string
169        :param on_failure: Determines what action will be taken if stack
170            creation fails. This must be one of: DO_NOTHING, ROLLBACK, or
171            DELETE. You can specify either `OnFailure` or `DisableRollback`,
172            but not both.
173        Default: `ROLLBACK`
174
175        :type stack_policy_body: string
176        :param stack_policy_body: Structure containing the stack policy body.
177            (For more information, go to ` Prevent Updates to Stack Resources`_
178            in the AWS CloudFormation User Guide.)
179        If you pass `StackPolicyBody` and `StackPolicyURL`, only
180            `StackPolicyBody` is used.
181
182        :type stack_policy_url: string
183        :param stack_policy_url: Location of a file containing the stack
184            policy. The URL must point to a policy (max size: 16KB) located in
185            an S3 bucket in the same region as the stack. If you pass
186            `StackPolicyBody` and `StackPolicyURL`, only `StackPolicyBody` is
187            used.
188
189        :type tags: list
190        :param tags: A set of user-defined `Tags` to associate with this stack,
191            represented by key/value pairs. Tags defined for the stack are
192            propagated to EC2 resources that are created as part of the stack.
193            A maximum number of 10 tags can be specified.
194
195        :type use_previous_template: boolean
196        :param use_previous_template: Set to `True` to use the previous
197            template instead of uploading a new one via `TemplateBody` or
198            `TemplateURL`.
199        Conditional: You must pass either `UsePreviousTemplate` or one of
200            `TemplateBody` or `TemplateUrl`.
201
202        :type stack_policy_during_update_body: string
203        :param stack_policy_during_update_body: Structure containing the
204            temporary overriding stack policy body. If you pass
205            `StackPolicyDuringUpdateBody` and `StackPolicyDuringUpdateURL`,
206            only `StackPolicyDuringUpdateBody` is used.
207        If you want to update protected resources, specify a temporary
208            overriding stack policy during this update. If you do not specify a
209            stack policy, the current policy that associated with the stack
210            will be used.
211
212        :type stack_policy_during_update_url: string
213        :param stack_policy_during_update_url: Location of a file containing
214            the temporary overriding stack policy. The URL must point to a
215            policy (max size: 16KB) located in an S3 bucket in the same region
216            as the stack. If you pass `StackPolicyDuringUpdateBody` and
217            `StackPolicyDuringUpdateURL`, only `StackPolicyDuringUpdateBody` is
218            used.
219        If you want to update protected resources, specify a temporary
220            overriding stack policy during this update. If you do not specify a
221            stack policy, the current policy that is associated with the stack
222            will be used.
223
224        :rtype: dict
225        :return: JSON parameters represented as a Python dict.
226        """
227        params = {'ContentType': "JSON", 'StackName': stack_name,
228                'DisableRollback': self.encode_bool(disable_rollback)}
229        if template_body:
230            params['TemplateBody'] = template_body
231        if template_url:
232            params['TemplateURL'] = template_url
233        if use_previous_template is not None:
234            params['UsePreviousTemplate'] = self.encode_bool(use_previous_template)
235        if template_body and template_url:
236            boto.log.warning("If both TemplateBody and TemplateURL are"
237                " specified, only TemplateBody will be honored by the API")
238        if parameters and len(parameters) > 0:
239            for i, parameter_tuple in enumerate(parameters):
240                key, value = parameter_tuple[:2]
241                use_previous = (parameter_tuple[2]
242                                if len(parameter_tuple) > 2 else False)
243                params['Parameters.member.%d.ParameterKey' % (i + 1)] = key
244                if use_previous:
245                    params['Parameters.member.%d.UsePreviousValue'
246                           % (i + 1)] = self.encode_bool(use_previous)
247                else:
248                    params['Parameters.member.%d.ParameterValue' % (i + 1)] = value
249
250        if capabilities:
251            for i, value in enumerate(capabilities):
252                params['Capabilities.member.%d' % (i + 1)] = value
253        if tags:
254            for i, (key, value) in enumerate(tags.items()):
255                params['Tags.member.%d.Key' % (i + 1)] = key
256                params['Tags.member.%d.Value' % (i + 1)] = value
257        if notification_arns and len(notification_arns) > 0:
258            self.build_list_params(params, notification_arns,
259                                   "NotificationARNs.member")
260        if timeout_in_minutes:
261            params['TimeoutInMinutes'] = int(timeout_in_minutes)
262        if disable_rollback is not None:
263            params['DisableRollback'] = str(
264                disable_rollback).lower()
265        if on_failure is not None:
266            params['OnFailure'] = on_failure
267        if stack_policy_body is not None:
268            params['StackPolicyBody'] = stack_policy_body
269        if stack_policy_url is not None:
270            params['StackPolicyURL'] = stack_policy_url
271        if stack_policy_during_update_body is not None:
272            params['StackPolicyDuringUpdateBody'] = stack_policy_during_update_body
273        if stack_policy_during_update_url is not None:
274            params['StackPolicyDuringUpdateURL'] = stack_policy_during_update_url
275        return params
276
277    def _do_request(self, call, params, path, method):
278        """
279        Do a request via ``self.make_request`` and parse the JSON response.
280
281        :type call: string
282        :param call: Call name, e.g. ``CreateStack``
283
284        :type params: dict
285        :param params: Dictionary of call parameters
286
287        :type path: string
288        :param path: Server path
289
290        :type method: string
291        :param method: HTTP method to use
292
293        :rtype: dict
294        :return: Parsed JSON response data
295        """
296        response = self.make_request(call, params, path, method)
297        body = response.read().decode('utf-8')
298        if response.status == 200:
299            body = json.loads(body)
300            return body
301        else:
302            boto.log.error('%s %s' % (response.status, response.reason))
303            boto.log.error('%s' % body)
304            raise self.ResponseError(response.status, response.reason, body=body)
305
306    def create_stack(self, stack_name, template_body=None, template_url=None,
307            parameters=None, notification_arns=None, disable_rollback=None,
308            timeout_in_minutes=None, capabilities=None, tags=None,
309            on_failure=None, stack_policy_body=None, stack_policy_url=None):
310        """
311        Creates a stack as specified in the template. After the call
312        completes successfully, the stack creation starts. You can
313        check the status of the stack via the DescribeStacks API.
314        Currently, the limit for stacks is 20 stacks per account per
315        region.
316
317        :type stack_name: string
318        :param stack_name:
319        The name associated with the stack. The name must be unique within your
320            AWS account.
321
322        Must contain only alphanumeric characters (case sensitive) and start
323            with an alpha character. Maximum length of the name is 255
324            characters.
325
326        :type template_body: string
327        :param template_body: Structure containing the template body. (For more
328            information, go to `Template Anatomy`_ in the AWS CloudFormation
329            User Guide.)
330        Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are
331            passed, only `TemplateBody` is used.
332
333        :type template_url: string
334        :param template_url: Location of file containing the template body. The
335            URL must point to a template (max size: 307,200 bytes) located in
336            an S3 bucket in the same region as the stack. For more information,
337            go to the `Template Anatomy`_ in the AWS CloudFormation User Guide.
338        Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are
339            passed, only `TemplateBody` is used.
340
341        :type parameters: list
342        :param parameters: A list of key/value tuples that specify input
343            parameters for the stack.
344
345        :type disable_rollback: boolean
346        :param disable_rollback: Set to `True` to disable rollback of the stack
347            if stack creation failed. You can specify either `DisableRollback`
348            or `OnFailure`, but not both.
349        Default: `False`
350
351        :type timeout_in_minutes: integer
352        :param timeout_in_minutes: The amount of time that can pass before the
353            stack status becomes CREATE_FAILED; if `DisableRollback` is not set
354            or is set to `False`, the stack will be rolled back.
355
356        :type notification_arns: list
357        :param notification_arns: The Simple Notification Service (SNS) topic
358            ARNs to publish stack related events. You can find your SNS topic
359            ARNs using the `SNS console`_ or your Command Line Interface (CLI).
360
361        :type capabilities: list
362        :param capabilities: The list of capabilities that you want to allow in
363            the stack. If your template contains certain resources, you must
364            specify the CAPABILITY_IAM value for this parameter; otherwise,
365            this action returns an InsufficientCapabilities error. The
366            following resources require you to specify the capabilities
367            parameter: `AWS::CloudFormation::Stack`_, `AWS::IAM::AccessKey`_,
368            `AWS::IAM::Group`_, `AWS::IAM::InstanceProfile`_,
369            `AWS::IAM::Policy`_, `AWS::IAM::Role`_, `AWS::IAM::User`_, and
370            `AWS::IAM::UserToGroupAddition`_.
371
372        :type on_failure: string
373        :param on_failure: Determines what action will be taken if stack
374            creation fails. This must be one of: DO_NOTHING, ROLLBACK, or
375            DELETE. You can specify either `OnFailure` or `DisableRollback`,
376            but not both.
377        Default: `ROLLBACK`
378
379        :type stack_policy_body: string
380        :param stack_policy_body: Structure containing the stack policy body.
381            (For more information, go to ` Prevent Updates to Stack Resources`_
382            in the AWS CloudFormation User Guide.)
383        If you pass `StackPolicyBody` and `StackPolicyURL`, only
384            `StackPolicyBody` is used.
385
386        :type stack_policy_url: string
387        :param stack_policy_url: Location of a file containing the stack
388            policy. The URL must point to a policy (max size: 16KB) located in
389            an S3 bucket in the same region as the stack. If you pass
390            `StackPolicyBody` and `StackPolicyURL`, only `StackPolicyBody` is
391            used.
392
393        :type tags: dict
394        :param tags: A set of user-defined `Tags` to associate with this stack,
395            represented by key/value pairs. Tags defined for the stack are
396            propagated to EC2 resources that are created as part of the stack.
397            A maximum number of 10 tags can be specified.
398        """
399        params = self._build_create_or_update_params(stack_name, template_body,
400            template_url, parameters, disable_rollback, timeout_in_minutes,
401            notification_arns, capabilities, on_failure, stack_policy_body,
402            stack_policy_url, tags)
403        body = self._do_request('CreateStack', params, '/', 'POST')
404        return body['CreateStackResponse']['CreateStackResult']['StackId']
405
406    def update_stack(self, stack_name, template_body=None, template_url=None,
407            parameters=None, notification_arns=None, disable_rollback=False,
408            timeout_in_minutes=None, capabilities=None, tags=None,
409            use_previous_template=None,
410            stack_policy_during_update_body=None,
411            stack_policy_during_update_url=None,
412            stack_policy_body=None, stack_policy_url=None):
413        """
414        Updates a stack as specified in the template. After the call
415        completes successfully, the stack update starts. You can check
416        the status of the stack via the DescribeStacks action.
417
418
419
420        **Note: **You cannot update `AWS::S3::Bucket`_ resources, for
421        example, to add or modify tags.
422
423
424
425        To get a copy of the template for an existing stack, you can
426        use the GetTemplate action.
427
428        Tags that were associated with this stack during creation time
429        will still be associated with the stack after an `UpdateStack`
430        operation.
431
432        For more information about creating an update template,
433        updating a stack, and monitoring the progress of the update,
434        see `Updating a Stack`_.
435
436        :type stack_name: string
437        :param stack_name:
438        The name or stack ID of the stack to update.
439
440        Must contain only alphanumeric characters (case sensitive) and start
441            with an alpha character. Maximum length of the name is 255
442            characters.
443
444        :type template_body: string
445        :param template_body: Structure containing the template body. (For more
446            information, go to `Template Anatomy`_ in the AWS CloudFormation
447            User Guide.)
448        Conditional: You must pass either `UsePreviousTemplate` or one of
449            `TemplateBody` or `TemplateUrl`. If both `TemplateBody` and
450            `TemplateUrl` are passed, only `TemplateBody` is used.
451
452        :type template_url: string
453        :param template_url: Location of file containing the template body. The
454            URL must point to a template (max size: 307,200 bytes) located in
455            an S3 bucket in the same region as the stack. For more information,
456            go to the `Template Anatomy`_ in the AWS CloudFormation User Guide.
457        Conditional: You must pass either `UsePreviousTemplate` or one of
458            `TemplateBody` or `TemplateUrl`. If both `TemplateBody` and
459            `TemplateUrl` are passed, only `TemplateBody` is used.
460            `TemplateBody`.
461
462        :type use_previous_template: boolean
463        :param use_previous_template: Set to `True` to use the previous
464            template instead of uploading a new one via `TemplateBody` or
465            `TemplateURL`.
466        Conditional: You must pass either `UsePreviousTemplate` or one of
467            `TemplateBody` or `TemplateUrl`.
468
469        :type parameters: list
470        :param parameters: A list of key/value tuples that specify input
471            parameters for the stack. A 3-tuple (key, value, bool) may be used to
472            specify the `UsePreviousValue` option.
473
474        :type notification_arns: list
475        :param notification_arns: The Simple Notification Service (SNS) topic
476            ARNs to publish stack related events. You can find your SNS topic
477            ARNs using the `SNS console`_ or your Command Line Interface (CLI).
478
479        :type disable_rollback: bool
480        :param disable_rollback: Indicates whether or not to rollback on
481            failure.
482
483        :type timeout_in_minutes: integer
484        :param timeout_in_minutes: The amount of time that can pass before the
485            stack status becomes CREATE_FAILED; if `DisableRollback` is not set
486            or is set to `False`, the stack will be rolled back.
487
488        :type capabilities: list
489        :param capabilities: The list of capabilities you want to allow in
490            the stack.  Currently, the only valid capability is
491            'CAPABILITY_IAM'.
492
493        :type tags: dict
494        :param tags: A set of user-defined `Tags` to associate with this stack,
495            represented by key/value pairs. Tags defined for the stack are
496            propagated to EC2 resources that are created as part of the stack.
497            A maximum number of 10 tags can be specified.
498
499        :type template_url: string
500        :param template_url: Location of file containing the template body. The
501            URL must point to a template located in an S3 bucket in the same
502            region as the stack. For more information, go to `Template
503            Anatomy`_ in the AWS CloudFormation User Guide.
504        Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are
505            passed, only `TemplateBody` is used.
506
507        :type stack_policy_during_update_body: string
508        :param stack_policy_during_update_body: Structure containing the
509            temporary overriding stack policy body. If you pass
510            `StackPolicyDuringUpdateBody` and `StackPolicyDuringUpdateURL`,
511            only `StackPolicyDuringUpdateBody` is used.
512        If you want to update protected resources, specify a temporary
513            overriding stack policy during this update. If you do not specify a
514            stack policy, the current policy that associated with the stack
515            will be used.
516
517        :type stack_policy_during_update_url: string
518        :param stack_policy_during_update_url: Location of a file containing
519            the temporary overriding stack policy. The URL must point to a
520            policy (max size: 16KB) located in an S3 bucket in the same region
521            as the stack. If you pass `StackPolicyDuringUpdateBody` and
522            `StackPolicyDuringUpdateURL`, only `StackPolicyDuringUpdateBody` is
523            used.
524        If you want to update protected resources, specify a temporary
525            overriding stack policy during this update. If you do not specify a
526            stack policy, the current policy that is associated with the stack
527            will be used.
528
529        :rtype: string
530        :return: The unique Stack ID.
531        """
532        params = self._build_create_or_update_params(stack_name, template_body,
533            template_url, parameters, disable_rollback, timeout_in_minutes,
534            notification_arns, capabilities, None, stack_policy_body,
535            stack_policy_url, tags, use_previous_template,
536            stack_policy_during_update_body, stack_policy_during_update_url)
537        body = self._do_request('UpdateStack', params, '/', 'POST')
538        return body['UpdateStackResponse']['UpdateStackResult']['StackId']
539
540    def delete_stack(self, stack_name_or_id):
541        """
542        Deletes a specified stack. Once the call completes
543        successfully, stack deletion starts. Deleted stacks do not
544        show up in the DescribeStacks API if the deletion has been
545        completed successfully.
546
547        :type stack_name_or_id: string
548        :param stack_name_or_id: The name or the unique identifier associated
549            with the stack.
550
551        """
552        params = {'ContentType': "JSON", 'StackName': stack_name_or_id}
553        return self._do_request('DeleteStack', params, '/', 'GET')
554
555    def describe_stack_events(self, stack_name_or_id=None, next_token=None):
556        """
557        Returns all stack related events for a specified stack. For
558        more information about a stack's event history, go to
559        `Stacks`_ in the AWS CloudFormation User Guide.
560        Events are returned, even if the stack never existed or has
561        been successfully deleted.
562
563        :type stack_name_or_id: string
564        :param stack_name_or_id: The name or the unique identifier associated
565            with the stack.
566        Default: There is no default value.
567
568        :type next_token: string
569        :param next_token: String that identifies the start of the next list of
570            events, if there is one.
571        Default: There is no default value.
572
573        """
574        params = {}
575        if stack_name_or_id:
576            params['StackName'] = stack_name_or_id
577        if next_token:
578            params['NextToken'] = next_token
579        return self.get_list('DescribeStackEvents', params, [('member',
580            StackEvent)])
581
582    def describe_stack_resource(self, stack_name_or_id, logical_resource_id):
583        """
584        Returns a description of the specified resource in the
585        specified stack.
586
587        For deleted stacks, DescribeStackResource returns resource
588        information for up to 90 days after the stack has been
589        deleted.
590
591        :type stack_name_or_id: string
592        :param stack_name_or_id: The name or the unique identifier associated
593            with the stack.
594        Default: There is no default value.
595
596        :type logical_resource_id: string
597        :param logical_resource_id: The logical name of the resource as
598            specified in the template.
599        Default: There is no default value.
600
601        """
602        params = {'ContentType': "JSON", 'StackName': stack_name_or_id,
603                'LogicalResourceId': logical_resource_id}
604        return self._do_request('DescribeStackResource', params, '/', 'GET')
605
606    def describe_stack_resources(self, stack_name_or_id=None,
607            logical_resource_id=None,
608            physical_resource_id=None):
609        """
610        Returns AWS resource descriptions for running and deleted
611        stacks. If `StackName` is specified, all the associated
612        resources that are part of the stack are returned. If
613        `PhysicalResourceId` is specified, the associated resources of
614        the stack that the resource belongs to are returned.
615        Only the first 100 resources will be returned. If your stack
616        has more resources than this, you should use
617        `ListStackResources` instead.
618        For deleted stacks, `DescribeStackResources` returns resource
619        information for up to 90 days after the stack has been
620        deleted.
621
622        You must specify either `StackName` or `PhysicalResourceId`,
623        but not both. In addition, you can specify `LogicalResourceId`
624        to filter the returned result. For more information about
625        resources, the `LogicalResourceId` and `PhysicalResourceId`,
626        go to the `AWS CloudFormation User Guide`_.
627        A `ValidationError` is returned if you specify both
628        `StackName` and `PhysicalResourceId` in the same request.
629
630        :type stack_name_or_id: string
631        :param stack_name_or_id: The name or the unique identifier associated
632            with the stack.
633        Required: Conditional. If you do not specify `StackName`, you must
634            specify `PhysicalResourceId`.
635
636        Default: There is no default value.
637
638        :type logical_resource_id: string
639        :param logical_resource_id: The logical name of the resource as
640            specified in the template.
641        Default: There is no default value.
642
643        :type physical_resource_id: string
644        :param physical_resource_id: The name or unique identifier that
645            corresponds to a physical instance ID of a resource supported by
646            AWS CloudFormation.
647        For example, for an Amazon Elastic Compute Cloud (EC2) instance,
648            `PhysicalResourceId` corresponds to the `InstanceId`. You can pass
649            the EC2 `InstanceId` to `DescribeStackResources` to find which
650            stack the instance belongs to and what other resources are part of
651            the stack.
652
653        Required: Conditional. If you do not specify `PhysicalResourceId`, you
654            must specify `StackName`.
655
656        Default: There is no default value.
657
658        """
659        params = {}
660        if stack_name_or_id:
661            params['StackName'] = stack_name_or_id
662        if logical_resource_id:
663            params['LogicalResourceId'] = logical_resource_id
664        if physical_resource_id:
665            params['PhysicalResourceId'] = physical_resource_id
666        return self.get_list('DescribeStackResources', params,
667                             [('member', StackResource)])
668
669    def describe_stacks(self, stack_name_or_id=None, next_token=None):
670        """
671        Returns the description for the specified stack; if no stack
672        name was specified, then it returns the description for all
673        the stacks created.
674
675        :type stack_name_or_id: string
676        :param stack_name_or_id: The name or the unique identifier associated
677            with the stack.
678        Default: There is no default value.
679
680        :type next_token: string
681        :param next_token: String that identifies the start of the next list of
682            stacks, if there is one.
683
684        """
685        params = {}
686        if stack_name_or_id:
687            params['StackName'] = stack_name_or_id
688        if next_token is not None:
689            params['NextToken'] = next_token
690        return self.get_list('DescribeStacks', params, [('member', Stack)])
691
692    def get_template(self, stack_name_or_id):
693        """
694        Returns the template body for a specified stack. You can get
695        the template for running or deleted stacks.
696
697        For deleted stacks, GetTemplate returns the template for up to
698        90 days after the stack has been deleted.
699        If the template does not exist, a `ValidationError` is
700        returned.
701
702        :type stack_name_or_id: string
703        :param stack_name_or_id: The name or the unique identifier associated
704            with the stack, which are not always interchangeable:
705
706        + Running stacks: You can specify either the stack's name or its unique
707              stack ID.
708        + Deleted stacks: You must specify the unique stack ID.
709
710
711        Default: There is no default value.
712
713        """
714        params = {'ContentType': "JSON", 'StackName': stack_name_or_id}
715        return self._do_request('GetTemplate', params, '/', 'GET')
716
717    def list_stack_resources(self, stack_name_or_id, next_token=None):
718        """
719        Returns descriptions of all resources of the specified stack.
720
721        For deleted stacks, ListStackResources returns resource
722        information for up to 90 days after the stack has been
723        deleted.
724
725        :type stack_name_or_id: string
726        :param stack_name_or_id: The name or the unique identifier associated
727            with the stack, which are not always interchangeable:
728
729        + Running stacks: You can specify either the stack's name or its unique
730              stack ID.
731        + Deleted stacks: You must specify the unique stack ID.
732
733
734        Default: There is no default value.
735
736        :type next_token: string
737        :param next_token: String that identifies the start of the next list of
738            stack resource summaries, if there is one.
739        Default: There is no default value.
740
741        """
742        params = {'StackName': stack_name_or_id}
743        if next_token:
744            params['NextToken'] = next_token
745        return self.get_list('ListStackResources', params,
746                             [('member', StackResourceSummary)])
747
748    def list_stacks(self, stack_status_filters=None, next_token=None):
749        """
750        Returns the summary information for stacks whose status
751        matches the specified StackStatusFilter. Summary information
752        for stacks that have been deleted is kept for 90 days after
753        the stack is deleted. If no StackStatusFilter is specified,
754        summary information for all stacks is returned (including
755        existing stacks and stacks that have been deleted).
756
757        :type next_token: string
758        :param next_token: String that identifies the start of the next list of
759            stacks, if there is one.
760        Default: There is no default value.
761
762        :type stack_status_filter: list
763        :param stack_status_filter: Stack status to use as a filter. Specify
764            one or more stack status codes to list only stacks with the
765            specified status codes. For a complete list of stack status codes,
766            see the `StackStatus` parameter of the Stack data type.
767
768        """
769        params = {}
770        if next_token:
771            params['NextToken'] = next_token
772        if stack_status_filters and len(stack_status_filters) > 0:
773            self.build_list_params(params, stack_status_filters,
774                "StackStatusFilter.member")
775
776        return self.get_list('ListStacks', params,
777                             [('member', StackSummary)])
778
779    def validate_template(self, template_body=None, template_url=None):
780        """
781        Validates a specified template.
782
783        :type template_body: string
784        :param template_body: String containing the template body. (For more
785            information, go to `Template Anatomy`_ in the AWS CloudFormation
786            User Guide.)
787        Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are
788            passed, only `TemplateBody` is used.
789
790        :type template_url: string
791        :param template_url: Location of file containing the template body. The
792            URL must point to a template (max size: 307,200 bytes) located in
793            an S3 bucket in the same region as the stack. For more information,
794            go to `Template Anatomy`_ in the AWS CloudFormation User Guide.
795        Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are
796            passed, only `TemplateBody` is used.
797
798        """
799        params = {}
800        if template_body:
801            params['TemplateBody'] = template_body
802        if template_url:
803            params['TemplateURL'] = template_url
804        if template_body and template_url:
805            boto.log.warning("If both TemplateBody and TemplateURL are"
806                " specified, only TemplateBody will be honored by the API")
807        return self.get_object('ValidateTemplate', params, Template,
808                verb="POST")
809
810    def cancel_update_stack(self, stack_name_or_id=None):
811        """
812        Cancels an update on the specified stack. If the call
813        completes successfully, the stack will roll back the update
814        and revert to the previous stack configuration.
815        Only stacks that are in the UPDATE_IN_PROGRESS state can be
816        canceled.
817
818        :type stack_name_or_id: string
819        :param stack_name_or_id: The name or the unique identifier associated with
820            the stack.
821
822        """
823        params = {}
824        if stack_name_or_id:
825            params['StackName'] = stack_name_or_id
826        return self.get_status('CancelUpdateStack', params)
827
828    def estimate_template_cost(self, template_body=None, template_url=None,
829                               parameters=None):
830        """
831        Returns the estimated monthly cost of a template. The return
832        value is an AWS Simple Monthly Calculator URL with a query
833        string that describes the resources required to run the
834        template.
835
836        :type template_body: string
837        :param template_body: Structure containing the template body. (For more
838            information, go to `Template Anatomy`_ in the AWS CloudFormation
839            User Guide.)
840        Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are
841            passed, only `TemplateBody` is used.
842
843        :type template_url: string
844        :param template_url: Location of file containing the template body. The
845            URL must point to a template located in an S3 bucket in the same
846            region as the stack. For more information, go to `Template
847            Anatomy`_ in the AWS CloudFormation User Guide.
848        Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are
849            passed, only `TemplateBody` is used.
850
851        :type parameters: list
852        :param parameters: A list of key/value tuples that specify input
853            parameters for the template.
854
855        :rtype: string
856        :returns: URL to pre-filled cost calculator
857        """
858        params = {'ContentType': "JSON"}
859        if template_body is not None:
860            params['TemplateBody'] = template_body
861        if template_url is not None:
862            params['TemplateURL'] = template_url
863        if parameters and len(parameters) > 0:
864            for i, (key, value) in enumerate(parameters):
865                params['Parameters.member.%d.ParameterKey' % (i + 1)] = key
866                params['Parameters.member.%d.ParameterValue' % (i + 1)] = value
867
868        response = self._do_request('EstimateTemplateCost', params, '/', 'POST')
869        return response['EstimateTemplateCostResponse']\
870                       ['EstimateTemplateCostResult']\
871                       ['Url']
872
873    def get_stack_policy(self, stack_name_or_id):
874        """
875        Returns the stack policy for a specified stack. If a stack
876        doesn't have a policy, a null value is returned.
877
878        :type stack_name_or_id: string
879        :param stack_name_or_id: The name or stack ID that is associated with
880            the stack whose policy you want to get.
881
882        :rtype: string
883        :return: The policy JSON document
884        """
885        params = {'ContentType': "JSON", 'StackName': stack_name_or_id, }
886        response = self._do_request('GetStackPolicy', params, '/', 'POST')
887        return response['GetStackPolicyResponse']\
888                       ['GetStackPolicyResult']\
889                       ['StackPolicyBody']
890
891    def set_stack_policy(self, stack_name_or_id, stack_policy_body=None,
892                         stack_policy_url=None):
893        """
894        Sets a stack policy for a specified stack.
895
896        :type stack_name_or_id: string
897        :param stack_name_or_id: The name or stack ID that you want to
898            associate a policy with.
899
900        :type stack_policy_body: string
901        :param stack_policy_body: Structure containing the stack policy body.
902            (For more information, go to ` Prevent Updates to Stack Resources`_
903            in the AWS CloudFormation User Guide.)
904        You must pass `StackPolicyBody` or `StackPolicyURL`. If both are
905            passed, only `StackPolicyBody` is used.
906
907        :type stack_policy_url: string
908        :param stack_policy_url: Location of a file containing the stack
909            policy. The URL must point to a policy (max size: 16KB) located in
910            an S3 bucket in the same region as the stack. You must pass
911            `StackPolicyBody` or `StackPolicyURL`. If both are passed, only
912            `StackPolicyBody` is used.
913
914        """
915        params = {'ContentType': "JSON", 'StackName': stack_name_or_id, }
916        if stack_policy_body is not None:
917            params['StackPolicyBody'] = stack_policy_body
918        if stack_policy_url is not None:
919            params['StackPolicyURL'] = stack_policy_url
920
921        response = self._do_request('SetStackPolicy', params, '/', 'POST')
922        return response['SetStackPolicyResponse']
923