github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_ssm_document_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/awserr" 9 "github.com/aws/aws-sdk-go/service/ssm" 10 "github.com/hashicorp/terraform/helper/acctest" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestAccAWSSSMDocument_basic(t *testing.T) { 16 name := acctest.RandString(10) 17 resource.Test(t, resource.TestCase{ 18 PreCheck: func() { testAccPreCheck(t) }, 19 Providers: testAccProviders, 20 CheckDestroy: testAccCheckAWSSSMDocumentDestroy, 21 Steps: []resource.TestStep{ 22 resource.TestStep{ 23 Config: testAccAWSSSMDocumentBasicConfig(name), 24 Check: resource.ComposeTestCheckFunc( 25 testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"), 26 ), 27 }, 28 }, 29 }) 30 } 31 32 func TestAccAWSSSMDocument_permission(t *testing.T) { 33 name := acctest.RandString(10) 34 resource.Test(t, resource.TestCase{ 35 PreCheck: func() { testAccPreCheck(t) }, 36 Providers: testAccProviders, 37 CheckDestroy: testAccCheckAWSSSMDocumentDestroy, 38 Steps: []resource.TestStep{ 39 resource.TestStep{ 40 Config: testAccAWSSSMDocumentPermissionConfig(name), 41 Check: resource.ComposeTestCheckFunc( 42 testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"), 43 resource.TestCheckResourceAttr( 44 "aws_ssm_document.foo", "permissions.type", "Share"), 45 resource.TestCheckResourceAttr( 46 "aws_ssm_document.foo", "permissions.account_ids", "all"), 47 ), 48 }, 49 }, 50 }) 51 } 52 53 func TestAccAWSSSMDocument_params(t *testing.T) { 54 name := acctest.RandString(10) 55 resource.Test(t, resource.TestCase{ 56 PreCheck: func() { testAccPreCheck(t) }, 57 Providers: testAccProviders, 58 CheckDestroy: testAccCheckAWSSSMDocumentDestroy, 59 Steps: []resource.TestStep{ 60 resource.TestStep{ 61 Config: testAccAWSSSMDocumentParamConfig(name), 62 Check: resource.ComposeTestCheckFunc( 63 testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"), 64 resource.TestCheckResourceAttr( 65 "aws_ssm_document.foo", "parameter.0.name", "commands"), 66 resource.TestCheckResourceAttr( 67 "aws_ssm_document.foo", "parameter.0.type", "StringList"), 68 resource.TestCheckResourceAttr( 69 "aws_ssm_document.foo", "parameter.1.name", "workingDirectory"), 70 resource.TestCheckResourceAttr( 71 "aws_ssm_document.foo", "parameter.1.type", "String"), 72 resource.TestCheckResourceAttr( 73 "aws_ssm_document.foo", "parameter.2.name", "executionTimeout"), 74 resource.TestCheckResourceAttr( 75 "aws_ssm_document.foo", "parameter.2.type", "String"), 76 ), 77 }, 78 }, 79 }) 80 } 81 82 func TestAccAWSSSMDocument_automation(t *testing.T) { 83 name := acctest.RandString(10) 84 resource.Test(t, resource.TestCase{ 85 PreCheck: func() { testAccPreCheck(t) }, 86 Providers: testAccProviders, 87 CheckDestroy: testAccCheckAWSSSMDocumentDestroy, 88 Steps: []resource.TestStep{ 89 resource.TestStep{ 90 Config: testAccAWSSSMDocumentTypeAutomationConfig(name), 91 Check: resource.ComposeTestCheckFunc( 92 testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"), 93 resource.TestCheckResourceAttr( 94 "aws_ssm_document.foo", "document_type", "Automation"), 95 ), 96 }, 97 }, 98 }) 99 } 100 101 func testAccCheckAWSSSMDocumentExists(n string) resource.TestCheckFunc { 102 return func(s *terraform.State) error { 103 rs, ok := s.RootModule().Resources[n] 104 if !ok { 105 return fmt.Errorf("Not found: %s", n) 106 } 107 108 if rs.Primary.ID == "" { 109 return fmt.Errorf("No SSM Document ID is set") 110 } 111 112 conn := testAccProvider.Meta().(*AWSClient).ssmconn 113 114 _, err := conn.DescribeDocument(&ssm.DescribeDocumentInput{ 115 Name: aws.String(rs.Primary.ID), 116 }) 117 if err != nil { 118 return err 119 } 120 121 return nil 122 } 123 } 124 125 func testAccCheckAWSSSMDocumentDestroy(s *terraform.State) error { 126 conn := testAccProvider.Meta().(*AWSClient).ssmconn 127 128 for _, rs := range s.RootModule().Resources { 129 if rs.Type != "aws_ssm_document" { 130 continue 131 } 132 133 out, err := conn.DescribeDocument(&ssm.DescribeDocumentInput{ 134 Name: aws.String(rs.Primary.Attributes["name"]), 135 }) 136 137 if err != nil { 138 // InvalidDocument means it's gone, this is good 139 if wserr, ok := err.(awserr.Error); ok && wserr.Code() == "InvalidDocument" { 140 return nil 141 } 142 return err 143 } 144 145 if out != nil { 146 return fmt.Errorf("Expected AWS SSM Document to be gone, but was still found") 147 } 148 149 return nil 150 } 151 152 return fmt.Errorf("Default error in SSM Document Test") 153 } 154 155 /* 156 Based on examples from here: https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/create-ssm-doc.html 157 */ 158 159 func testAccAWSSSMDocumentBasicConfig(rName string) string { 160 return fmt.Sprintf(` 161 resource "aws_ssm_document" "foo" { 162 name = "test_document-%s" 163 document_type = "Command" 164 165 content = <<DOC 166 { 167 "schemaVersion": "1.2", 168 "description": "Check ip configuration of a Linux instance.", 169 "parameters": { 170 171 }, 172 "runtimeConfig": { 173 "aws:runShellScript": { 174 "properties": [ 175 { 176 "id": "0.aws:runShellScript", 177 "runCommand": ["ifconfig"] 178 } 179 ] 180 } 181 } 182 } 183 DOC 184 } 185 186 `, rName) 187 } 188 189 func testAccAWSSSMDocumentPermissionConfig(rName string) string { 190 return fmt.Sprintf(` 191 resource "aws_ssm_document" "foo" { 192 name = "test_document-%s" 193 document_type = "Command" 194 195 permissions = { 196 type = "Share" 197 account_ids = "all" 198 } 199 200 content = <<DOC 201 { 202 "schemaVersion": "1.2", 203 "description": "Check ip configuration of a Linux instance.", 204 "parameters": { 205 206 }, 207 "runtimeConfig": { 208 "aws:runShellScript": { 209 "properties": [ 210 { 211 "id": "0.aws:runShellScript", 212 "runCommand": ["ifconfig"] 213 } 214 ] 215 } 216 } 217 } 218 DOC 219 } 220 `, rName) 221 } 222 223 func testAccAWSSSMDocumentParamConfig(rName string) string { 224 return fmt.Sprintf(` 225 resource "aws_ssm_document" "foo" { 226 name = "test_document-%s" 227 document_type = "Command" 228 229 content = <<DOC 230 { 231 "schemaVersion":"1.2", 232 "description":"Run a PowerShell script or specify the paths to scripts to run.", 233 "parameters":{ 234 "commands":{ 235 "type":"StringList", 236 "description":"(Required) Specify the commands to run or the paths to existing scripts on the instance.", 237 "minItems":1, 238 "displayType":"textarea" 239 }, 240 "workingDirectory":{ 241 "type":"String", 242 "default":"", 243 "description":"(Optional) The path to the working directory on your instance.", 244 "maxChars":4096 245 }, 246 "executionTimeout":{ 247 "type":"String", 248 "default":"3600", 249 "description":"(Optional) The time in seconds for a command to be completed before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours).", 250 "allowedPattern":"([1-9][0-9]{0,3})|(1[0-9]{1,4})|(2[0-7][0-9]{1,3})|(28[0-7][0-9]{1,2})|(28800)" 251 } 252 }, 253 "runtimeConfig":{ 254 "aws:runPowerShellScript":{ 255 "properties":[ 256 { 257 "id":"0.aws:runPowerShellScript", 258 "runCommand":"{{ commands }}", 259 "workingDirectory":"{{ workingDirectory }}", 260 "timeoutSeconds":"{{ executionTimeout }}" 261 } 262 ] 263 } 264 } 265 } 266 DOC 267 } 268 269 `, rName) 270 } 271 272 func testAccAWSSSMDocumentTypeAutomationConfig(rName string) string { 273 return fmt.Sprintf(` 274 data "aws_ami" "ssm_ami" { 275 most_recent = true 276 filter { 277 name = "name" 278 values = ["*hvm-ssd/ubuntu-trusty-14.04*"] 279 } 280 } 281 282 resource "aws_iam_instance_profile" "ssm_profile" { 283 name = "ssm_profile-%s" 284 roles = ["${aws_iam_role.ssm_role.name}"] 285 } 286 287 resource "aws_iam_role" "ssm_role" { 288 name = "ssm_role-%s" 289 path = "/" 290 assume_role_policy = <<EOF 291 { 292 "Version": "2012-10-17", 293 "Statement": [ 294 { 295 "Action": "sts:AssumeRole", 296 "Principal": { 297 "Service": "ec2.amazonaws.com" 298 }, 299 "Effect": "Allow", 300 "Sid": "" 301 } 302 ] 303 } 304 EOF 305 } 306 307 resource "aws_ssm_document" "foo" { 308 name = "test_document-%s" 309 document_type = "Automation" 310 content = <<DOC 311 { 312 "description": "Systems Manager Automation Demo", 313 "schemaVersion": "0.3", 314 "assumeRole": "${aws_iam_role.ssm_role.arn}", 315 "mainSteps": [ 316 { 317 "name": "startInstances", 318 "action": "aws:runInstances", 319 "timeoutSeconds": 1200, 320 "maxAttempts": 1, 321 "onFailure": "Abort", 322 "inputs": { 323 "ImageId": "${data.aws_ami.ssm_ami.id}", 324 "InstanceType": "t2.small", 325 "MinInstanceCount": 1, 326 "MaxInstanceCount": 1, 327 "IamInstanceProfileName": "${aws_iam_instance_profile.ssm_profile.name}" 328 } 329 }, 330 { 331 "name": "stopInstance", 332 "action": "aws:changeInstanceState", 333 "maxAttempts": 1, 334 "onFailure": "Continue", 335 "inputs": { 336 "InstanceIds": [ 337 "{{ startInstances.InstanceIds }}" 338 ], 339 "DesiredState": "stopped" 340 } 341 }, 342 { 343 "name": "terminateInstance", 344 "action": "aws:changeInstanceState", 345 "maxAttempts": 1, 346 "onFailure": "Continue", 347 "inputs": { 348 "InstanceIds": [ 349 "{{ startInstances.InstanceIds }}" 350 ], 351 "DesiredState": "terminated" 352 } 353 } 354 ] 355 } 356 DOC 357 } 358 359 `, rName, rName, rName) 360 } 361 362 func TestAccAWSSSMDocument_documentTypeValidation(t *testing.T) { 363 cases := []struct { 364 Value string 365 ErrCount int 366 }{ 367 {Value: "Command", ErrCount: 0}, 368 {Value: "Policy", ErrCount: 0}, 369 {Value: "Automation", ErrCount: 0}, 370 {Value: "XYZ", ErrCount: 1}, 371 } 372 373 for _, tc := range cases { 374 _, errors := validateAwsSSMDocumentType(tc.Value, "aws_ssm_document") 375 376 if len(errors) != tc.ErrCount { 377 t.Fatalf("Expected the AWS SSM Document document_type to trigger a validation error") 378 } 379 } 380 }