def test_stack_time_attributes(cfn_client, deploy_cfn_template):
    api_name = f"test_{short_uid()}"
    template_path = os.path.join(os.path.dirname(__file__),
                                 "../templates/simple_api.yaml")

    deployed = deploy_cfn_template(
        template_path=template_path,
        parameters={"ApiName": api_name},
    )
    stack_name = deployed.stack_name
    assert "CreationTime" in cfn_client.describe_stacks(
        StackName=stack_name)["Stacks"][0]

    api_name = f"test_{short_uid()}"
    stack_id = deployed.stack_id
    cfn_client.update_stack(
        StackName=stack_name,
        TemplateBody=load_template_file(template_path),
        Parameters=[{
            "ParameterKey": "ApiName",
            "ParameterValue": api_name
        }],
    )

    def wait_stack_done():
        return cfn_client.describe_stacks(
            StackName=stack_id)["Stacks"][0]["StackStatus"] in [
                "CREATE_COMPLETE",
                "UPDATE_COMPLETE",
            ]

    assert wait_until(wait_stack_done)

    assert "LastUpdatedTime" in cfn_client.describe_stacks(
        StackName=stack_name)["Stacks"][0]
    cfn_client.delete_stack(StackName=stack_name, )
    assert "DeletionTime" in cfn_client.describe_stacks(
        StackName=stack_name)["Stacks"][0]
Exemple #2
0
def load_template_raw(file_name: str):
    return load_template_file(
        os.path.join(os.path.dirname(__file__), "../templates", file_name))
Exemple #3
0
    def _deploy(
        *,
        is_update: Optional[bool] = False,
        stack_name: Optional[str] = None,
        change_set_name: Optional[str] = None,
        template: Optional[str] = None,
        template_path: Optional[str | os.PathLike] = None,
        template_mapping: Optional[Dict[str, any]] = None,
        parameters: Optional[Dict[str, str]] = None,
    ) -> DeployResult:
        if is_update:
            assert stack_name
        stack_name = stack_name or f"stack-{short_uid()}"
        change_set_name = change_set_name or f"change-set-{short_uid()}"

        if template_path is not None:
            template = load_template_file(template_path)
        template_rendered = render_template(template, **(template_mapping
                                                         or {}))

        response = cfn_client.create_change_set(
            StackName=stack_name,
            ChangeSetName=change_set_name,
            TemplateBody=template_rendered,
            Capabilities=[
                "CAPABILITY_AUTO_EXPAND", "CAPABILITY_IAM",
                "CAPABILITY_NAMED_IAM"
            ],
            ChangeSetType=("UPDATE" if is_update else "CREATE"),
            Parameters=[{
                "ParameterKey": k,
                "ParameterValue": v,
            } for (k, v) in (parameters or {}).items()],
        )
        change_set_id = response["Id"]
        stack_id = response["StackId"]

        assert wait_until(is_change_set_created_and_available(change_set_id),
                          _max_wait=60)
        cfn_client.execute_change_set(ChangeSetName=change_set_id)
        assert wait_until(is_change_set_finished(change_set_id), _max_wait=60)

        outputs = cfn_client.describe_stacks(
            StackName=stack_id)["Stacks"][0].get("Outputs", [])

        mapped_outputs = {o["OutputKey"]: o["OutputValue"] for o in outputs}

        state.append({"stack_id": stack_id, "change_set_id": change_set_id})

        def _destroy_stack():
            cfn_client.delete_stack(StackName=stack_id)

            def _await_stack_delete():
                return (cfn_client.describe_stacks(StackName=stack_id)
                        ["Stacks"][0]["StackStatus"] == "DELETE_COMPLETE")

            assert wait_until(_await_stack_delete, _max_wait=60)
            time.sleep(
                2
            )  # TODO: fix in localstack. stack should only be in DELETE_COMPLETE state after all resources have been deleted

        return DeployResult(change_set_id, stack_id, stack_name,
                            change_set_name, mapped_outputs, _destroy_stack)