github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/test/terraform_remote_exec_example_test.go (about)

     1  package test
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/gruntwork-io/terratest/modules/aws"
    12  	"github.com/gruntwork-io/terratest/modules/random"
    13  	"github.com/gruntwork-io/terratest/modules/ssh"
    14  	"github.com/gruntwork-io/terratest/modules/terraform"
    15  	test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  // This test shows how to override the systems local SSH Agent, with an in-process SSH agent, whose keys can be managed
    20  // from within your tests. This allows you to test Terraform modules which make SSH connections to the created
    21  // instances, useful for tasks such as provisioning.
    22  func TestTerraformRemoteExecExample(t *testing.T) {
    23  	t.Parallel()
    24  
    25  	terraformDirectory := "../examples/terraform-remote-exec-example"
    26  
    27  	// At the end of the test, run `terraform destroy` to clean up any resources that were created
    28  	defer test_structure.RunTestStage(t, "teardown", func() {
    29  		terraformOptions := test_structure.LoadTerraformOptions(t, terraformDirectory)
    30  		keyPair := test_structure.LoadEc2KeyPair(t, terraformDirectory)
    31  
    32  		// destroy terraform resources and delete ec2 key pair
    33  		terraform.Destroy(t, terraformOptions)
    34  		aws.DeleteEC2KeyPair(t, keyPair)
    35  
    36  		// remove testFile, if it exists
    37  		testFile := filepath.Join(terraformDirectory, "public-ip")
    38  		if _, err := os.Stat(testFile); err == nil {
    39  			os.Remove(testFile)
    40  		}
    41  	})
    42  
    43  	// Deploy the example
    44  	test_structure.RunTestStage(t, "setup", func() {
    45  
    46  		// A unique ID we can use to namespace resources so we don't clash with anything already in the AWS account or
    47  		// tests running in parallel
    48  		uniqueID := random.UniqueId()
    49  
    50  		// Give this EC2 Instance and other resources in the Terraform code a name with a unique ID so it doesn't clash
    51  		// with anything else in the AWS account.
    52  		instanceName := fmt.Sprintf("terratest-remote-exec-example-%s", uniqueID)
    53  
    54  		// Pick a random AWS region to test in. This helps ensure your code works in all regions.
    55  		awsRegion := aws.GetRandomStableRegion(t, nil, nil)
    56  
    57  		// Some AWS regions are missing certain instance types, so pick an available type based on the region we picked
    58  		instanceType := aws.GetRecommendedInstanceType(t, awsRegion, []string{"t2.micro", "t3.micro"})
    59  
    60  		// Create an EC2 KeyPair that we can use for SSH access
    61  		keyPairName := fmt.Sprintf("terratest-remote-exec-example-%s", uniqueID)
    62  		keyPair := aws.CreateAndImportEC2KeyPair(t, awsRegion, keyPairName)
    63  
    64  		// start an SSH agent, with our key pair added
    65  		sshAgent := ssh.SshAgentWithKeyPair(t, keyPair.KeyPair)
    66  		defer sshAgent.Stop()
    67  
    68  		// Construct the terraform options with default retryable errors to handle the most common retryable errors in
    69  		// terraform testing.
    70  		terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
    71  			// The path to where our Terraform code is located
    72  			TerraformDir: terraformDirectory,
    73  
    74  			// Variables to pass to our Terraform code using -var options
    75  			Vars: map[string]interface{}{
    76  				"aws_region":    awsRegion,
    77  				"instance_name": instanceName,
    78  				"instance_type": instanceType,
    79  				"key_pair_name": keyPairName,
    80  			},
    81  
    82  			SshAgent: sshAgent, // Overrides local SSH agent with our new agent
    83  		})
    84  
    85  		// Save the options and key pair so later test stages can use them
    86  		test_structure.SaveTerraformOptions(t, terraformDirectory, terraformOptions)
    87  		test_structure.SaveEc2KeyPair(t, terraformDirectory, keyPair)
    88  
    89  		// Because of the SshAgent option above, the terraform process will be provided an `SSH_AUTH_SOCK` environment
    90  		// variable, which will point to the socket file of our in-process `sshAgent` instance:
    91  		terraform.InitAndApply(t, terraformOptions)
    92  
    93  		// save the `public_instance_ip` output variable for later steps
    94  		publicIP := terraform.Output(t, terraformOptions, "public_instance_ip")
    95  		test_structure.SaveString(t, terraformDirectory, "publicIP", publicIP)
    96  	})
    97  
    98  	// Make sure we can SSH to the public Instance directly from the public Internet and the private Instance by using
    99  	// the public Instance as a jump host
   100  	test_structure.RunTestStage(t, "validate", func() {
   101  		publicIP := test_structure.LoadString(t, terraformDirectory, "publicIP")
   102  
   103  		// Confirm that the public-ip file that was generated by the provisioner was copied back from the server using
   104  		// the `scp` command
   105  		testFile := filepath.Join(terraformDirectory, "public-ip")
   106  		assert.FileExists(t, testFile)
   107  
   108  		// Check that public IP from output matches public IP generated by script on the server
   109  		b, err := ioutil.ReadFile(testFile)
   110  		if err != nil {
   111  			fmt.Print(err)
   112  		}
   113  		assert.Equal(t, strings.TrimSpace(publicIP), strings.TrimSpace(string(b)))
   114  	})
   115  
   116  }