github.com/someshkoli/terratest@v0.41.1/modules/terraform/plan_test.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "path/filepath" 6 "testing" 7 8 "github.com/gruntwork-io/terratest/modules/files" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestInitAndPlanWithError(t *testing.T) { 14 t.Parallel() 15 16 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-with-plan-error", t.Name()) 17 require.NoError(t, err) 18 19 options := &Options{ 20 TerraformDir: testFolder, 21 } 22 23 _, err = InitAndPlanE(t, options) 24 require.Error(t, err) 25 } 26 27 func TestInitAndPlanWithNoError(t *testing.T) { 28 t.Parallel() 29 30 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-no-error", t.Name()) 31 require.NoError(t, err) 32 33 options := &Options{ 34 TerraformDir: testFolder, 35 } 36 37 // In Terraform 0.12 and below, if there were no resources to create, update, or destroy, 'plan' command would 38 // report "No changes. Infrastructure is up-to-date." However, with 0.13 and above, if the Terraform configuration 39 // has never been applied at all, 'plan' always shows changes. So we have to run 'apply' first, and can then 40 // check that 'plan' returns the message we expect. 41 InitAndApply(t, options) 42 out, err := PlanE(t, options) 43 require.NoError(t, err) 44 require.Contains(t, out, "No changes.") 45 } 46 47 func TestInitAndPlanWithOutput(t *testing.T) { 48 t.Parallel() 49 50 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-basic-configuration", t.Name()) 51 require.NoError(t, err) 52 53 options := &Options{ 54 TerraformDir: testFolder, 55 Vars: map[string]interface{}{ 56 "cnt": 1, 57 }, 58 } 59 60 out, err := InitAndPlanE(t, options) 61 require.NoError(t, err) 62 require.Contains(t, out, "1 to add, 0 to change, 0 to destroy.") 63 } 64 65 func TestInitAndPlanWithPlanFile(t *testing.T) { 66 t.Parallel() 67 68 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-basic-configuration", t.Name()) 69 require.NoError(t, err) 70 planFilePath := filepath.Join(testFolder, "plan.out") 71 72 options := &Options{ 73 TerraformDir: testFolder, 74 Vars: map[string]interface{}{ 75 "cnt": 1, 76 }, 77 PlanFilePath: planFilePath, 78 } 79 80 out, err := InitAndPlanE(t, options) 81 require.NoError(t, err) 82 assert.Contains(t, out, "1 to add, 0 to change, 0 to destroy.") 83 assert.Contains(t, out, fmt.Sprintf("Saved the plan to: %s", planFilePath)) 84 assert.FileExists(t, planFilePath, "Plan file was not saved to expected location:", planFilePath) 85 } 86 87 func TestInitAndPlanAndShowWithStructNoLogTempPlanFile(t *testing.T) { 88 t.Parallel() 89 90 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-basic-configuration", t.Name()) 91 require.NoError(t, err) 92 93 options := &Options{ 94 TerraformDir: testFolder, 95 Vars: map[string]interface{}{ 96 "cnt": 1, 97 }, 98 } 99 planStruct := InitAndPlanAndShowWithStructNoLogTempPlanFile(t, options) 100 assert.Equal(t, 1, len(planStruct.ResourceChangesMap)) 101 } 102 103 func TestPlanWithExitCodeWithNoChanges(t *testing.T) { 104 t.Parallel() 105 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-no-error", t.Name()) 106 require.NoError(t, err) 107 108 options := &Options{ 109 TerraformDir: testFolder, 110 } 111 112 // In Terraform 0.12 and below, if there were no resources to create, update, or destroy, the -detailed-exitcode 113 // would return a code of 0. However, with 0.13 and above, if the Terraform configuration has never been applied 114 // at all, -detailed-exitcode always returns an exit code of 2. So we have to run 'apply' first, and can then 115 // check that 'plan' returns the exit code we expect. 116 InitAndApply(t, options) 117 exitCode := PlanExitCode(t, options) 118 require.Equal(t, DefaultSuccessExitCode, exitCode) 119 } 120 121 func TestPlanWithExitCodeWithChanges(t *testing.T) { 122 t.Parallel() 123 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-basic-configuration", t.Name()) 124 require.NoError(t, err) 125 126 options := &Options{ 127 TerraformDir: testFolder, 128 Vars: map[string]interface{}{ 129 "cnt": 1, 130 }, 131 } 132 exitCode := InitAndPlanWithExitCode(t, options) 133 require.Equal(t, TerraformPlanChangesPresentExitCode, exitCode) 134 } 135 136 func TestPlanWithExitCodeWithFailure(t *testing.T) { 137 t.Parallel() 138 139 testFolder, err := files.CopyTerraformFolderToTemp("../../test/fixtures/terraform-with-plan-error", t.Name()) 140 require.NoError(t, err) 141 142 options := &Options{ 143 TerraformDir: testFolder, 144 } 145 146 exitCode, getExitCodeErr := InitAndPlanWithExitCodeE(t, options) 147 require.NoError(t, getExitCodeErr) 148 require.Equal(t, exitCode, 1) 149 } 150 151 func TestTgPlanAllNoError(t *testing.T) { 152 t.Parallel() 153 154 testFolder, err := files.CopyTerragruntFolderToTemp("../../test/fixtures/terragrunt/terragrunt-multi-plan", t.Name()) 155 require.NoError(t, err) 156 157 options := &Options{ 158 TerraformDir: testFolder, 159 TerraformBinary: "terragrunt", 160 } 161 162 // In Terraform 0.12 and below, if there were no resources to create, update, or destroy, the -detailed-exitcode 163 // would return a code of 0. However, with 0.13 and above, if the Terraform configuration has never been applied 164 // at all, -detailed-exitcode always returns an exit code of 2. So we have to run 'apply' first, and can then 165 // check that 'plan' returns the exit code we expect. 166 TgApplyAll(t, options) 167 getExitCode, errExitCode := TgPlanAllExitCodeE(t, options) 168 // GetExitCodeForRunCommandError was unable to determine the exit code correctly 169 if errExitCode != nil { 170 t.Fatal(errExitCode) 171 } 172 173 // Since PlanAllExitCodeTgE returns error codes, we want to compare against 1 174 require.Equal(t, DefaultSuccessExitCode, getExitCode) 175 } 176 177 func TestTgPlanAllWithError(t *testing.T) { 178 t.Parallel() 179 180 testFolder, err := files.CopyTerragruntFolderToTemp("../../test/fixtures/terragrunt/terragrunt-with-plan-error", t.Name()) 181 require.NoError(t, err) 182 183 options := &Options{ 184 TerraformDir: testFolder, 185 TerraformBinary: "terragrunt", 186 } 187 188 getExitCode, errExitCode := TgPlanAllExitCodeE(t, options) 189 // GetExitCodeForRunCommandError was unable to determine the exit code correctly 190 require.NoError(t, errExitCode) 191 192 require.Equal(t, DefaultErrorExitCode, getExitCode) 193 }