github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/backend/local/backend_plan_test.go (about) 1 package local 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/terraform/backend" 11 "github.com/hashicorp/terraform/config/module" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestLocal_planBasic(t *testing.T) { 16 b := TestLocal(t) 17 p := TestLocalProvider(t, b, "test") 18 19 mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") 20 defer modCleanup() 21 22 op := testOperationPlan() 23 op.Module = mod 24 op.PlanRefresh = true 25 26 run, err := b.Operation(context.Background(), op) 27 if err != nil { 28 t.Fatalf("bad: %s", err) 29 } 30 <-run.Done() 31 if run.Err != nil { 32 t.Fatalf("err: %s", err) 33 } 34 35 if !p.DiffCalled { 36 t.Fatal("diff should be called") 37 } 38 } 39 40 func TestLocal_planNoConfig(t *testing.T) { 41 b := TestLocal(t) 42 TestLocalProvider(t, b, "test") 43 44 op := testOperationPlan() 45 op.Module = nil 46 op.PlanRefresh = true 47 48 run, err := b.Operation(context.Background(), op) 49 if err != nil { 50 t.Fatalf("bad: %s", err) 51 } 52 <-run.Done() 53 54 err = run.Err 55 if err == nil { 56 t.Fatal("should error") 57 } 58 if !strings.Contains(err.Error(), "configuration") { 59 t.Fatalf("bad: %s", err) 60 } 61 } 62 63 func TestLocal_planRefreshFalse(t *testing.T) { 64 b := TestLocal(t) 65 p := TestLocalProvider(t, b, "test") 66 terraform.TestStateFile(t, b.StatePath, testPlanState()) 67 68 mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") 69 defer modCleanup() 70 71 op := testOperationPlan() 72 op.Module = mod 73 74 run, err := b.Operation(context.Background(), op) 75 if err != nil { 76 t.Fatalf("bad: %s", err) 77 } 78 <-run.Done() 79 if run.Err != nil { 80 t.Fatalf("err: %s", err) 81 } 82 83 if p.RefreshCalled { 84 t.Fatal("refresh should not be called") 85 } 86 87 if !run.PlanEmpty { 88 t.Fatal("plan should be empty") 89 } 90 } 91 92 func TestLocal_planDestroy(t *testing.T) { 93 b := TestLocal(t) 94 p := TestLocalProvider(t, b, "test") 95 terraform.TestStateFile(t, b.StatePath, testPlanState()) 96 97 mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") 98 defer modCleanup() 99 100 outDir := testTempDir(t) 101 defer os.RemoveAll(outDir) 102 planPath := filepath.Join(outDir, "plan.tfplan") 103 104 op := testOperationPlan() 105 op.Destroy = true 106 op.PlanRefresh = true 107 op.Module = mod 108 op.PlanOutPath = planPath 109 110 run, err := b.Operation(context.Background(), op) 111 if err != nil { 112 t.Fatalf("bad: %s", err) 113 } 114 <-run.Done() 115 if run.Err != nil { 116 t.Fatalf("err: %s", err) 117 } 118 119 if !p.RefreshCalled { 120 t.Fatal("refresh should be called") 121 } 122 123 if run.PlanEmpty { 124 t.Fatal("plan should not be empty") 125 } 126 127 plan := testReadPlan(t, planPath) 128 for _, m := range plan.Diff.Modules { 129 for _, r := range m.Resources { 130 if !r.Destroy { 131 t.Fatalf("bad: %#v", r) 132 } 133 } 134 } 135 } 136 137 func TestLocal_planDestroyNoConfig(t *testing.T) { 138 b := TestLocal(t) 139 p := TestLocalProvider(t, b, "test") 140 terraform.TestStateFile(t, b.StatePath, testPlanState()) 141 142 outDir := testTempDir(t) 143 defer os.RemoveAll(outDir) 144 planPath := filepath.Join(outDir, "plan.tfplan") 145 146 op := testOperationPlan() 147 op.Destroy = true 148 op.PlanRefresh = true 149 op.Module = nil 150 op.PlanOutPath = planPath 151 152 run, err := b.Operation(context.Background(), op) 153 if err != nil { 154 t.Fatalf("bad: %s", err) 155 } 156 <-run.Done() 157 if run.Err != nil { 158 t.Fatalf("err: %s", err) 159 } 160 161 if !p.RefreshCalled { 162 t.Fatal("refresh should be called") 163 } 164 165 if run.PlanEmpty { 166 t.Fatal("plan should not be empty") 167 } 168 169 plan := testReadPlan(t, planPath) 170 for _, m := range plan.Diff.Modules { 171 for _, r := range m.Resources { 172 if !r.Destroy { 173 t.Fatalf("bad: %#v", r) 174 } 175 } 176 } 177 } 178 179 func TestLocal_planOutPathNoChange(t *testing.T) { 180 b := TestLocal(t) 181 TestLocalProvider(t, b, "test") 182 terraform.TestStateFile(t, b.StatePath, testPlanState()) 183 184 mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") 185 defer modCleanup() 186 187 outDir := testTempDir(t) 188 defer os.RemoveAll(outDir) 189 planPath := filepath.Join(outDir, "plan.tfplan") 190 191 op := testOperationPlan() 192 op.Module = mod 193 op.PlanOutPath = planPath 194 195 run, err := b.Operation(context.Background(), op) 196 if err != nil { 197 t.Fatalf("bad: %s", err) 198 } 199 <-run.Done() 200 if run.Err != nil { 201 t.Fatalf("err: %s", err) 202 } 203 204 plan := testReadPlan(t, planPath) 205 if !plan.Diff.Empty() { 206 t.Fatalf("expected empty plan to be written") 207 } 208 } 209 210 func testOperationPlan() *backend.Operation { 211 return &backend.Operation{ 212 Type: backend.OperationTypePlan, 213 } 214 } 215 216 // testPlanState is just a common state that we use for testing refresh. 217 func testPlanState() *terraform.State { 218 return &terraform.State{ 219 Version: 2, 220 Modules: []*terraform.ModuleState{ 221 &terraform.ModuleState{ 222 Path: []string{"root"}, 223 Resources: map[string]*terraform.ResourceState{ 224 "test_instance.foo": &terraform.ResourceState{ 225 Type: "test_instance", 226 Primary: &terraform.InstanceState{ 227 ID: "bar", 228 }, 229 }, 230 }, 231 }, 232 }, 233 } 234 } 235 236 func testReadPlan(t *testing.T, path string) *terraform.Plan { 237 f, err := os.Open(path) 238 if err != nil { 239 t.Fatalf("err: %s", err) 240 } 241 defer f.Close() 242 243 p, err := terraform.ReadPlan(f) 244 if err != nil { 245 t.Fatalf("err: %s", err) 246 } 247 248 return p 249 }