| 33 | |
| 34 | |
| 35 | class Deployer: |
| 36 | def __init__( |
| 37 | self, |
| 38 | cloudformation_client, |
| 39 | changeset_prefix="awscli-cloudformation-package-deploy-", |
| 40 | ): |
| 41 | self._client = cloudformation_client |
| 42 | self.changeset_prefix = changeset_prefix |
| 43 | |
| 44 | def has_stack(self, stack_name): |
| 45 | """ |
| 46 | Checks if a CloudFormation stack with given name exists |
| 47 | |
| 48 | :param stack_name: Name or ID of the stack |
| 49 | :return: True if stack exists. False otherwise |
| 50 | """ |
| 51 | try: |
| 52 | resp = self._client.describe_stacks(StackName=stack_name) |
| 53 | if len(resp["Stacks"]) != 1: |
| 54 | return False |
| 55 | |
| 56 | # When you run CreateChangeSet on a a stack that does not exist, |
| 57 | # CloudFormation will create a stack and set it's status |
| 58 | # REVIEW_IN_PROGRESS. However this stack is cannot be manipulated |
| 59 | # by "update" commands. Under this circumstances, we treat like |
| 60 | # this stack does not exist and call CreateChangeSet will |
| 61 | # ChangeSetType set to CREATE and not UPDATE. |
| 62 | stack = resp["Stacks"][0] |
| 63 | return stack["StackStatus"] != "REVIEW_IN_PROGRESS" |
| 64 | |
| 65 | except botocore.exceptions.ClientError as e: |
| 66 | # If a stack does not exist, describe_stacks will throw an |
| 67 | # exception. Unfortunately we don't have a better way than parsing |
| 68 | # the exception msg to understand the nature of this exception. |
| 69 | msg = str(e) |
| 70 | |
| 71 | if f"Stack with id {stack_name} does not exist" in msg: |
| 72 | LOG.debug(f"Stack with id {stack_name} does not exist") |
| 73 | return False |
| 74 | else: |
| 75 | # We don't know anything about this exception. Don't handle |
| 76 | LOG.debug("Unable to get stack details.", exc_info=e) |
| 77 | raise e |
| 78 | |
| 79 | def create_changeset( |
| 80 | self, |
| 81 | stack_name, |
| 82 | cfn_template, |
| 83 | parameter_values, |
| 84 | capabilities, |
| 85 | role_arn, |
| 86 | notification_arns, |
| 87 | s3_uploader, |
| 88 | tags, |
| 89 | ): |
| 90 | """ |
| 91 | Call Cloudformation to create a changeset and wait for it to complete |
| 92 |
no outgoing calls