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  }