Skip to content

Commit 0fe81af

Browse files
committed
Updated ListResource to return diags inside ListResult
1 parent ff6d367 commit 0fe81af

9 files changed

+41
-207
lines changed

internal/fwserver/server_listresource.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type ListRequest struct {
2828
// Resource field in the ListResult struct.
2929
IncludeResource bool
3030

31+
// Limit specifies the maximum number of results that Terraform is
32+
// expecting.
33+
Limit int64
34+
3135
ResourceSchema fwschema.Schema
3236
ResourceIdentitySchema fwschema.Schema
3337
}
@@ -79,17 +83,11 @@ type ListResult struct {
7983
var NoListResults = func(func(ListResult) bool) {}
8084

8185
// ListResource implements the framework server ListResource RPC.
82-
func (s *Server) ListResource(ctx context.Context, fwReq *ListRequest, fwStream *ListResultsStream) diag.Diagnostics {
86+
func (s *Server) ListResource(ctx context.Context, fwReq *ListRequest, fwStream *ListResultsStream) {
8387
listResource := fwReq.ListResource
8488

8589
if fwReq.Config == nil {
8690
fwStream.Results = NoListResults
87-
return diag.Diagnostics{
88-
diag.NewErrorDiagnostic(
89-
"Invalid ListResource Request",
90-
"Config cannot be nil",
91-
),
92-
}
9391
}
9492

9593
req := list.ListRequest{
@@ -111,7 +109,6 @@ func (s *Server) ListResource(ctx context.Context, fwReq *ListRequest, fwStream
111109
}
112110

113111
fwStream.Results = processListResults(req, stream.Results)
114-
return nil
115112
}
116113

117114
func processListResults(req list.ListRequest, stream iter.Seq[list.ListResult]) iter.Seq[ListResult] {

internal/fwserver/server_listresource_test.go

Lines changed: 2 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestServerListResource(t *testing.T) {
7373
server *fwserver.Server
7474
request *fwserver.ListRequest
7575
expectedStreamEvents []fwserver.ListResult
76-
expectedError diag.Diagnostics
76+
expectedError string
7777
}{
7878
"success-with-zero-results": {
7979
server: &fwserver.Server{
@@ -89,20 +89,6 @@ func TestServerListResource(t *testing.T) {
8989
},
9090
expectedStreamEvents: []fwserver.ListResult{},
9191
},
92-
"success-with-nil-results": {
93-
server: &fwserver.Server{
94-
Provider: &testprovider.Provider{},
95-
},
96-
request: &fwserver.ListRequest{
97-
Config: &tfsdk.Config{},
98-
ListResource: &testprovider.ListResource{
99-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
100-
// Do nothing, so that resp.Results is nil
101-
},
102-
},
103-
},
104-
expectedStreamEvents: []fwserver.ListResult{},
105-
},
10692
"success-with-multiple-results": {
10793
server: &fwserver.Server{
10894
Provider: &testprovider.Provider{},
@@ -167,167 +153,17 @@ func TestServerListResource(t *testing.T) {
167153
},
168154
},
169155
},
170-
"error-on-nil-config": {
171-
server: &fwserver.Server{
172-
Provider: &testprovider.Provider{},
173-
},
174-
request: &fwserver.ListRequest{
175-
Config: nil,
176-
ListResource: &testprovider.ListResource{
177-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
178-
resp.Results = list.NoListResults
179-
},
180-
},
181-
},
182-
expectedError: diag.Diagnostics{
183-
diag.NewErrorDiagnostic("Invalid ListResource Request", "Config cannot be nil"),
184-
},
185-
expectedStreamEvents: []fwserver.ListResult{},
186-
},
187-
"error-on-nil-resource-identity": {
188-
server: &fwserver.Server{
189-
Provider: &testprovider.Provider{},
190-
},
191-
request: &fwserver.ListRequest{
192-
Config: &tfsdk.Config{},
193-
ListResource: &testprovider.ListResource{
194-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
195-
resp.Results = slices.Values([]list.ListResult{
196-
{
197-
Identity: nil,
198-
Resource: &tfsdk.Resource{
199-
Schema: testSchema,
200-
Raw: testResourceValue1,
201-
},
202-
DisplayName: "Test Resource 1",
203-
},
204-
})
205-
},
206-
},
207-
},
208-
expectedStreamEvents: []fwserver.ListResult{
209-
{
210-
Diagnostics: diag.Diagnostics{
211-
diag.NewErrorDiagnostic("Incomplete List Result", "..."),
212-
},
213-
},
214-
},
215-
},
216-
"error-on-null-resource-identity": {
217-
server: &fwserver.Server{
218-
Provider: &testprovider.Provider{},
219-
},
220-
request: &fwserver.ListRequest{
221-
Config: &tfsdk.Config{},
222-
ListResource: &testprovider.ListResource{
223-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
224-
resp.Results = slices.Values([]list.ListResult{
225-
{
226-
Identity: &tfsdk.ResourceIdentity{},
227-
Resource: &tfsdk.Resource{
228-
Schema: testSchema,
229-
Raw: testResourceValue1,
230-
},
231-
DisplayName: "Test Resource 1",
232-
},
233-
})
234-
},
235-
},
236-
},
237-
expectedStreamEvents: []fwserver.ListResult{
238-
{
239-
Diagnostics: diag.Diagnostics{
240-
diag.NewErrorDiagnostic("Incomplete List Result", "..."),
241-
},
242-
},
243-
},
244-
},
245-
"warning-on-missing-resource": {
246-
server: &fwserver.Server{
247-
Provider: &testprovider.Provider{},
248-
},
249-
request: &fwserver.ListRequest{
250-
Config: &tfsdk.Config{},
251-
IncludeResource: true,
252-
ListResource: &testprovider.ListResource{
253-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
254-
resp.Results = slices.Values([]list.ListResult{
255-
{
256-
Identity: &tfsdk.ResourceIdentity{
257-
Schema: testIdentitySchema,
258-
Raw: testIdentityValue1,
259-
},
260-
Resource: nil,
261-
DisplayName: "Test Resource 1",
262-
},
263-
})
264-
},
265-
},
266-
},
267-
expectedStreamEvents: []fwserver.ListResult{
268-
{
269-
Identity: &tfsdk.ResourceIdentity{
270-
Schema: testIdentitySchema,
271-
Raw: testIdentityValue1,
272-
},
273-
DisplayName: "Test Resource 1",
274-
Diagnostics: diag.Diagnostics{
275-
diag.NewWarningDiagnostic("Incomplete List Result", "..."),
276-
},
277-
},
278-
},
279-
},
280-
"warning-on-null-resource": {
281-
server: &fwserver.Server{
282-
Provider: &testprovider.Provider{},
283-
},
284-
request: &fwserver.ListRequest{
285-
Config: &tfsdk.Config{},
286-
IncludeResource: true,
287-
ListResource: &testprovider.ListResource{
288-
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
289-
resp.Results = slices.Values([]list.ListResult{
290-
{
291-
Identity: &tfsdk.ResourceIdentity{
292-
Schema: testIdentitySchema,
293-
Raw: testIdentityValue1,
294-
},
295-
Resource: &tfsdk.Resource{},
296-
DisplayName: "Test Resource 1",
297-
},
298-
})
299-
},
300-
},
301-
},
302-
expectedStreamEvents: []fwserver.ListResult{
303-
{
304-
Identity: &tfsdk.ResourceIdentity{
305-
Schema: testIdentitySchema,
306-
Raw: testIdentityValue1,
307-
},
308-
Resource: &tfsdk.Resource{},
309-
DisplayName: "Test Resource 1",
310-
Diagnostics: diag.Diagnostics{
311-
diag.NewWarningDiagnostic("Incomplete List Result", "..."),
312-
},
313-
},
314-
},
315-
},
316156
}
317157

