github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/command/push_test.go (about) 1 package command 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "compress/gzip" 7 "io" 8 "os" 9 "reflect" 10 "sort" 11 "testing" 12 13 "github.com/hashicorp/terraform/terraform" 14 "github.com/mitchellh/cli" 15 ) 16 17 func TestPush_good(t *testing.T) { 18 tmp, cwd := testCwd(t) 19 defer testFixCwd(t, tmp, cwd) 20 21 // Create remote state file, this should be pulled 22 conf, srv := testRemoteState(t, testState(), 200) 23 defer srv.Close() 24 25 // Persist local remote state 26 s := terraform.NewState() 27 s.Serial = 5 28 s.Remote = conf 29 testStateFileRemote(t, s) 30 31 // Path where the archive will be "uploaded" to 32 archivePath := testTempFile(t) 33 defer os.Remove(archivePath) 34 35 client := &mockPushClient{File: archivePath} 36 ui := new(cli.MockUi) 37 c := &PushCommand{ 38 Meta: Meta{ 39 ContextOpts: testCtxConfig(testProvider()), 40 Ui: ui, 41 }, 42 43 client: client, 44 } 45 46 args := []string{ 47 testFixturePath("push"), 48 } 49 if code := c.Run(args); code != 0 { 50 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 51 } 52 53 actual := testArchiveStr(t, archivePath) 54 expected := []string{ 55 ".terraform/", 56 ".terraform/terraform.tfstate", 57 "main.tf", 58 } 59 if !reflect.DeepEqual(actual, expected) { 60 t.Fatalf("bad: %#v", actual) 61 } 62 63 variables := make(map[string]string) 64 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 65 t.Fatalf("bad: %#v", client.UpsertOptions) 66 } 67 68 if client.UpsertOptions.Name != "foo" { 69 t.Fatalf("bad: %#v", client.UpsertOptions) 70 } 71 } 72 73 func TestPush_input(t *testing.T) { 74 tmp, cwd := testCwd(t) 75 defer testFixCwd(t, tmp, cwd) 76 77 // Create remote state file, this should be pulled 78 conf, srv := testRemoteState(t, testState(), 200) 79 defer srv.Close() 80 81 // Persist local remote state 82 s := terraform.NewState() 83 s.Serial = 5 84 s.Remote = conf 85 testStateFileRemote(t, s) 86 87 // Path where the archive will be "uploaded" to 88 archivePath := testTempFile(t) 89 defer os.Remove(archivePath) 90 91 client := &mockPushClient{File: archivePath} 92 ui := new(cli.MockUi) 93 c := &PushCommand{ 94 Meta: Meta{ 95 ContextOpts: testCtxConfig(testProvider()), 96 Ui: ui, 97 }, 98 99 client: client, 100 } 101 102 // Disable test mode so input would be asked and setup the 103 // input reader/writers. 104 test = false 105 defer func() { test = true }() 106 defaultInputReader = bytes.NewBufferString("foo\n") 107 defaultInputWriter = new(bytes.Buffer) 108 109 args := []string{ 110 testFixturePath("push-input"), 111 } 112 if code := c.Run(args); code != 0 { 113 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 114 } 115 116 variables := map[string]string{ 117 "foo": "foo", 118 } 119 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 120 t.Fatalf("bad: %#v", client.UpsertOptions) 121 } 122 } 123 124 func TestPush_inputPartial(t *testing.T) { 125 tmp, cwd := testCwd(t) 126 defer testFixCwd(t, tmp, cwd) 127 128 // Create remote state file, this should be pulled 129 conf, srv := testRemoteState(t, testState(), 200) 130 defer srv.Close() 131 132 // Persist local remote state 133 s := terraform.NewState() 134 s.Serial = 5 135 s.Remote = conf 136 testStateFileRemote(t, s) 137 138 // Path where the archive will be "uploaded" to 139 archivePath := testTempFile(t) 140 defer os.Remove(archivePath) 141 142 client := &mockPushClient{ 143 File: archivePath, 144 GetResult: map[string]string{"foo": "bar"}, 145 } 146 ui := new(cli.MockUi) 147 c := &PushCommand{ 148 Meta: Meta{ 149 ContextOpts: testCtxConfig(testProvider()), 150 Ui: ui, 151 }, 152 153 client: client, 154 } 155 156 // Disable test mode so input would be asked and setup the 157 // input reader/writers. 158 test = false 159 defer func() { test = true }() 160 defaultInputReader = bytes.NewBufferString("foo\n") 161 defaultInputWriter = new(bytes.Buffer) 162 163 args := []string{ 164 testFixturePath("push-input-partial"), 165 } 166 if code := c.Run(args); code != 0 { 167 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 168 } 169 170 variables := map[string]string{ 171 "foo": "bar", 172 "bar": "foo", 173 } 174 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 175 t.Fatalf("bad: %#v", client.UpsertOptions) 176 } 177 } 178 179 func TestPush_name(t *testing.T) { 180 tmp, cwd := testCwd(t) 181 defer testFixCwd(t, tmp, cwd) 182 183 // Create remote state file, this should be pulled 184 conf, srv := testRemoteState(t, testState(), 200) 185 defer srv.Close() 186 187 // Persist local remote state 188 s := terraform.NewState() 189 s.Serial = 5 190 s.Remote = conf 191 testStateFileRemote(t, s) 192 193 // Path where the archive will be "uploaded" to 194 archivePath := testTempFile(t) 195 defer os.Remove(archivePath) 196 197 client := &mockPushClient{File: archivePath} 198 ui := new(cli.MockUi) 199 c := &PushCommand{ 200 Meta: Meta{ 201 ContextOpts: testCtxConfig(testProvider()), 202 Ui: ui, 203 }, 204 205 client: client, 206 } 207 208 args := []string{ 209 "-name", "bar", 210 testFixturePath("push"), 211 } 212 if code := c.Run(args); code != 0 { 213 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 214 } 215 216 if client.UpsertOptions.Name != "bar" { 217 t.Fatalf("bad: %#v", client.UpsertOptions) 218 } 219 } 220 221 func TestPush_noState(t *testing.T) { 222 tmp, cwd := testCwd(t) 223 defer testFixCwd(t, tmp, cwd) 224 225 ui := new(cli.MockUi) 226 c := &PushCommand{ 227 Meta: Meta{ 228 ContextOpts: testCtxConfig(testProvider()), 229 Ui: ui, 230 }, 231 } 232 233 args := []string{} 234 if code := c.Run(args); code != 1 { 235 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 236 } 237 } 238 239 func TestPush_noRemoteState(t *testing.T) { 240 state := &terraform.State{ 241 Modules: []*terraform.ModuleState{ 242 &terraform.ModuleState{ 243 Path: []string{"root"}, 244 Resources: map[string]*terraform.ResourceState{ 245 "test_instance.foo": &terraform.ResourceState{ 246 Type: "test_instance", 247 Primary: &terraform.InstanceState{ 248 ID: "bar", 249 }, 250 }, 251 }, 252 }, 253 }, 254 } 255 statePath := testStateFile(t, state) 256 257 ui := new(cli.MockUi) 258 c := &PushCommand{ 259 Meta: Meta{ 260 Ui: ui, 261 }, 262 } 263 264 args := []string{ 265 "-state", statePath, 266 } 267 if code := c.Run(args); code != 1 { 268 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 269 } 270 } 271 272 func TestPush_plan(t *testing.T) { 273 tmp, cwd := testCwd(t) 274 defer testFixCwd(t, tmp, cwd) 275 276 // Create remote state file, this should be pulled 277 conf, srv := testRemoteState(t, testState(), 200) 278 defer srv.Close() 279 280 // Persist local remote state 281 s := terraform.NewState() 282 s.Serial = 5 283 s.Remote = conf 284 testStateFileRemote(t, s) 285 286 // Create a plan 287 planPath := testPlanFile(t, &terraform.Plan{ 288 Module: testModule(t, "apply"), 289 }) 290 291 ui := new(cli.MockUi) 292 c := &PushCommand{ 293 Meta: Meta{ 294 ContextOpts: testCtxConfig(testProvider()), 295 Ui: ui, 296 }, 297 } 298 299 args := []string{planPath} 300 if code := c.Run(args); code != 1 { 301 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 302 } 303 } 304 305 func testArchiveStr(t *testing.T, path string) []string { 306 f, err := os.Open(path) 307 if err != nil { 308 t.Fatalf("err: %s", err) 309 } 310 defer f.Close() 311 312 // Ungzip 313 gzipR, err := gzip.NewReader(f) 314 if err != nil { 315 t.Fatalf("err: %s", err) 316 } 317 318 // Accumulator 319 result := make([]string, 0, 10) 320 321 // Untar 322 tarR := tar.NewReader(gzipR) 323 for { 324 header, err := tarR.Next() 325 if err == io.EOF { 326 break 327 } 328 if err != nil { 329 t.Fatalf("err: %s", err) 330 } 331 332 result = append(result, header.Name) 333 } 334 335 sort.Strings(result) 336 return result 337 }