@@ -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
1520func 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 \n to include: %q" , actual , stateBytes )
126+ }
127+ }
128+
46129func TestStatePull_noState (t * testing.T ) {
47130 tmp := t .TempDir ()
48131 t .Chdir (tmp )
0 commit comments