cloudformatious 0.5.0

Extension traits for rusoto_cloudformation
Documentation
use assert_matches::assert_matches;
use cloudformatious::{
    ApplyStackError, ApplyStackInput, Client, DeleteStackError, DeleteStackInput, Parameter,
    StackFailure, StackStatus, TemplateSource,
};

use crate::common::{get_role_arn, TestingRole, EMPTY_TEMPLATE};

use super::{generated_name, NON_EMPTY_TEMPLATE};

const FAILING_TEMPLATE: &str = r#"{
    "Resources": {
        "Bucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {}
        }
    }

}"#;

pub const ROLLBACK_FAILING_TEMPLATE: &str = r#"{
    "Parameters": {
        "CidrBlock": {
            "Type": "String"
        }
    },
    "Resources": {
        "Subnet": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "CidrBlock": {"Ref": "CidrBlock"},
                "Tags": [
                    {
                        "Key": "Foo",
                        "Value": "Bar"
                    }
                ],
                "VpcId": {"Fn::ImportValue": "cloudformatious-testing-VpcId"}
            }
        },
        "Bucket": {
            "Type": "AWS::S3::Bucket",
            "DependsOn": ["Subnet"],
            "Properties": {}
        }
    }
}"#;

pub async fn create_failed(client: &Client) -> StackFailure {
    let error = client
        .apply_stack(
            ApplyStackInput::new(generated_name(), TemplateSource::inline(FAILING_TEMPLATE))
                .set_disable_rollback(true),
        )
        .await
        .unwrap_err();
    let failure = assert_matches!(error, ApplyStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::CreateFailed);
    failure
}

pub async fn rollback_complete(client: &Client) -> StackFailure {
    let error = client
        .apply_stack(ApplyStackInput::new(
            generated_name(),
            TemplateSource::inline(FAILING_TEMPLATE),
        ))
        .await
        .unwrap_err();
    let failure = assert_matches!(error, ApplyStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::RollbackComplete);
    failure
}

pub async fn rollback_failed(client: &Client) -> StackFailure {
    let error = client
        .apply_stack(
            ApplyStackInput::new(
                generated_name(),
                TemplateSource::inline(ROLLBACK_FAILING_TEMPLATE),
            )
            .set_parameters([Parameter {
                key: "CidrBlock".to_string(),
                value: "10.0.0.32/28".to_string(),
            }])
            .set_role_arn(get_role_arn(TestingRole::DenyDeleteSubnet).await),
        )
        .await
        .unwrap_err();
    let failure = assert_matches!(error, ApplyStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::RollbackFailed);
    failure
}

pub async fn delete_failed(client: &Client) -> StackFailure {
    let output = client
        .apply_stack(
            ApplyStackInput::new(generated_name(), TemplateSource::inline(NON_EMPTY_TEMPLATE))
                .set_parameters([Parameter {
                    key: "CidrBlock".to_string(),
                    value: "10.0.0.48/28".to_string(),
                }]),
        )
        .await
        .unwrap();

    let error = client
        .delete_stack(
            DeleteStackInput::new(&output.stack_id)
                .set_role_arn(get_role_arn(TestingRole::DenyDeleteSubnet).await),
        )
        .await
        .unwrap_err();
    let failure = assert_matches!(error, DeleteStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::DeleteFailed);
    failure
}

pub async fn update_failed(client: &Client) -> StackFailure {
    let output = client
        .apply_stack(ApplyStackInput::new(
            generated_name(),
            TemplateSource::inline(EMPTY_TEMPLATE),
        ))
        .await
        .unwrap();

    let error = client
        .apply_stack(
            ApplyStackInput::new(output.stack_id, TemplateSource::inline(FAILING_TEMPLATE))
                .set_disable_rollback(true),
        )
        .await
        .unwrap_err();

    let failure = assert_matches!(error, ApplyStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::UpdateFailed);
    failure
}

pub async fn update_rollback_failed(client: &Client) -> StackFailure {
    let output = client
        .apply_stack(
            ApplyStackInput::new(generated_name(), TemplateSource::inline(NON_EMPTY_TEMPLATE))
                .set_parameters([Parameter {
                    key: "CidrBlock".to_string(),
                    value: "10.0.0.80/28".to_string(),
                }]),
        )
        .await
        .unwrap();

    let error = client
        .apply_stack(
            ApplyStackInput::new(
                output.stack_id,
                TemplateSource::inline(ROLLBACK_FAILING_TEMPLATE),
            )
            .set_parameters([Parameter {
                key: "CidrBlock".to_string(),
                value: "10.0.0.80/28".to_string(),
            }]),
        )
        .await
        .unwrap_err();

    let failure = assert_matches!(error, ApplyStackError::Failure(failure) => failure);
    assert_eq!(failure.stack_status, StackStatus::UpdateRollbackFailed);
    failure
}