github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/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 expectedPolicyBody := "{\"Statement\":[{\"Action\":\"Update:*\",\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"LogicalResourceId/StaticVPC\"},{\"Action\":\"Update:*\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"*\"}]}" 55 resource.Test(t, resource.TestCase{ 56 PreCheck: func() { testAccPreCheck(t) }, 57 Providers: testAccProviders, 58 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 59 Steps: []resource.TestStep{ 60 resource.TestStep{ 61 Config: testAccAWSCloudFormationConfig_allAttributesWithBodies, 62 Check: resource.ComposeTestCheckFunc( 63 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.full", &stack), 64 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "name", "tf-full-stack"), 65 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "capabilities.#", "1"), 66 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "capabilities.1328347040", "CAPABILITY_IAM"), 67 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "disable_rollback", "false"), 68 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "notification_arns.#", "1"), 69 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "parameters.%", "1"), 70 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "parameters.VpcCIDR", "10.0.0.0/16"), 71 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "policy_body", expectedPolicyBody), 72 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.%", "2"), 73 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.First", "Mickey"), 74 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.Second", "Mouse"), 75 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "timeout_in_minutes", "10"), 76 ), 77 }, 78 resource.TestStep{ 79 Config: testAccAWSCloudFormationConfig_allAttributesWithBodies_modified, 80 Check: resource.ComposeTestCheckFunc( 81 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.full", &stack), 82 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "name", "tf-full-stack"), 83 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "capabilities.#", "1"), 84 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "capabilities.1328347040", "CAPABILITY_IAM"), 85 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "disable_rollback", "false"), 86 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "notification_arns.#", "1"), 87 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "parameters.%", "1"), 88 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "parameters.VpcCIDR", "10.0.0.0/16"), 89 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "policy_body", expectedPolicyBody), 90 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.%", "2"), 91 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.First", "Mickey"), 92 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "tags.Second", "Mouse"), 93 resource.TestCheckResourceAttr("aws_cloudformation_stack.full", "timeout_in_minutes", "10"), 94 ), 95 }, 96 }, 97 }) 98 } 99 100 // Regression for https://github.com/hashicorp/terraform/issues/4332 101 func TestAccAWSCloudFormation_withParams(t *testing.T) { 102 var stack cloudformation.Stack 103 104 resource.Test(t, resource.TestCase{ 105 PreCheck: func() { testAccPreCheck(t) }, 106 Providers: testAccProviders, 107 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 108 Steps: []resource.TestStep{ 109 resource.TestStep{ 110 Config: testAccAWSCloudFormationConfig_withParams, 111 Check: resource.ComposeTestCheckFunc( 112 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack), 113 ), 114 }, 115 resource.TestStep{ 116 Config: testAccAWSCloudFormationConfig_withParams_modified, 117 Check: resource.ComposeTestCheckFunc( 118 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with_params", &stack), 119 ), 120 }, 121 }, 122 }) 123 } 124 125 // Regression for https://github.com/hashicorp/terraform/issues/4534 126 func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) { 127 var stack cloudformation.Stack 128 129 resource.Test(t, resource.TestCase{ 130 PreCheck: func() { testAccPreCheck(t) }, 131 Providers: testAccProviders, 132 CheckDestroy: testAccCheckAWSCloudFormationDestroy, 133 Steps: []resource.TestStep{ 134 resource.TestStep{ 135 Config: testAccAWSCloudFormationConfig_templateUrl_withParams, 136 Check: resource.ComposeTestCheckFunc( 137 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack), 138 ), 139 }, 140 resource.TestStep{ 141 Config: testAccAWSCloudFormationConfig_templateUrl_withParams_modified, 142 Check: resource.ComposeTestCheckFunc( 143 testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack), 144 ), 145 }, 146 }, 147 }) 148 } 149 150 func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc { 151 return func(s *terraform.State) error { 152 rs, ok := s.RootModule().Resources[n] 153 if !ok { 154 return fmt.Errorf("Not found: %s", n) 155 } 156 157 conn := testAccProvider.Meta().(*AWSClient).cfconn 158 params := &cloudformation.DescribeStacksInput{ 159 StackName: aws.String(rs.Primary.ID), 160 } 161 resp, err := conn.DescribeStacks(params) 162 if err != nil { 163 return err 164 } 165 if len(resp.Stacks) == 0 { 166 return fmt.Errorf("CloudFormation stack not found") 167 } 168 169 return nil 170 } 171 } 172 173 func testAccCheckAWSCloudFormationDestroy(s *terraform.State) error { 174 conn := testAccProvider.Meta().(*AWSClient).cfconn 175 176 for _, rs := range s.RootModule().Resources { 177 if rs.Type != "aws_cloudformation_stack" { 178 continue 179 } 180 181 params := cloudformation.DescribeStacksInput{ 182 StackName: aws.String(rs.Primary.ID), 183 } 184 185 resp, err := conn.DescribeStacks(¶ms) 186 187 if err != nil { 188 return err 189 } 190 191 for _, s := range resp.Stacks { 192 if *s.StackId == rs.Primary.ID && *s.StackStatus != "DELETE_COMPLETE" { 193 return fmt.Errorf("CloudFormation stack still exists: %q", rs.Primary.ID) 194 } 195 } 196 } 197 198 return nil 199 } 200 201 var testAccAWSCloudFormationConfig = ` 202 resource "aws_cloudformation_stack" "network" { 203 name = "tf-networking-stack" 204 template_body = <<STACK 205 { 206 "Resources" : { 207 "MyVPC": { 208 "Type" : "AWS::EC2::VPC", 209 "Properties" : { 210 "CidrBlock" : "10.0.0.0/16", 211 "Tags" : [ 212 {"Key": "Name", "Value": "Primary_CF_VPC"} 213 ] 214 } 215 } 216 }, 217 "Outputs" : { 218 "DefaultSgId" : { 219 "Description": "The ID of default security group", 220 "Value" : { "Fn::GetAtt" : [ "MyVPC", "DefaultSecurityGroup" ]} 221 }, 222 "VpcID" : { 223 "Description": "The VPC ID", 224 "Value" : { "Ref" : "MyVPC" } 225 } 226 } 227 } 228 STACK 229 }` 230 231 var testAccAWSCloudFormationConfig_defaultParams = ` 232 resource "aws_cloudformation_stack" "asg-demo" { 233 name = "tf-asg-demo-stack" 234 template_body = <<BODY 235 { 236 "Parameters": { 237 "TopicName": { 238 "Type": "String" 239 }, 240 "VPCCIDR": { 241 "Type": "String", 242 "Default": "10.10.0.0/16" 243 } 244 }, 245 "Resources": { 246 "NotificationTopic": { 247 "Type": "AWS::SNS::Topic", 248 "Properties": { 249 "TopicName": { 250 "Ref": "TopicName" 251 } 252 } 253 }, 254 "MyVPC": { 255 "Type": "AWS::EC2::VPC", 256 "Properties": { 257 "CidrBlock": { 258 "Ref": "VPCCIDR" 259 }, 260 "Tags": [ 261 { 262 "Key": "Name", 263 "Value": "Primary_CF_VPC" 264 } 265 ] 266 } 267 } 268 }, 269 "Outputs": { 270 "VPCCIDR": { 271 "Value": { 272 "Ref": "VPCCIDR" 273 } 274 } 275 } 276 } 277 BODY 278 279 parameters { 280 TopicName = "ExampleTopic" 281 } 282 } 283 ` 284 285 var testAccAWSCloudFormationConfig_allAttributesWithBodies_tpl = ` 286 resource "aws_cloudformation_stack" "full" { 287 name = "tf-full-stack" 288 template_body = <<STACK 289 { 290 "Parameters" : { 291 "VpcCIDR" : { 292 "Description" : "CIDR to be used for the VPC", 293 "Type" : "String" 294 } 295 }, 296 "Resources" : { 297 "MyVPC": { 298 "Type" : "AWS::EC2::VPC", 299 "Properties" : { 300 "CidrBlock" : {"Ref": "VpcCIDR"}, 301 "Tags" : [ 302 {"Key": "Name", "Value": "%s"} 303 ] 304 } 305 }, 306 "StaticVPC": { 307 "Type" : "AWS::EC2::VPC", 308 "Properties" : { 309 "CidrBlock" : {"Ref": "VpcCIDR"}, 310 "Tags" : [ 311 {"Key": "Name", "Value": "Static_CF_VPC"} 312 ] 313 } 314 }, 315 "InstanceRole" : { 316 "Type" : "AWS::IAM::Role", 317 "Properties" : { 318 "AssumeRolePolicyDocument": { 319 "Version": "2012-10-17", 320 "Statement": [ { 321 "Effect": "Allow", 322 "Principal": { "Service": "ec2.amazonaws.com" }, 323 "Action": "sts:AssumeRole" 324 } ] 325 }, 326 "Path" : "/", 327 "Policies" : [ { 328 "PolicyName": "terraformtest", 329 "PolicyDocument": { 330 "Version": "2012-10-17", 331 "Statement": [ { 332 "Effect": "Allow", 333 "Action": [ "ec2:DescribeSnapshots" ], 334 "Resource": [ "*" ] 335 } ] 336 } 337 } ] 338 } 339 } 340 } 341 } 342 STACK 343 parameters { 344 VpcCIDR = "10.0.0.0/16" 345 } 346 347 policy_body = <<POLICY 348 %s 349 POLICY 350 capabilities = ["CAPABILITY_IAM"] 351 notification_arns = ["${aws_sns_topic.cf-updates.arn}"] 352 on_failure = "DELETE" 353 timeout_in_minutes = 10 354 tags { 355 First = "Mickey" 356 Second = "Mouse" 357 } 358 } 359 360 resource "aws_sns_topic" "cf-updates" { 361 name = "tf-cf-notifications" 362 } 363 ` 364 365 var policyBody = ` 366 { 367 "Statement" : [ 368 { 369 "Effect" : "Deny", 370 "Action" : "Update:*", 371 "Principal": "*", 372 "Resource" : "LogicalResourceId/StaticVPC" 373 }, 374 { 375 "Effect" : "Allow", 376 "Action" : "Update:*", 377 "Principal": "*", 378 "Resource" : "*" 379 } 380 ] 381 } 382 ` 383 384 var testAccAWSCloudFormationConfig_allAttributesWithBodies = fmt.Sprintf( 385 testAccAWSCloudFormationConfig_allAttributesWithBodies_tpl, 386 "Primary_CF_VPC", 387 policyBody) 388 var testAccAWSCloudFormationConfig_allAttributesWithBodies_modified = fmt.Sprintf( 389 testAccAWSCloudFormationConfig_allAttributesWithBodies_tpl, 390 "Primary_CloudFormation_VPC", 391 policyBody) 392 393 var tpl_testAccAWSCloudFormationConfig_withParams = ` 394 resource "aws_cloudformation_stack" "with_params" { 395 name = "tf-stack-with-params" 396 parameters { 397 VpcCIDR = "%s" 398 } 399 template_body = <<STACK 400 { 401 "Parameters" : { 402 "VpcCIDR" : { 403 "Description" : "CIDR to be used for the VPC", 404 "Type" : "String" 405 } 406 }, 407 "Resources" : { 408 "MyVPC": { 409 "Type" : "AWS::EC2::VPC", 410 "Properties" : { 411 "CidrBlock" : {"Ref": "VpcCIDR"}, 412 "Tags" : [ 413 {"Key": "Name", "Value": "Primary_CF_VPC"} 414 ] 415 } 416 } 417 } 418 } 419 STACK 420 421 on_failure = "DELETE" 422 timeout_in_minutes = 1 423 } 424 ` 425 426 var testAccAWSCloudFormationConfig_withParams = fmt.Sprintf( 427 tpl_testAccAWSCloudFormationConfig_withParams, 428 "10.0.0.0/16") 429 var testAccAWSCloudFormationConfig_withParams_modified = fmt.Sprintf( 430 tpl_testAccAWSCloudFormationConfig_withParams, 431 "12.0.0.0/16") 432 433 var tpl_testAccAWSCloudFormationConfig_templateUrl_withParams = ` 434 resource "aws_s3_bucket" "b" { 435 bucket = "%s" 436 acl = "public-read" 437 policy = <<POLICY 438 { 439 "Version":"2008-10-17", 440 "Statement": [ 441 { 442 "Sid":"AllowPublicRead", 443 "Effect":"Allow", 444 "Principal": { 445 "AWS": "*" 446 }, 447 "Action": "s3:GetObject", 448 "Resource": "arn:aws:s3:::%s/*" 449 } 450 ] 451 } 452 POLICY 453 454 website { 455 index_document = "index.html" 456 error_document = "error.html" 457 } 458 } 459 460 resource "aws_s3_bucket_object" "object" { 461 bucket = "${aws_s3_bucket.b.id}" 462 key = "tf-cf-stack.json" 463 source = "test-fixtures/cloudformation-template.json" 464 } 465 466 resource "aws_cloudformation_stack" "with-url-and-params" { 467 name = "tf-stack-template-url-with-params" 468 parameters { 469 VpcCIDR = "%s" 470 } 471 template_url = "https://${aws_s3_bucket.b.id}.s3-us-west-2.amazonaws.com/${aws_s3_bucket_object.object.key}" 472 on_failure = "DELETE" 473 timeout_in_minutes = 1 474 } 475 ` 476 477 var cfRandInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int() 478 var cfBucketName = "tf-stack-with-url-and-params-" + fmt.Sprintf("%d", cfRandInt) 479 480 var testAccAWSCloudFormationConfig_templateUrl_withParams = fmt.Sprintf( 481 tpl_testAccAWSCloudFormationConfig_templateUrl_withParams, 482 cfBucketName, cfBucketName, "11.0.0.0/16") 483 var testAccAWSCloudFormationConfig_templateUrl_withParams_modified = fmt.Sprintf( 484 tpl_testAccAWSCloudFormationConfig_templateUrl_withParams, 485 cfBucketName, cfBucketName, "13.0.0.0/16")