Skip to content

Commit 25e27b4

Browse files
committed
test: Add command-level test for state list showing integration with pluggable state storage code.
1 parent 444c044 commit 25e27b4

File tree

6 files changed

+172
-0
lines changed

6 files changed

+172
-0
lines changed

internal/command/state_list_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
package command
55

66
import (
7+
"bytes"
78
"strings"
89
"testing"
910

1011
"github.com/hashicorp/cli"
12+
"github.com/hashicorp/terraform/internal/addrs"
13+
"github.com/hashicorp/terraform/internal/providers"
14+
"github.com/hashicorp/terraform/internal/states"
15+
"github.com/hashicorp/terraform/internal/states/statefile"
1116
)
1217

1318
func TestStateList(t *testing.T) {
@@ -153,6 +158,83 @@ func TestStateList_backendCustomState(t *testing.T) {
153158
}
154159
}
155160

161+
// Tests using `terraform state list` subcommand in combination with pluggable state storage
162+
//
163+
// Note: Whereas other tests in this file use the local backend and require a state file in the test fixures,
164+
// with pluggable state storage we can define the state via the mocked provider.
165+
func TestStateList_stateStore(t *testing.T) {
166+
// Create a temporary working directory that is empty
167+
td := t.TempDir()
168+
testCopyDir(t, testFixturePath("state-list-state-store"), td)
169+
t.Chdir(td)
170+
171+
// Get bytes describing a state containing a resource
172+
state := states.NewState()
173+
rootModule := state.RootModule()
174+
rootModule.SetResourceInstanceCurrent(
175+
addrs.Resource{
176+
Mode: addrs.ManagedResourceMode,
177+
Type: "test_instance",
178+
Name: "foo",
179+
}.Instance(addrs.NoKey),
180+
&states.ResourceInstanceObjectSrc{
181+
Status: states.ObjectReady,
182+
AttrsJSON: []byte(`{
183+
"ami": "bar",
184+
"network_interface": [{
185+
"device_index": 0,
186+
"description": "Main network interface"
187+
}]
188+
}`),
189+
},
190+
addrs.AbsProviderConfig{
191+
Provider: addrs.NewDefaultProvider("test"),
192+
Module: addrs.RootModule,
193+
},
194+
)
195+
var stateBuf bytes.Buffer
196+
if err := statefile.Write(statefile.New(state, "", 1), &stateBuf); err != nil {
197+
t.Fatal(err)
198+
}
199+
200+
// Create a mock that contains a persisted "default" state that uses the bytes from above.
201+
mockProvider := mockPluggableStateStorageProvider(t)
202+
mockProvider.MockStates = map[string]interface{}{
203+
"default": stateBuf.Bytes(),
204+
}
205+
mockProviderAddress := addrs.NewDefaultProvider("test")
206+
providerSource, close := newMockProviderSource(t, map[string][]string{
207+
"hashicorp/test": {"1.0.0"},
208+
})
209+
defer close()
210+
211+
ui := cli.NewMockUi()
212+
c := &StateListCommand{
213+
Meta: Meta{
214+
AllowExperimentalFeatures: true,
215+
testingOverrides: &testingOverrides{
216+
Providers: map[addrs.Provider]providers.Factory{
217+
mockProviderAddress: providers.FactoryFixed(mockProvider),
218+
},
219+
},
220+
ProviderSource: providerSource,
221+
Ui: ui,
222+
},
223+
}
224+
225+
args := []string{}
226+
if code := c.Run(args); code != 0 {
227+
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
228+
}
229+
230+
// Test that outputs were displayed
231+
expected := "test_instance.foo\n"
232+
actual := ui.OutputWriter.String()
233+
if actual != expected {
234+
t.Fatalf("Expected:\n%q\n\nTo equal: %q", actual, expected)
235+
}
236+
}
237+
156238
func TestStateList_backendOverrideState(t *testing.T) {
157239
// Create a temporary working directory that is empty
158240
td := t.TempDir()

internal/command/testdata/state-list-state-store/.terraform.lock.hcl

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/command/testdata/state-list-state-store/.terraform/providers/registry.terraform.io/hashicorp/simple6/0.0.1/.gitkeep

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": 3,
3+
"serial": 0,
4+
"lineage": "666f9301-7e65-4b19-ae23-71184bb19b03",
5+
"state_store": {
6+
"type": "test_store",
7+
"config": {
8+
"value": "foobar"
9+
},
10+
"provider": {
11+
"version": "1.2.3",
12+
"source": "registry.terraform.io/hashicorp/test",
13+
"config": {
14+
"region": null
15+
}
16+
},
17+
"hash": 4158988729
18+
}
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
terraform {
2+
required_providers {
3+
test = {
4+
source = "registry.terraform.io/hashicorp/test"
5+
}
6+
}
7+
8+
state_store "test_store" {
9+
provider "test" {}
10+
11+
value = "foobar"
12+
}
13+
}
14+
15+
variable "name" {
16+
default = "world"
17+
}
18+
19+
resource "test_instance" "my-data" {
20+
input = "hello ${var.name}"
21+
}
22+
23+
output "greeting" {
24+
value = resource.terraform_data.my-data.output
25+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"version": 4,
3+
"terraform_version": "1.15.0",
4+
"serial": 1,
5+
"lineage": "9e13d881-e480-7a63-d47a-b4f5224e6743",
6+
"outputs": {
7+
"greeting": {
8+
"value": "hello world",
9+
"type": "string"
10+
}
11+
},
12+
"resources": [
13+
{
14+
"mode": "managed",
15+
"type": "terraform_data",
16+
"name": "my-data",
17+
"provider": "provider[\"terraform.io/builtin/terraform\"]",
18+
"instances": [
19+
{
20+
"schema_version": 0,
21+
"attributes": {
22+
"id": "d71fb368-2ba1-fb4c-5bd9-6a2b7f05d60c",
23+
"input": {
24+
"value": "hello world",
25+
"type": "string"
26+
},
27+
"output": {
28+
"value": "hello world",
29+
"type": "string"
30+
},
31+
"triggers_replace": null
32+
},
33+
"sensitive_attributes": [],
34+
"identity_schema_version": 0
35+
}
36+
]
37+
}
38+
],
39+
"check_results": null
40+
}

0 commit comments

Comments
 (0)