Skip to content

Commit e51954f

Browse files
committed
test: Add command-level test for state pull showing integration with pluggable state storage code.
1 parent 29a43d9 commit e51954f

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

internal/command/state_pull_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import (
1010
"testing"
1111

1212
"github.com/hashicorp/cli"
13+
"github.com/hashicorp/terraform/internal/addrs"
14+
"github.com/hashicorp/terraform/internal/providers"
15+
"github.com/hashicorp/terraform/internal/states"
16+
"github.com/hashicorp/terraform/internal/states/statefile"
17+
"github.com/hashicorp/terraform/internal/terminal"
1318
)
1419

1520
func TestStatePull(t *testing.T) {
@@ -43,6 +48,84 @@ func TestStatePull(t *testing.T) {
4348
}
4449
}
4550

51+
// Tests using `terraform state pull` subcommand in combination with pluggable state storage
52+
//
53+
// Note: Whereas other tests in this file use the local backend and require a state file in the test fixures,
54+
// with pluggable state storage we can define the state via the mocked provider.
55+
func TestStatePull_stateStore(t *testing.T) {
56+
// Create a temporary working directory that is empty
57+
td := t.TempDir()
58+
testCopyDir(t, testFixturePath("state-list-state-store"), td)
59+
t.Chdir(td)
60+
61+
// Get bytes describing a state containing a resource
62+
state := states.NewState()
63+
rootModule := state.RootModule()
64+
rootModule.SetResourceInstanceCurrent(
65+
addrs.Resource{
66+
Mode: addrs.ManagedResourceMode,
67+
Type: "test_instance",
68+
Name: "foo",
69+
}.Instance(addrs.NoKey),
70+
&states.ResourceInstanceObjectSrc{
71+
Status: states.ObjectReady,
72+
AttrsJSON: []byte(`{
73+
"input": "foobar"
74+
}`),
75+
},
76+
addrs.AbsProviderConfig{
77+
Provider: addrs.NewDefaultProvider("test"),
78+
Module: addrs.RootModule,
79+
},
80+
)
81+
var stateBuf bytes.Buffer
82+
if err := statefile.Write(statefile.New(state, "", 1), &stateBuf); err != nil {
83+
t.Fatalf("error during test setup: %s", err)
84+
}
85+
stateBytes := stateBuf.Bytes()
86+
87+
// Create a mock that contains a persisted "default" state that uses the bytes from above.
88+
mockProvider := mockPluggableStateStorageProvider(t)
89+
mockProvider.MockStates = map[string]interface{}{
90+
"default": stateBytes,
91+
}
92+
mockProviderAddress := addrs.NewDefaultProvider("test")
93+
providerSource, close := newMockProviderSource(t, map[string][]string{
94+
"hashicorp/test": {"1.0.0"},
95+
})
96+
defer close()
97+
98+
ui := cli.NewMockUi()
99+
streams, _ := terminal.StreamsForTesting(t)
100+
c := &StatePullCommand{
101+
Meta: Meta{
102+
AllowExperimentalFeatures: true,
103+
testingOverrides: &testingOverrides{
104+
Providers: map[addrs.Provider]providers.Factory{
105+
mockProviderAddress: providers.FactoryFixed(mockProvider),
106+
},
107+
},
108+
ProviderSource: providerSource,
109+
Ui: ui,
110+
Streams: streams,
111+
},
112+
}
113+
114+
// `terraform show` command specifying a given resource addr
115+
expectedResourceAddr := "test_instance.foo"
116+
args := []string{expectedResourceAddr}
117+
code := c.Run(args)
118+
if code != 0 {
119+
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
120+
}
121+
122+
// Test that the state in the output matches the original state
123+
actual := ui.OutputWriter.Bytes()
124+
if bytes.Equal(actual, stateBytes) {
125+
t.Fatalf("expected:\n%s\n\nto include: %q", actual, stateBytes)
126+
}
127+
}
128+
46129
func TestStatePull_noState(t *testing.T) {
47130
tmp := t.TempDir()
48131
t.Chdir(tmp)

0 commit comments

Comments
 (0)