moto/tests/test_cloudformation/test_cloudformation_nested_stacks.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

181 lines
6.1 KiB
Python
Raw Normal View History

import json
from uuid import uuid4
import boto3
2024-01-07 12:03:33 +00:00
from moto import mock_aws
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_basic_stack():
# Create inner template
cf = boto3.client("cloudformation", "us-east-1")
bucket_created_by_cf = str(uuid4())
template = get_inner_template(bucket_created_by_cf)
# Upload inner template to S3
s3 = boto3.client("s3", "us-east-1")
cf_storage_bucket = str(uuid4())
s3.create_bucket(Bucket=cf_storage_bucket)
s3.put_object(Bucket=cf_storage_bucket, Key="stack.json", Body=json.dumps(template))
# Create template that includes the inner template
stack_name = "a" + str(uuid4())[0:6]
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"NestedStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": f"https://s3.amazonaws.com/{cf_storage_bucket}/stack.json",
},
},
},
}
cf.create_stack(StackName=stack_name, TemplateBody=str(template))
# Verify the inner S3 bucket has been created
bucket_names = sorted([b["Name"] for b in s3.list_buckets()["Buckets"]])
assert bucket_names == sorted([cf_storage_bucket, bucket_created_by_cf])
# Verify both stacks are created
stacks = cf.list_stacks()["StackSummaries"]
assert len(stacks) == 2
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_stack_with_params():
# Create inner template
cf = boto3.client("cloudformation", "us-east-1")
bucket_created_by_cf = str(uuid4())
inner_template = json.dumps(get_inner_template_with_params())
# Upload inner template to S3
s3 = boto3.client("s3", "us-east-1")
cf_storage_bucket = str(uuid4())
s3.create_bucket(Bucket=cf_storage_bucket)
s3.put_object(Bucket=cf_storage_bucket, Key="stack.json", Body=inner_template)
# Create template that includes the inner template
stack_name = "a" + str(uuid4())[0:6]
template = get_outer_template_with_params(cf_storage_bucket, bucket_created_by_cf)
cf.create_stack(StackName=stack_name, TemplateBody=str(template))
# Verify the inner S3 bucket has been created
bucket_names = sorted([b["Name"] for b in s3.list_buckets()["Buckets"]])
assert bucket_names == sorted([cf_storage_bucket, bucket_created_by_cf])
2024-01-07 12:03:33 +00:00
@mock_aws
def test_update_stack_with_params():
# Create inner template
cf = boto3.client("cloudformation", "us-east-1")
first_bucket = str(uuid4())
second_bucket = str(uuid4())
inner_template = json.dumps(get_inner_template_with_params())
# Upload inner template to S3
s3 = boto3.client("s3", "us-east-1")
cf_storage_bucket = str(uuid4())
s3.create_bucket(Bucket=cf_storage_bucket)
s3.put_object(Bucket=cf_storage_bucket, Key="stack.json", Body=inner_template)
# Create template that includes the inner template
stack_name = "a" + str(uuid4())[0:6]
template = get_outer_template_with_params(cf_storage_bucket, first_bucket)
cf.create_stack(StackName=stack_name, TemplateBody=str(template))
# Verify the inner S3 bucket has been created
bucket_names = sorted([b["Name"] for b in s3.list_buckets()["Buckets"]])
assert bucket_names == sorted([cf_storage_bucket, first_bucket])
# Update stack
template = get_outer_template_with_params(cf_storage_bucket, second_bucket)
cf.update_stack(StackName=stack_name, TemplateBody=str(template))
# Verify the inner S3 bucket has been created
bucket_names = sorted([b["Name"] for b in s3.list_buckets()["Buckets"]])
assert bucket_names == sorted([cf_storage_bucket, second_bucket])
2024-01-07 12:03:33 +00:00
@mock_aws
def test_delete_basic_stack():
# Create inner template
cf = boto3.client("cloudformation", "us-east-1")
bucket_created_by_cf = str(uuid4())
template = get_inner_template(bucket_created_by_cf)
# Upload inner template to S3
s3 = boto3.client("s3", "us-east-1")
cf_storage_bucket = str(uuid4())
s3.create_bucket(Bucket=cf_storage_bucket)
s3.put_object(Bucket=cf_storage_bucket, Key="stack.json", Body=json.dumps(template))
# Create template that includes the inner template
stack_name = "a" + str(uuid4())[0:6]
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"NestedStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": f"https://s3.amazonaws.com/{cf_storage_bucket}/stack.json",
},
},
},
}
cf.create_stack(StackName=stack_name, TemplateBody=str(template))
cf.delete_stack(StackName=stack_name)
# Verify the stack-controlled S3 bucket has been deleted
bucket_names = sorted([b["Name"] for b in s3.list_buckets()["Buckets"]])
assert bucket_names == [cf_storage_bucket]
# Verify both stacks are deleted
stacks = cf.list_stacks()["StackSummaries"]
assert len(stacks) == 2
for stack in stacks:
assert stack["StackStatus"] == "DELETE_COMPLETE"
def get_inner_template(bucket_created_by_cf):
return {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"bcbcf": {
"Type": "AWS::S3::Bucket",
"Properties": {"BucketName": bucket_created_by_cf},
}
},
"Outputs": {"Bucket": {"Value": {"Ref": "bcbcf"}}},
}
def get_inner_template_with_params():
return {
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"BName": {"Description": "bucket name", "Type": "String"},
},
"Resources": {
"bcbcf": {
"Type": "AWS::S3::Bucket",
"Properties": {"BucketName": {"Ref": "BName"}},
}
},
}
def get_outer_template_with_params(cf_storage_bucket, first_bucket):
return {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"NestedStack": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": f"https://s3.amazonaws.com/{cf_storage_bucket}/stack.json",
"Parameters": {"BName": first_bucket},
},
},
},
}