Skip to content

Commit d218892

Browse files
committed
ListResource: null handling
1 parent 9cafd72 commit d218892

File tree

6 files changed

+64
-56
lines changed

6 files changed

+64
-56
lines changed

internal/fwserver/server_listresource.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,15 @@ func processListResult(req list.ListRequest, result list.ListResult) ListResult
127127
return ListResult(result)
128128
}
129129

130-
if result.Identity == nil { // TODO: is result.Identity.Raw.IsNull() a practical concern?
130+
if result.Identity == nil || result.Identity.Raw.IsNull() {
131131
return ListResultError(
132132
"Incomplete List Result",
133133
"The provider did not populate the Identity field in the ListResourceResult. This may be due to an error in the provider's implementation.",
134134
)
135135
}
136136

137137
if req.IncludeResource {
138-
if result.Resource == nil { // TODO: is result.Resource.Raw.IsNull() a practical concern?
138+
if result.Resource == nil || result.Resource.Raw.IsNull() {
139139
result.Diagnostics.AddWarning(
140140
"Incomplete List Result",
141141
"The provider did not populate the Resource field in the ListResourceResult. This may be due to the provider not supporting this functionality or an error in the provider's implementation.",

internal/fwserver/server_listresource_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,38 @@ func TestServerListResource(t *testing.T) {
214214
},
215215
},
216216
},
217+
"error-on-null-resource-identity": {
218+
server: &fwserver.Server{
219+
Provider: &testprovider.Provider{},
220+
},
221+
request: &fwserver.ListRequest{
222+
Config: &tfsdk.Config{},
223+
ListResource: &testprovider.ListResource{
224+
ListMethod: func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
225+
resp.Results = slices.Values([]list.ListResult{
226+
{
227+
Identity: &tfsdk.ResourceIdentity{},
228+
Resource: &tfsdk.Resource{
229+
Schema: testSchema,
230+
Raw: testResourceValue1,
231+
},
232+
DisplayName: "Test Resource 1",
233+
},
234+
})
235+
},
236+
},
237+
},
238+
expectedStreamEvents: []fwserver.ListResult{
239+
{
240+
Diagnostics: diag.Diagnostics{
241+
diag.NewErrorDiagnostic(
242+
"Incomplete List Result",
243+
"The provider did not populate the Identity field in the ListResourceResult. This may be due to an error in the provider's implementation.",
244+
),
245+
},
246+
},
247+
},
248+
},
217249
"warning-on-missing-resource": {
218250
server: &fwserver.Server{
219251
Provider: &testprovider.Provider{},

internal/proto5server/server_listresource_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ func TestServerListResource(t *testing.T) {
106106
continue
107107
}
108108

109-
result := req.ToListResult(ctx, resources[name].ThingResourceIdentity, resources[name], name)
109+
result := req.NewListResult()
110+
result.Identity.Set(ctx, resources[name].ThingResourceIdentity)
111+
result.Resource.Set(ctx, resources[name])
112+
result.DisplayName = name
113+
110114
results = append(results, result)
111115
}
112116
resp.Results = slices.Values(results)
@@ -124,7 +128,9 @@ func TestServerListResource(t *testing.T) {
124128
}
125129

126130
r.ListMethod = func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
127-
result := req.ToListResult(ctx, resources["plateau"].ThingResourceIdentity, nil, "plateau")
131+
result := req.NewListResult()
132+
result.Identity.Set(ctx, resources["plateau"].ThingResourceIdentity)
133+
result.DisplayName = "plateau"
128134

129135
resp.Results = slices.Values([]list.ListResult{result})
130136
}
@@ -264,6 +270,7 @@ func TestServerListResource(t *testing.T) {
264270
{
265271
DisplayName: "plateau",
266272
Identity: expectedResourceIdentities["plateau"],
273+
Resource: &tfprotov5.DynamicValue{MsgPack: []uint8{0xc0}},
267274
Diagnostics: []*tfprotov5.Diagnostic{
268275
{
269276
Severity: tfprotov5.DiagnosticSeverityWarning,

internal/proto6server/server_listresource_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ func TestServerListResource(t *testing.T) {
106106
continue
107107
}
108108

109-
result := req.ToListResult(ctx, resources[name].ThingResourceIdentity, resources[name], name)
109+
result := req.NewListResult()
110+
result.Identity.Set(ctx, resources[name].ThingResourceIdentity)
111+
result.Resource.Set(ctx, resources[name])
112+
result.DisplayName = name
113+
110114
results = append(results, result)
111115
}
112116
resp.Results = slices.Values(results)
@@ -124,7 +128,9 @@ func TestServerListResource(t *testing.T) {
124128
}
125129

126130
r.ListMethod = func(ctx context.Context, req list.ListRequest, resp *list.ListResultsStream) {
127-
result := req.ToListResult(ctx, resources["plateau"].ThingResourceIdentity, nil, "plateau")
131+
result := req.NewListResult()
132+
result.Identity.Set(ctx, resources["plateau"].ThingResourceIdentity)
133+
result.DisplayName = "plateau"
128134

129135
resp.Results = slices.Values([]list.ListResult{result})
130136
}
@@ -264,6 +270,7 @@ func TestServerListResource(t *testing.T) {
264270
{
265271
DisplayName: "plateau",
266272
Identity: expectedResourceIdentities["plateau"],
273+
Resource: &tfprotov6.DynamicValue{MsgPack: []uint8{0xc0}},
267274
Diagnostics: []*tfprotov6.Diagnostic{
268275
{
269276
Severity: tfprotov6.DiagnosticSeverityWarning,

list/list_resource.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,18 @@ type ListRequest struct {
103103
ResourceIdentitySchema fwschema.Schema
104104
}
105105

106+
func (r ListRequest) NewListResult() ListResult {
107+
identity := &tfsdk.ResourceIdentity{Schema: r.ResourceIdentitySchema}
108+
resource := &tfsdk.Resource{Schema: r.ResourceSchema}
109+
110+
return ListResult{
111+
DisplayName: "",
112+
Resource: resource,
113+
Identity: identity,
114+
Diagnostics: diag.Diagnostics{},
115+
}
116+
}
117+
106118
// ListResultsStream represents a streaming response to a [ListRequest]. An
107119
// instance of this struct is supplied as an argument to the provider's
108120
// [ListResource.List] function. The provider should set a Results iterator

list/tosdk.go

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)