github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/command/state_push_test.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "os" 6 "strings" 7 "testing" 8 9 "github.com/hashicorp/terraform/backend" 10 "github.com/hashicorp/terraform/backend/remote-state/inmem" 11 "github.com/hashicorp/terraform/helper/copy" 12 "github.com/hashicorp/terraform/states" 13 "github.com/mitchellh/cli" 14 ) 15 16 func TestStatePush_empty(t *testing.T) { 17 // Create a temporary working directory that is empty 18 td := tempDir(t) 19 copy.CopyDir(testFixturePath("state-push-good"), td) 20 defer os.RemoveAll(td) 21 defer testChdir(t, td)() 22 23 expected := testStateRead(t, "replace.tfstate") 24 25 p := testProvider() 26 ui := new(cli.MockUi) 27 c := &StatePushCommand{ 28 Meta: Meta{ 29 testingOverrides: metaOverridesForProvider(p), 30 Ui: ui, 31 }, 32 } 33 34 args := []string{"replace.tfstate"} 35 if code := c.Run(args); code != 0 { 36 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 37 } 38 39 actual := testStateRead(t, "local-state.tfstate") 40 if !actual.Equal(expected) { 41 t.Fatalf("bad: %#v", actual) 42 } 43 } 44 45 func TestStatePush_lockedState(t *testing.T) { 46 // Create a temporary working directory that is empty 47 td := tempDir(t) 48 copy.CopyDir(testFixturePath("state-push-good"), td) 49 defer os.RemoveAll(td) 50 defer testChdir(t, td)() 51 52 p := testProvider() 53 ui := new(cli.MockUi) 54 c := &StatePushCommand{ 55 Meta: Meta{ 56 testingOverrides: metaOverridesForProvider(p), 57 Ui: ui, 58 }, 59 } 60 61 unlock, err := testLockState(testDataDir, "local-state.tfstate") 62 if err != nil { 63 t.Fatal(err) 64 } 65 defer unlock() 66 67 args := []string{"replace.tfstate"} 68 if code := c.Run(args); code != 1 { 69 t.Fatalf("bad: %d", code) 70 } 71 if !strings.Contains(ui.ErrorWriter.String(), "Error acquiring the state lock") { 72 t.Fatalf("expected a lock error, got: %s", ui.ErrorWriter.String()) 73 } 74 } 75 76 func TestStatePush_replaceMatch(t *testing.T) { 77 // Create a temporary working directory that is empty 78 td := tempDir(t) 79 copy.CopyDir(testFixturePath("state-push-replace-match"), td) 80 defer os.RemoveAll(td) 81 defer testChdir(t, td)() 82 83 expected := testStateRead(t, "replace.tfstate") 84 85 p := testProvider() 86 ui := new(cli.MockUi) 87 c := &StatePushCommand{ 88 Meta: Meta{ 89 testingOverrides: metaOverridesForProvider(p), 90 Ui: ui, 91 }, 92 } 93 94 args := []string{"replace.tfstate"} 95 if code := c.Run(args); code != 0 { 96 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 97 } 98 99 actual := testStateRead(t, "local-state.tfstate") 100 if !actual.Equal(expected) { 101 t.Fatalf("bad: %#v", actual) 102 } 103 } 104 105 func TestStatePush_replaceMatchStdin(t *testing.T) { 106 // Create a temporary working directory that is empty 107 td := tempDir(t) 108 copy.CopyDir(testFixturePath("state-push-replace-match"), td) 109 defer os.RemoveAll(td) 110 defer testChdir(t, td)() 111 112 expected := testStateRead(t, "replace.tfstate") 113 114 // Setup the replacement to come from stdin 115 var buf bytes.Buffer 116 if err := writeStateForTesting(expected, &buf); err != nil { 117 t.Fatalf("err: %s", err) 118 } 119 defer testStdinPipe(t, &buf)() 120 121 p := testProvider() 122 ui := new(cli.MockUi) 123 c := &StatePushCommand{ 124 Meta: Meta{ 125 testingOverrides: metaOverridesForProvider(p), 126 Ui: ui, 127 }, 128 } 129 130 args := []string{"-force", "-"} 131 if code := c.Run(args); code != 0 { 132 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 133 } 134 135 actual := testStateRead(t, "local-state.tfstate") 136 if !actual.Equal(expected) { 137 t.Fatalf("bad: %#v", actual) 138 } 139 } 140 141 func TestStatePush_lineageMismatch(t *testing.T) { 142 // Create a temporary working directory that is empty 143 td := tempDir(t) 144 copy.CopyDir(testFixturePath("state-push-bad-lineage"), td) 145 defer os.RemoveAll(td) 146 defer testChdir(t, td)() 147 148 expected := testStateRead(t, "local-state.tfstate") 149 150 p := testProvider() 151 ui := cli.NewMockUi() 152 c := &StatePushCommand{ 153 Meta: Meta{ 154 testingOverrides: metaOverridesForProvider(p), 155 Ui: ui, 156 }, 157 } 158 159 args := []string{"replace.tfstate"} 160 if code := c.Run(args); code != 1 { 161 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 162 } 163 164 actual := testStateRead(t, "local-state.tfstate") 165 if !actual.Equal(expected) { 166 t.Fatalf("bad: %#v", actual) 167 } 168 } 169 170 func TestStatePush_serialNewer(t *testing.T) { 171 // Create a temporary working directory that is empty 172 td := tempDir(t) 173 copy.CopyDir(testFixturePath("state-push-serial-newer"), td) 174 defer os.RemoveAll(td) 175 defer testChdir(t, td)() 176 177 expected := testStateRead(t, "local-state.tfstate") 178 179 p := testProvider() 180 ui := new(cli.MockUi) 181 c := &StatePushCommand{ 182 Meta: Meta{ 183 testingOverrides: metaOverridesForProvider(p), 184 Ui: ui, 185 }, 186 } 187 188 args := []string{"replace.tfstate"} 189 if code := c.Run(args); code != 1 { 190 t.Fatalf("bad: %d", code) 191 } 192 193 actual := testStateRead(t, "local-state.tfstate") 194 if !actual.Equal(expected) { 195 t.Fatalf("bad: %#v", actual) 196 } 197 } 198 199 func TestStatePush_serialOlder(t *testing.T) { 200 // Create a temporary working directory that is empty 201 td := tempDir(t) 202 copy.CopyDir(testFixturePath("state-push-serial-older"), td) 203 defer os.RemoveAll(td) 204 defer testChdir(t, td)() 205 206 expected := testStateRead(t, "replace.tfstate") 207 208 p := testProvider() 209 ui := new(cli.MockUi) 210 c := &StatePushCommand{ 211 Meta: Meta{ 212 testingOverrides: metaOverridesForProvider(p), 213 Ui: ui, 214 }, 215 } 216 217 args := []string{"replace.tfstate"} 218 if code := c.Run(args); code != 0 { 219 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 220 } 221 222 actual := testStateRead(t, "local-state.tfstate") 223 if !actual.Equal(expected) { 224 t.Fatalf("bad: %#v", actual) 225 } 226 } 227 228 func TestStatePush_forceRemoteState(t *testing.T) { 229 td := tempDir(t) 230 copy.CopyDir(testFixturePath("inmem-backend"), td) 231 defer os.RemoveAll(td) 232 defer testChdir(t, td)() 233 defer inmem.Reset() 234 235 s := states.NewState() 236 statePath := testStateFile(t, s) 237 238 // init the backend 239 ui := new(cli.MockUi) 240 initCmd := &InitCommand{ 241 Meta: Meta{Ui: ui}, 242 } 243 if code := initCmd.Run([]string{}); code != 0 { 244 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 245 } 246 247 // create a new workspace 248 ui = new(cli.MockUi) 249 newCmd := &WorkspaceNewCommand{ 250 Meta: Meta{Ui: ui}, 251 } 252 if code := newCmd.Run([]string{"test"}); code != 0 { 253 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter) 254 } 255 256 // put a dummy state in place, so we have something to force 257 b := backend.TestBackendConfig(t, inmem.New(), nil) 258 sMgr, err := b.StateMgr("test") 259 if err != nil { 260 t.Fatal(err) 261 } 262 if err := sMgr.WriteState(states.NewState()); err != nil { 263 t.Fatal(err) 264 } 265 if err := sMgr.PersistState(); err != nil { 266 t.Fatal(err) 267 } 268 269 // push our local state to that new workspace 270 ui = new(cli.MockUi) 271 c := &StatePushCommand{ 272 Meta: Meta{Ui: ui}, 273 } 274 275 args := []string{"-force", statePath} 276 if code := c.Run(args); code != 0 { 277 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 278 } 279 }