github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/aws/resource_aws_cloudformation_stack_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "math/rand" 6 "testing" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/service/cloudformation" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestAccAWSCloudFormation_basic(t *testing.T) { 16 var stack cloudformation.Stack 17 18 resource.Test(t, resource.TestCase{ 19 PreCheck: func() { testAccPreCheck(t) }, 20 Providers: testAccProviders, 21 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 22 Steps: []resource.TestStep{ 23 resource.TestStep{ 24 Config: testAccAWSCloudFormationConfig, 25 Check: resource.ComposeTestCheckFunc( 26 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.network", &stack), 27 ), 28 }, 29 }, 30 }) 31 } 32 33 func TestAccAWSCloudFormation_defaultParams(t *testing.T) { 34 var stack cloudformation.Stack 35 36 resource.Test(t, resource.TestCase{ 37 PreCheck: func() { testAccPreCheck(t) }, 38 Providers: testAccProviders, 39 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 40 Steps: []resource.TestStep{ 41 resource.TestStep{ 42 Config: testAccAWSCloudFormationConfig_defaultParams, 43 Check: resource.ComposeTestCheckFunc( 44 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.asg-demo", &stack), 45 ), 46 }, 47 }, 48 }) 49 } 50 51 func TestAccAWSCloudFormation_allAttributes(t *testing.T) { 52 var stack cloudformation.Stack 53 54 resource.Test(t, resource.TestCase{ 55 PreCheck: func() { testAccPreCheck(t) }, 56 Providers: testAccProviders, 57 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 58 Steps: []resource.TestStep{ 59 resource.TestStep{ 60 Config: testAccAWSCloudFormationConfig_allAttributes, 61 Check: resource.ComposeTestCheckFunc( 62 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.full", &stack), 63 ), 64 }, 65 }, 66 }) 67 } 68 69 // Regression for https://github.com/hashicorp/terraform/issues/4332 70 func TestAccAWSCloudFormation_withParams(t *testing.T) { 71 var stack cloudformation.Stack 72 73 resource.Test(t, resource.TestCase{ 74 PreCheck: func() { testAccPreCheck(t) }, 75 Providers: testAccProviders, 76 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 77 Steps: []resource.TestStep{ 78 resource.TestStep{ 79 Config: testAccAWSCloudFormationConfig_withParams, 80 Check: resource.ComposeTestCheckFunc( 81 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack), 82 ), 83 }, 84 resource.TestStep{ 85 Config: testAccAWSCloudFormationConfig_withParams_modified, 86 Check: resource.ComposeTestCheckFunc( 87 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack), 88 ), 89 }, 90 }, 91 }) 92 } 93 94 // Regression for https://github.com/hashicorp/terraform/issues/4534 95 func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) { 96 var stack cloudformation.Stack 97 98 resource.Test(t, resource.TestCase{ 99 PreCheck: func() { testAccPreCheck(t) }, 100 Providers: testAccProviders, 101 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 102 Steps: []resource.TestStep{ 103 resource.TestStep{ 104 Config: testAccAWSCloudFormationConfig_templateUrl_withParams, 105 Check: resource.ComposeTestCheckFunc( 106 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack), 107 ), 108 }, 109 resource.TestStep{ 110 Config: testAccAWSCloudFormationConfig_templateUrl_withParams_modified, 111 Check: resource.ComposeTestCheckFunc( 112 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack), 113 ), 114 }, 115 }, 116 }) 117 } 118 119 func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc { 120 return func(s *terraform.State) error { 121 rs, ok := s.RootModule().Resources[n] 122 if !ok { 123 return fmt.Errorf("Not found: %s", n) 124 } 125 126 conn := testAccProvider.Meta().(*AWSClient).cfconn 127 params := &cloudformation.DescribeStacksInput{ 128 StackName: aws.String(rs.Primary.ID), 129 } 130 resp, err := conn.DescribeStacks(params) 131 if err != nil { 132 return err 133 } 134 if len(resp.Stacks) == 0 { 135 return fmt.Errorf("CloudFormation stack not found") 136 } 137 138 return nil 139 } 140 } 141 142 func testAccCheckAWSCloudFormationDestroy(s *terraform.State) error { 143 conn := testAccProvider.Meta().(*AWSClient).cfconn 144 145 for _, rs := range s.RootModule().Resources { 146 if rs.Type != "aws_cloudformation_stack" { 147 continue 148 } 149 150 params := cloudformation.DescribeStacksInput{ 151 StackName: aws.String(rs.Primary.ID), 152 } 153 154 resp, err := conn.DescribeStacks(¶ms) 155 156 if err != nil { 157 return err 158 } 159 160 for _, s := range resp.Stacks { 161 if *s.StackId == rs.Primary.ID && *s.StackStatus != "DELETE_COMPLETE" { 162 return fmt.Errorf("CloudFormation stack still exists: %q", rs.Primary.ID) 163 } 164 } 165 } 166 167 return nil 168 } 169 170 var testAccAWSCloudFormationConfig = ` 171 resource "aws_cloudformation_stack" "network" { 172 name = "tf-networking-stack" 173 template_body = <<STACK 174 { 175 "Resources" : { 176 "MyVPC": { 177 "Type" : "AWS::EC2::VPC", 178 "Properties" : { 179 "CidrBlock" : "10.0.0.0/16", 180 "Tags" : [ 181 {"Key": "Name", "Value": "Primary_CF_VPC"} 182 ] 183 } 184 } 185 }, 186 "Outputs" : { 187 "DefaultSgId" : { 188 "Description": "The ID of default security group", 189 "Value" : { "Fn::GetAtt" : [ "MyVPC", "DefaultSecurityGroup" ]} 190 }, 191 "VpcID" : { 192 "Description": "The VPC ID", 193 "Value" : { "Ref" : "MyVPC" } 194 } 195 } 196 } 197 STACK 198 }` 199 200 var testAccAWSCloudFormationConfig_defaultParams = ` 201 resource "aws_cloudformation_stack" "asg-demo" { 202 name = "tf-asg-demo-stack" 203 template_body = <<BODY 204 { 205 "Parameters": { 206 "TopicName": { 207 "Type": "String" 208 }, 209 "VPCCIDR": { 210 "Type": "String", 211 "Default": "10.10.0.0/16" 212 } 213 }, 214 "Resources": { 215 "NotificationTopic": { 216 "Type": "AWS::SNS::Topic", 217 "Properties": { 218 "TopicName": { 219 "Ref": "TopicName" 220 } 221 } 222 }, 223 "MyVPC": { 224 "Type": "AWS::EC2::VPC", 225 "Properties": { 226 "CidrBlock": { 227 "Ref": "VPCCIDR" 228 }, 229 "Tags": [ 230 { 231 "Key": "Name", 232 "Value": "Primary_CF_VPC" 233 } 234 ] 235 } 236 } 237 }, 238 "Outputs": { 239 "VPCCIDR": { 240 "Value": { 241 "Ref": "VPCCIDR" 242 } 243 } 244 } 245 } 246 BODY 247 248 parameters { 249 TopicName = "ExampleTopic" 250 } 251 } 252 ` 253 254 var testAccAWSCloudFormationConfig_allAttributes = ` 255 resource "aws_cloudformation_stack" "full" { 256 name = "tf-full-stack" 257 template_body = <<STACK 258 { 259 "Resources" : { 260 "MyVPC": { 261 "Type" : "AWS::EC2::VPC", 262 "Properties" : { 263 "CidrBlock" : "10.0.0.0/16", 264 "Tags" : [ 265 {"Key": "Name", "Value": "Primary_CF_VPC"} 266 ] 267 } 268 } 269 } 270 } 271 STACK 272 273 capabilities = ["CAPABILITY_IAM"] 274 notification_arns = ["${aws_sns_topic.cf-updates.arn}"] 275 on_failure = "DELETE" 276 timeout_in_minutes = 1 277 } 278 279 resource "aws_sns_topic" "cf-updates" { 280 name = "tf-cf-notifications" 281 } 282 ` 283 284 var tpl_testAccAWSCloudFormationConfig_withParams = ` 285 resource "aws_cloudformation_stack" "with_params" { 286 name = "tf-stack-with-params" 287 parameters { 288 VpcCIDR = "%s" 289 } 290 template_body = <<STACK 291 { 292 "Parameters" : { 293 "VpcCIDR" : { 294 "Description" : "CIDR to be used for the VPC", 295 "Type" : "String" 296 } 297 }, 298 "Resources" : { 299 "MyVPC": { 300 "Type" : "AWS::EC2::VPC", 301 "Properties" : { 302 "CidrBlock" : {"Ref": "VpcCIDR"}, 303 "Tags" : [ 304 {"Key": "Name", "Value": "Primary_CF_VPC"} 305 ] 306 } 307 } 308 } 309 } 310 STACK 311 312 on_failure = "DELETE" 313 timeout_in_minutes = 1 314 } 315 ` 316 317 var testAccAWSCloudFormationConfig_withParams = fmt.Sprintf( 318 tpl_testAccAWSCloudFormationConfig_withParams, 319 "10.0.0.0/16") 320 var testAccAWSCloudFormationConfig_withParams_modified = fmt.Sprintf( 321 tpl_testAccAWSCloudFormationConfig_withParams, 322 "12.0.0.0/16") 323 324 var tpl_testAccAWSCloudFormationConfig_templateUrl_withParams = ` 325 resource "aws_s3_bucket" "b" { 326 bucket = "%s" 327 acl = "public-read" 328 policy = <<POLICY 329 { 330 "Version":"2008-10-17", 331 "Statement": [ 332 { 333 "Sid":"AllowPublicRead", 334 "Effect":"Allow", 335 "Principal": { 336 "AWS": "*" 337 }, 338 "Action": "s3:GetObject", 339 "Resource": "arn:aws:s3:::%s/*" 340 } 341 ] 342 } 343 POLICY 344 345 website { 346 index_document = "index.html" 347 error_document = "error.html" 348 } 349 } 350 351 resource "aws_s3_bucket_object" "object" { 352 bucket = "${aws_s3_bucket.b.id}" 353 key = "tf-cf-stack.json" 354 source = "test-fixtures/cloudformation-template.json" 355 } 356 357 resource "aws_cloudformation_stack" "with-url-and-params" { 358 name = "tf-stack-template-url-with-params" 359 parameters { 360 VpcCIDR = "%s" 361 } 362 template_url = "https://${aws_s3_bucket.b.id}.s3-us-west-2.amazonaws.com/${aws_s3_bucket_object.object.key}" 363 on_failure = "DELETE" 364 timeout_in_minutes = 1 365 } 366 ` 367 368 var cfRandInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int() 369 var cfBucketName = "tf-stack-with-url-and-params-" + fmt.Sprintf("%d", cfRandInt) 370 371 var testAccAWSCloudFormationConfig_templateUrl_withParams = fmt.Sprintf( 372 tpl_testAccAWSCloudFormationConfig_templateUrl_withParams, 373 cfBucketName, cfBucketName, "11.0.0.0/16") 374 var testAccAWSCloudFormationConfig_templateUrl_withParams_modified = fmt.Sprintf( 375 tpl_testAccAWSCloudFormationConfig_templateUrl_withParams, 376 cfBucketName, cfBucketName, "13.0.0.0/16")