Skip to content

Commit cf9903e

Browse files
rainkwanstephybunSBGoods
authored
List Resource QueryCheck (#533)
* Initial work on Query command for List Resource * Added helper/resource parts for query * Moved files * But what if we comment out print statements? * What if we are more specific and say `.tfquery.hcl` * Updating to version 1.14 for query_test.go * Scaffolding for QueryCheck * Outlining the marshalling for filling in terraform-json.Query * Update testing_new.go * Update helper/resource/query/query_test.go Co-authored-by: stephybun <[email protected]> * Update internal/plugintest/working_dir.go Co-authored-by: stephybun <[email protected]> * Update internal/teststep/file.go Co-authored-by: stephybun <[email protected]> * Updating branch * Working on using unmarshalled buffer instead of tfjson * Removed tests that get skipped for version * pass reattach info into QueryJSON call * unmarshal found list result * change tfversion checks to skip below `1.14` * try unmarshalling query results and traversing using `tfjsonpath` * Updated go mod to latest * Changes from pairing * Updated terraform exec with new draft and initial query test in helper/resource running * Updated to add error handling for returned terraform exec boolean * Pushing for up to dateness * updating providerserver.go * Updated the query test to return actual identity and start to implement List * fixed test so expect_identity.go runs * Refactored expect_identity.go so it works for multiple identity attributes, started to add length and length exact checks * Changes by sgoods * Updated error messages * Updated error messages * Updated comment * add contains query check for checking if a given resource exists in the query results * update CheckQueryRequest to provide ListResourceFoundData and ListCompleteData and refactor a little * add expect known value check * Updated comment * Ran make generate * Fixed lintier * Fixed lintier * update terraform-json and terraform-exec dependencies and update query checks to be consistent with existing statechecks * remove redundant return statement and skip over nil messages * fix query test * review comments * update query test * minor fixes --------- Co-authored-by: stephybun <[email protected]> Co-authored-by: Selena Goods <[email protected]>
1 parent 1a2eeae commit cf9903e

22 files changed

+804
-90
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ require (
1313
github.com/hashicorp/hc-install v0.9.2
1414
github.com/hashicorp/hcl/v2 v2.24.0
1515
github.com/hashicorp/logutils v1.0.0
16-
github.com/hashicorp/terraform-exec v0.23.1-0.20250717072919-061a850a52d2
17-
github.com/hashicorp/terraform-json v0.26.0
16+
github.com/hashicorp/terraform-exec v0.24.0
17+
github.com/hashicorp/terraform-json v0.27.2
1818
github.com/hashicorp/terraform-plugin-go v0.29.0-beta.1
1919
github.com/hashicorp/terraform-plugin-log v0.9.0
2020
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQx
7676
github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM=
7777
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
7878
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
79-
github.com/hashicorp/terraform-exec v0.23.1-0.20250717072919-061a850a52d2 h1:90fcAqw0Qmv4vY7zL4jEKgKarHmOnNN6SjTY68eLKGA=
80-
github.com/hashicorp/terraform-exec v0.23.1-0.20250717072919-061a850a52d2/go.mod h1:8D3RLLpzAZdhT9jvALYz1KHyGU4OvI73I1o0+01QJxA=
81-
github.com/hashicorp/terraform-json v0.26.0 h1:+BnJavhRH+oyNWPnfzrfQwVWCZBFMvjdiH2Vi38Udz4=
82-
github.com/hashicorp/terraform-json v0.26.0/go.mod h1:eyWCeC3nrZamyrKLFnrvwpc3LQPIJsx8hWHQ/nu2/v4=
79+
github.com/hashicorp/terraform-exec v0.24.0 h1:mL0xlk9H5g2bn0pPF6JQZk5YlByqSqrO5VoaNtAf8OE=
80+
github.com/hashicorp/terraform-exec v0.24.0/go.mod h1:lluc/rDYfAhYdslLJQg3J0oDqo88oGQAdHR+wDqFvo4=
81+
github.com/hashicorp/terraform-json v0.27.2 h1:BwGuzM6iUPqf9JYM/Z4AF1OJ5VVJEEzoKST/tRDBJKU=
82+
github.com/hashicorp/terraform-json v0.27.2/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE=
8383
github.com/hashicorp/terraform-plugin-go v0.29.0-beta.1 h1:xeHlRQYev3iMXwX2W7+D1bSfLRBs9jojZXqE6hmNxMI=
8484
github.com/hashicorp/terraform-plugin-go v0.29.0-beta.1/go.mod h1:5pww/UULn9C2tItq6o5sbScEkJxBUt9X9kI4DkeRsIw=
8585
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package query_test
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
8+
"github.com/hashicorp/terraform-plugin-go/tftypes"
9+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
10+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
11+
"github.com/hashicorp/terraform-plugin-testing/internal/teststep"
12+
)
13+
14+
func examplecloudListResource() testprovider.ListResource {
15+
return testprovider.ListResource{
16+
IncludeResource: true,
17+
SchemaResponse: &list.SchemaResponse{
18+
Schema: &tfprotov6.Schema{
19+
Block: &tfprotov6.SchemaBlock{
20+
Attributes: []*tfprotov6.SchemaAttribute{
21+
{
22+
Name: "id",
23+
Type: tftypes.String,
24+
Computed: true,
25+
},
26+
},
27+
},
28+
},
29+
},
30+
ListResultsStream: &list.ListResultsStream{
31+
Results: func(push func(list.ListResult) bool) {
32+
push(list.ListResult{
33+
Resource: teststep.Pointer(tftypes.NewValue(
34+
tftypes.Object{
35+
AttributeTypes: map[string]tftypes.Type{
36+
"id": tftypes.String,
37+
"location": tftypes.String,
38+
"name": tftypes.String,
39+
},
40+
},
41+
map[string]tftypes.Value{
42+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
43+
"location": tftypes.NewValue(tftypes.String, "westeurope"),
44+
"name": tftypes.NewValue(tftypes.String, "somevalue"),
45+
},
46+
)),
47+
Identity: teststep.Pointer(tftypes.NewValue(
48+
tftypes.Object{
49+
AttributeTypes: map[string]tftypes.Type{
50+
"id": tftypes.String,
51+
"location": tftypes.String,
52+
},
53+
},
54+
map[string]tftypes.Value{
55+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue1"),
56+
"location": tftypes.NewValue(tftypes.String, "westeurope"),
57+
},
58+
)),
59+
})
60+
push(list.ListResult{
61+
Identity: teststep.Pointer(tftypes.NewValue(
62+
tftypes.Object{
63+
AttributeTypes: map[string]tftypes.Type{
64+
"id": tftypes.String,
65+
"location": tftypes.String,
66+
},
67+
},
68+
map[string]tftypes.Value{
69+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue2"),
70+
"location": tftypes.NewValue(tftypes.String, "westeurope2"),
71+
},
72+
)),
73+
})
74+
push(list.ListResult{
75+
Identity: teststep.Pointer(tftypes.NewValue(
76+
tftypes.Object{
77+
AttributeTypes: map[string]tftypes.Type{
78+
"id": tftypes.String,
79+
"location": tftypes.String,
80+
},
81+
},
82+
map[string]tftypes.Value{
83+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue3"),
84+
"location": tftypes.NewValue(tftypes.String, "westeurope3"),
85+
},
86+
)),
87+
})
88+
},
89+
},
90+
}
91+
}

helper/resource/query/examplecloud_test.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ func examplecloudResource() testprovider.Resource {
3131
NewIdentity: teststep.Pointer(tftypes.NewValue(
3232
tftypes.Object{
3333
AttributeTypes: map[string]tftypes.Type{
34-
"id": tftypes.String,
34+
"id": tftypes.String,
35+
"location": tftypes.String,
3536
},
3637
},
3738
map[string]tftypes.Value{
38-
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
39+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
40+
"location": tftypes.NewValue(tftypes.String, "somelocation"),
3941
},
4042
)),
4143
},
@@ -57,11 +59,13 @@ func examplecloudResource() testprovider.Resource {
5759
NewIdentity: teststep.Pointer(tftypes.NewValue(
5860
tftypes.Object{
5961
AttributeTypes: map[string]tftypes.Type{
60-
"id": tftypes.String,
62+
"id": tftypes.String,
63+
"location": tftypes.String,
6164
},
6265
},
6366
map[string]tftypes.Value{
64-
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
67+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
68+
"location": tftypes.NewValue(tftypes.String, "westeurope"),
6569
},
6670
)),
6771
},
@@ -83,11 +87,13 @@ func examplecloudResource() testprovider.Resource {
8387
Identity: teststep.Pointer(tftypes.NewValue(
8488
tftypes.Object{
8589
AttributeTypes: map[string]tftypes.Type{
86-
"id": tftypes.String,
90+
"id": tftypes.String,
91+
"location": tftypes.String,
8792
},
8893
},
8994
map[string]tftypes.Value{
90-
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
95+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
96+
"location": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
9197
},
9298
)),
9399
},
@@ -111,6 +117,11 @@ func examplecloudResource() testprovider.Resource {
111117
Type: tftypes.String,
112118
RequiredForImport: true,
113119
},
120+
{
121+
Name: "location",
122+
Type: tftypes.String,
123+
RequiredForImport: true,
124+
},
114125
},
115126
},
116127
},
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package query
5+
6+
import (
7+
"context"
8+
"errors"
9+
"fmt"
10+
11+
tfjson "github.com/hashicorp/terraform-json"
12+
"github.com/mitchellh/go-testing-interface"
13+
14+
"github.com/hashicorp/terraform-plugin-testing/querycheck"
15+
)
16+
17+
func RunQueryChecks(ctx context.Context, t testing.T, query []tfjson.LogMsg, queryChecks []querycheck.QueryResultCheck) error {
18+
t.Helper()
19+
20+
var result []error
21+
22+
if query == nil {
23+
result = append(result, fmt.Errorf("no query results found"))
24+
}
25+
26+
found := make([]tfjson.ListResourceFoundData, 0)
27+
summary := tfjson.ListCompleteData{}
28+
29+
for _, msg := range query {
30+
switch v := msg.(type) {
31+
case tfjson.ListResourceFoundMessage:
32+
found = append(found, v.ListResourceFound)
33+
case tfjson.ListCompleteMessage:
34+
summary = v.ListComplete
35+
// TODO diagnostics and errors?
36+
default:
37+
continue
38+
}
39+
}
40+
41+
for _, queryCheck := range queryChecks {
42+
resp := querycheck.CheckQueryResponse{}
43+
queryCheck.CheckQuery(ctx, querycheck.CheckQueryRequest{
44+
Query: found,
45+
QuerySummary: &summary,
46+
}, &resp)
47+
48+
result = append(result, resp.Error)
49+
}
50+
51+
return errors.Join(result...)
52+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package query
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/querycheck"
10+
)
11+
12+
var _ querycheck.QueryResultCheck = &queryCheckSpy{}
13+
14+
type queryCheckSpy struct {
15+
err error
16+
called bool
17+
}
18+
19+
func (s *queryCheckSpy) CheckQuery(ctx context.Context, req querycheck.CheckQueryRequest, resp *querycheck.CheckQueryResponse) {
20+
s.called = true
21+
resp.Error = s.err
22+
}

0 commit comments

Comments
 (0)