diff --git a/README.md b/README.md index d373e0b..6051c5a 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,12 @@ module "cloudformation_stack" { namespace = "eg" stage = "prod" name = "app" + + # Option 1: Use template_url (for templates stored in S3) template_url = "https://aws-quickstart.s3.amazonaws.com/quickstart-compliance-cis-benchmark/templates/main.template" + + # Option 2: Use template_body (for inline templates or local files) + # template_body = file("${path.module}/template.yaml") parameters = { NotificationEmailAddressForCloudWatchAlarms = "notify-me@example.com" @@ -124,6 +129,7 @@ module "cloudformation_stack" { | [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | | [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | | [capabilities](#input\_capabilities) | A list of capabilities. Valid values: CAPABILITY\_IAM, CAPABILITY\_NAMED\_IAM, CAPABILITY\_AUTO\_EXPAND | `list(string)` | `[]` | no | +| [disable\_rollback](#input\_disable\_rollback) | Set to true to disable rollback of the stack if stack creation failed. You can specify either on\_failure or disable\_rollback, but not both. | `bool` | `false` | no | | [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
| no | | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | @@ -142,7 +148,8 @@ module "cloudformation_stack" { | [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | -| [template\_url](#input\_template\_url) | Amazon S3 bucket URL location of a file containing the CloudFormation template body. Maximum file size: 460,800 bytes | `string` | n/a | yes | +| [template\_body](#input\_template\_body) | Structure containing the CloudFormation template body. Maximum size: 51,200 bytes | `string` | `null` | no | +| [template\_url](#input\_template\_url) | Amazon S3 bucket URL location of a file containing the CloudFormation template body. Maximum file size: 460,800 bytes | `string` | `null` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | | [timeout\_in\_minutes](#input\_timeout\_in\_minutes) | The amount of time that can pass before the stack status becomes `CREATE_FAILED` | `number` | `30` | no | diff --git a/examples/complete/example.template b/examples/complete/example.template new file mode 100644 index 0000000..9bb166b --- /dev/null +++ b/examples/complete/example.template @@ -0,0 +1,29 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: 'Basic test template for CloudFormation stack module' + +Parameters: + StackSuffix: + Type: String + Description: 'Unique suffix for the stack and bucket names' + Default: 'test' + +Resources: + TestBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Delete + Properties: + BucketName: !Sub '${StackSuffix}-${AWS::AccountId}' + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + VersioningConfiguration: + Status: Suspended + +Outputs: + BucketName: + Description: 'Name of the created S3 bucket' + Value: !Ref TestBucket + Export: + Name: !Sub '${AWS::StackName}-BucketName' diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index 9c4af48..e85383f 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -6,15 +6,6 @@ stage = "test" name = "cloudformation-stack" -template_url = "https://aws-quickstart.s3.amazonaws.com/quickstart-compliance-cis-benchmark/templates/main.template" +parameters = {} -parameters = { - NotificationEmailAddressForCloudWatchAlarms = "notify-me@example.com" - ConfigureCloudtrail = "Yes" - ConfigureConfig = "Yes" - ProfileLevel = "Level 2" - QSS3BucketName = "aws-quickstart" - QSS3KeyPrefix = "quickstart-compliance-cis-benchmark/" -} - -capabilities = ["CAPABILITY_IAM"] +capabilities = [] diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 7e53100..d401fc3 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -2,11 +2,21 @@ provider "aws" { region = var.region } +resource "random_string" "suffix" { + length = 8 + special = false + upper = false +} + module "cloudformation_stack" { - source = "../../" - template_url = var.template_url - parameters = var.parameters + source = "../../" + template_body = file("${path.module}/example.template") + parameters = merge(var.parameters, { + StackSuffix = "t${formatdate("MMDDhh", timestamp())}${random_string.suffix.result}" + }) capabilities = var.capabilities - context = module.this.context + context = merge(module.this.context, { + name = "${module.this.name}-${random_string.suffix.result}" + }) } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index b17f520..28061fb 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -3,11 +3,6 @@ variable "region" { description = "AWS Region" } -variable "template_url" { - type = string - description = "Amazon S3 bucket URL location of a file containing the CloudFormation template body. Maximum file size: 460,800 bytes" -} - variable "parameters" { type = map(string) description = "Key-value map of input parameters for the Stack Set template. (_e.g._ map(\"BusinessUnit\",\"ABC\")" @@ -18,22 +13,4 @@ variable "capabilities" { type = list(string) description = "A list of capabilities. Valid values: CAPABILITY_IAM, CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND" default = [] -} - -variable "on_failure" { - type = string - default = "ROLLBACK" - description = "Action to be taken if stack creation fails. This must be one of: `DO_NOTHING`, `ROLLBACK`, or `DELETE`" -} - -variable "timeout_in_minutes" { - type = number - default = 30 - description = "The amount of time that can pass before the stack status becomes `CREATE_FAILED`" -} - -variable "policy_body" { - type = string - default = "" - description = "Structure containing the stack policy body" -} +} \ No newline at end of file diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf index 5b2c49b..3b49b80 100644 --- a/examples/complete/versions.tf +++ b/examples/complete/versions.tf @@ -6,5 +6,9 @@ terraform { source = "hashicorp/aws" version = ">= 2.0" } + random = { + source = "hashicorp/random" + version = ">= 3.0" + } } } diff --git a/main.tf b/main.tf index 4c69e02..8936770 100644 --- a/main.tf +++ b/main.tf @@ -5,10 +5,15 @@ resource "aws_cloudformation_stack" "default" { tags = module.this.tags template_url = var.template_url - parameters = var.parameters - capabilities = var.capabilities + # template_url and template_body are mutually exclusive + template_body = var.template_url == null ? var.template_body : null + parameters = var.parameters + capabilities = var.capabilities - on_failure = var.on_failure + # When disable_rollback is true, on_failure should not be set (or set to null) + # When disable_rollback is false, use the value of var.on_failure + on_failure = var.disable_rollback ? null : var.on_failure + disable_rollback = var.disable_rollback timeout_in_minutes = var.timeout_in_minutes policy_body = var.policy_body diff --git a/output.tf b/output.tf index d357605..0a95f59 100644 --- a/output.tf +++ b/output.tf @@ -1,10 +1,10 @@ output "name" { - value = join("", aws_cloudformation_stack.default.*.name) + value = join("", aws_cloudformation_stack.default[*].name) description = "Name of the CloudFormation Stack" } output "id" { - value = join("", aws_cloudformation_stack.default.*.id) + value = join("", aws_cloudformation_stack.default[*].id) description = "ID of the CloudFormation Stack" } diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 8b1bed0..168bfca 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -1,9 +1,10 @@ package test import ( + "testing" + "github.com/gruntwork-io/terratest/modules/terraform" "github.com/stretchr/testify/assert" - "testing" ) func int32Ptr(i int32) *int32 { return &i } @@ -28,11 +29,11 @@ func TestExamplesComplete(t *testing.T) { // Run `terraform output` to get the value of an output variable name := terraform.Output(t, terraformOptions, "name") - // Verify we're getting back the outputs we expect - assert.Equal(t, "eg-test-cloudformation-stack", name) + // Verify we're getting back the outputs we expect (check prefix and any suffix) + assert.Contains(t, name, "eg-test-cloudformation-stack") // Run `terraform output` to get the value of an output variable id := terraform.Output(t, terraformOptions, "id") - // Verify we're getting back the outputs we expect + // Verify we're getting back the outputs we expect (check prefix and any suffix) assert.Contains(t, id, "stack/eg-test-cloudformation-stack") } diff --git a/variables.tf b/variables.tf index 8fe9897..da970cb 100644 --- a/variables.tf +++ b/variables.tf @@ -1,8 +1,15 @@ variable "template_url" { type = string + default = null description = "Amazon S3 bucket URL location of a file containing the CloudFormation template body. Maximum file size: 460,800 bytes" } +variable "template_body" { + type = string + default = null + description = "Structure containing the CloudFormation template body. Maximum size: 51,200 bytes" +} + variable "parameters" { type = map(string) description = "Key-value map of input parameters for the Stack Set template. (_e.g._ map(\"BusinessUnit\",\"ABC\")" @@ -33,3 +40,9 @@ variable "policy_body" { description = "Structure containing the stack policy body" } +variable "disable_rollback" { + type = bool + default = false + description = "Set to true to disable rollback of the stack if stack creation failed. You can specify either on_failure or disable_rollback, but not both." +} +