318158
for name, testCase := range testCases {
319159
t.Run(name, func(t *testing.T) {
320160
t.Parallel()
321161

322162
response := &fwserver.ListResultsStream{}
323-
err := testCase.server.ListResource(context.Background(), testCase.request, response)
324-
if diff := cmp.Diff(testCase.expectedError, err); diff != "" {
325-
t.Errorf("unexpected error difference: %s", diff)
326-
}
163+
testCase.server.ListResource(context.Background(), testCase.request, response)
327164

328165
opts := cmp.Options{
329166
cmp.Comparer(func(a, b diag.Diagnostics) bool {
330-
// Differences in Detail() are not relevant to correctness of logic
331167
for i := range a {
332168
if a[i].Severity() != b[i].Severity() || a[i].Summary() != b[i].Summary() {
333169
return false

internal/proto5server/server_listresource.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
// ListRequestErrorDiagnostics returns a value suitable for
1717
// [ListResourceServerStream.Results]. It yields a single result that contains
1818
// the given error diagnostics.
19-
func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic) (*tfprotov5.ListResourceServerStream, diag.Diagnostics) {
19+
func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic) (*tfprotov5.ListResourceServerStream, error) {
2020
protoDiags := toproto5.Diagnostics(ctx, diags)
2121
return &tfprotov5.ListResourceServerStream{
2222
Results: func(push func(tfprotov5.ListResourceResult) bool) {
@@ -25,7 +25,7 @@ func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic)
2525
}, nil
2626
}
2727

28-
func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov5.ListResourceRequest) (*tfprotov5.ListResourceServerStream, diag.Diagnostics) {
28+
func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov5.ListResourceRequest) (*tfprotov5.ListResourceServerStream, error) {
2929
protoStream := &tfprotov5.ListResourceServerStream{Results: tfprotov5.NoListResults}
3030
allDiags := diag.Diagnostics{}
3131

@@ -68,10 +68,7 @@ func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov5.ListResou
6868
}
6969
stream := &fwserver.ListResultsStream{}
7070

71-
err := s.FrameworkServer.ListResource(ctx, req, stream)
72-
if err != nil {
73-
return protoStream, err
74-
}
71+
s.FrameworkServer.ListResource(ctx, req, stream)
7572

7673
protoStream.Results = func(push func(tfprotov5.ListResourceResult) bool) {
7774
for result := range stream.Results {

internal/proto5server/server_listresource_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func TestServerListResource(t *testing.T) {
173173
testCases := map[string]struct {
174174
server *Server
175175
request *tfprotov5.ListResourceRequest
176-
expectedError diag.Diagnostics
176+
expectedError error
177177
expectedDiagnostics diag.Diagnostics
178178
expectedResults []tfprotov5.ListResourceResult
179179
}{

internal/proto5server/server_validatelistresourceconfig.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ func (s *Server) ValidateListResourceConfig(ctx context.Context, proto5Req *tfpr
6666
}
6767
stream := &fwserver.ListResultsStream{}
6868

69-
err := s.FrameworkServer.ListResource(ctx, req, stream)
70-
if err != nil {
71-
return toproto5.ValidateListResourceConfigResponse(ctx, fwResp), nil
72-
}
69+
s.FrameworkServer.ListResource(ctx, req, stream)
7370

7471
fwReq, diags := fromproto5.ValidateListResourceConfigRequest(ctx, proto5Req, listResource, listResourceSchema)
7572

internal/proto5server/server_validatelistresourceconfig_test.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package proto5server
66
import (
77
"context"
88
"github.com/hashicorp/terraform-plugin-framework/resource"
9+
"github.com/hashicorp/terraform-plugin-go/tftypes"
910
"testing"
1011

1112
"github.com/google/go-cmp/cmp"
@@ -14,12 +15,22 @@ import (
1415
"github.com/hashicorp/terraform-plugin-framework/list"
1516
"github.com/hashicorp/terraform-plugin-framework/list/schema"
1617
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
17-
"github.com/hashicorp/terraform-plugin-go/tftypes"
1818
)
1919

2020
func TestServerValidateListResourceConfig(t *testing.T) {
2121
t.Parallel()
2222

23+
testSchema := schema.Schema{
24+
Attributes: map[string]schema.Attribute{
25+
"test_optional": schema.StringAttribute{
26+
Optional: false,
27+
},
28+
"test_required": schema.StringAttribute{
29+
Required: true,
30+
},
31+
},
32+
}
33+
2334
testType := tftypes.Object{
2435
AttributeTypes: map[string]tftypes.Type{
2536
"test": tftypes.String,
@@ -33,15 +44,7 @@ func TestServerValidateListResourceConfig(t *testing.T) {
3344
testDynamicValue, err := tfprotov5.NewDynamicValue(testType, testValue)
3445

3546
if err != nil {
36-
t.Fatalf("unexpected error calling tfprotov5.NewDynamicValue(): %s", err)
37-
}
38-
39-
testSchema := schema.Schema{
40-
Attributes: map[string]schema.Attribute{
41-
"test": schema.StringAttribute{
42-
Required: true,
43-
},
44-
},
47+
t.Fatalf("unexpected error calling tfprotov6.NewDynamicValue(): %s", err)
4548
}
4649

4750
testCases := map[string]struct {
@@ -58,10 +61,20 @@ func TestServerValidateListResourceConfig(t *testing.T) {
5861
return []func() list.ListResource{
5962
func() list.ListResource {
6063
return &testprovider.ListResource{
61-
ListResourceConfigSchemaMethod: func(_ context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) {},
6264
MetadataMethod: func(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) {
6365
resp.TypeName = "test_resource"
6466
},
67+
ListResourceConfigSchemaMethod: func(_ context.Context, _ list.ListResourceSchemaRequest, resp *list.ListResourceSchemaResponse) {
68+
resp.Schema = schema.Schema{
69+
Attributes: map[string]schema.Attribute{
70+
"example_attribute": schema.StringAttribute{
71+
Required: true,
72+
},
73+
},
74+
}
75+
},
76+
ListMethod: func(_ context.Context, _ list.ListRequest, resp *list.ListResultsStream) {
77+
},
6578
}
6679
},
6780
}

internal/proto6server/server_listresource.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
// ListRequestErrorDiagnostics returns a value suitable for
1717
// [ListResourceServerStream.Results]. It yields a single result that contains
1818
// the given error diagnostics.
19-
func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic) (*tfprotov6.ListResourceServerStream, diag.Diagnostics) {
19+
func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic) (*tfprotov6.ListResourceServerStream, error) {
2020
protoDiags := toproto6.Diagnostics(ctx, diags)
2121
return &tfprotov6.ListResourceServerStream{
2222
Results: func(push func(tfprotov6.ListResourceResult) bool) {
@@ -25,7 +25,7 @@ func ListRequestErrorDiagnostics(ctx context.Context, diags ...diag.Diagnostic)
2525
}, nil
2626
}
2727

28-
func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov6.ListResourceRequest) (*tfprotov6.ListResourceServerStream, diag.Diagnostics) {
28+
func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov6.ListResourceRequest) (*tfprotov6.ListResourceServerStream, error) {
2929
protoStream := &tfprotov6.ListResourceServerStream{Results: tfprotov6.NoListResults}
3030
allDiags := diag.Diagnostics{}
3131

@@ -68,10 +68,7 @@ func (s *Server) ListResource(ctx context.Context, protoReq *tfprotov6.ListResou
6868
}
6969
stream := &fwserver.ListResultsStream{}
7070

71-
err := s.FrameworkServer.ListResource(ctx, req, stream)
72-
if err != nil {
73-
return protoStream, err
74-
}
71+
s.FrameworkServer.ListResource(ctx, req, stream)
7572

7673
protoStream.Results = func(push func(tfprotov6.ListResourceResult) bool) {
7774
for result := range stream.Results {

internal/proto6server/server_listresource_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func TestServerListResource(t *testing.T) {
193193
testCases := map[string]struct {
194194
server *Server
195195
request *tfprotov6.ListResourceRequest
196-
expectedError diag.Diagnostics
196+
expectedError error
197197
expectedDiagnostics diag.Diagnostics
198198
expectedResults []tfprotov6.ListResourceResult
199199
}{

0 commit comments

Comments
 (0)