Skip to content

Commit 5f48f41

Browse files
committed
Update fwserver GetMetadata to cache ListResources
1 parent ce1fee3 commit 5f48f41

File tree

4 files changed

+129
-24
lines changed

4 files changed

+129
-24
lines changed

internal/fwserver/server.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,3 +819,79 @@ func (s *Server) ResourceIdentitySchemas(ctx context.Context) (map[string]fwsche
819819

820820
return resourceIdentitySchemas, diags
821821
}
822+
823+
// ListResourceFuncs returns a map of ListResource functions. The results are
824+
// cached on first use.
825+
func (s *Server) ListResourceFuncs(ctx context.Context) (map[string]func() list.ListResource, diag.Diagnostics) {
826+
provider, ok := s.Provider.(provider.ProviderWithListResources)
827+
if !ok {
828+
return nil, nil
829+
}
830+
831+
logging.FrameworkTrace(ctx, "Checking ListResourceTypes lock")
832+
s.listResourceTypesMutex.Lock()
833+
defer s.listResourceTypesMutex.Unlock()
834+
835+
if s.listResourceFuncs != nil {
836+
return s.listResourceFuncs, s.resourceTypesDiags
837+
}
838+
839+
providerTypeName := s.ProviderTypeName(ctx)
840+
s.listResourceFuncs = make(map[string]func() list.ListResource)
841+
842+
logging.FrameworkTrace(ctx, "Calling provider defined ListResources")
843+
listResourceFuncSlice := provider.ListResources(ctx)
844+
logging.FrameworkTrace(ctx, "Called provider defined ListResources")
845+
846+
for _, listResourceFunc := range listResourceFuncSlice {
847+
listResource := listResourceFunc()
848+
849+
metadataReq := resource.MetadataRequest{
850+
ProviderTypeName: providerTypeName,
851+
}
852+
metadataResp := resource.MetadataResponse{}
853+
listResource.Metadata(ctx, metadataReq, &metadataResp)
854+
855+
typeName := metadataResp.TypeName
856+
if typeName == "" {
857+
s.listResourceTypesDiags.AddError(
858+
"ListResource Type Name Missing",
859+
fmt.Sprintf("The %T ListResource returned an empty string from the Metadata method. ", listResource)+
860+
"This is always an issue with the provider and should be reported to the provider developers.",
861+
)
862+
continue
863+
}
864+
865+
logging.FrameworkTrace(ctx, "Found resource type", map[string]interface{}{logging.KeyListResourceType: typeName})
866+
867+
if _, ok := s.listResourceFuncs[typeName]; ok {
868+
s.listResourceTypesDiags.AddError(
869+
"Duplicate ListResource Type Defined",
870+
fmt.Sprintf("The %s ListResource type name was returned for multiple resources. ", typeName)+
871+
"ListResource type names must be unique. "+
872+
"This is always an issue with the provider and should be reported to the provider developers.",
873+
)
874+
continue
875+
}
876+
877+
s.listResourceFuncs[typeName] = listResourceFunc
878+
}
879+
880+
return s.listResourceFuncs, s.resourceTypesDiags
881+
}
882+
883+
// ListResourceMetadatas returns a slice of ListResourceMetadata for the GetMetadata
884+
// RPC.
885+
func (s *Server) ListResourceMetadatas(ctx context.Context) ([]ListResourceMetadata, diag.Diagnostics) {
886+
resourceFuncs, diags := s.ListResourceFuncs(ctx)
887+
888+
resourceMetadatas := make([]ListResourceMetadata, 0, len(resourceFuncs))
889+
890+
for typeName := range resourceFuncs {
891+
resourceMetadatas = append(resourceMetadatas, ListResourceMetadata{
892+
TypeName: typeName,
893+
})
894+
}
895+
896+
return resourceMetadatas, diags
897+
}

internal/fwserver/server_getmetadata.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type GetMetadataResponse struct {
2020
Diagnostics diag.Diagnostics
2121
EphemeralResources []EphemeralResourceMetadata
2222
Functions []FunctionMetadata
23+
ListResources []ListResourceMetadata
2324
Resources []ResourceMetadata
2425
ServerCapabilities *ServerCapabilities
2526
}
@@ -52,28 +53,36 @@ type ResourceMetadata struct {
5253
TypeName string
5354
}
5455

56+
// ListResourceMetadata is the framework server equivalent of the
57+
// tfprotov5.ListResourceMetadata and tfprotov6.ListResourceMetadata types.
58+
type ListResourceMetadata struct {
59+
// TypeName is the name of the list resource.
60+
TypeName string
61+
}
62+
5563
// GetMetadata implements the framework server GetMetadata RPC.
5664
func (s *Server) GetMetadata(ctx context.Context, req *GetMetadataRequest, resp *GetMetadataResponse) {
5765
resp.DataSources = []DataSourceMetadata{}
5866
resp.EphemeralResources = []EphemeralResourceMetadata{}
5967
resp.Functions = []FunctionMetadata{}
68+
resp.ListResources = []ListResourceMetadata{}
6069
resp.Resources = []ResourceMetadata{}
70+
6171
resp.ServerCapabilities = s.ServerCapabilities()
6272

6373
datasourceMetadatas, diags := s.DataSourceMetadatas(ctx)
64-
6574
resp.Diagnostics.Append(diags...)
6675

6776
ephemeralResourceMetadatas, diags := s.EphemeralResourceMetadatas(ctx)
68-
6977
resp.Diagnostics.Append(diags...)
7078

7179
functionMetadatas, diags := s.FunctionMetadatas(ctx)
72-
7380
resp.Diagnostics.Append(diags...)
7481

7582
resourceMetadatas, diags := s.ResourceMetadatas(ctx)
83+
resp.Diagnostics.Append(diags...)
7684

85+
listResourceMetadatas, diags := s.ListResourceMetadatas(ctx)
7786
resp.Diagnostics.Append(diags...)
7887

7988
if resp.Diagnostics.HasError() {
@@ -83,5 +92,6 @@ func (s *Server) GetMetadata(ctx context.Context, req *GetMetadataRequest, resp
8392
resp.DataSources = datasourceMetadatas
8493
resp.EphemeralResources = ephemeralResourceMetadatas
8594
resp.Functions = functionMetadatas
95+
resp.ListResources = listResourceMetadatas
8696
resp.Resources = resourceMetadatas
8797
}

internal/fwserver/server_getmetadata_test.go

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ func TestServerGetMetadata(t *testing.T) {
3636
DataSources: []fwserver.DataSourceMetadata{},
3737
EphemeralResources: []fwserver.EphemeralResourceMetadata{},
3838
Functions: []fwserver.FunctionMetadata{},
39+
ListResources: []fwserver.ListResourceMetadata{},
3940
Resources: []fwserver.ResourceMetadata{},
4041
ServerCapabilities: &fwserver.ServerCapabilities{
4142
GetProviderSchemaOptional: true,
@@ -79,6 +80,7 @@ func TestServerGetMetadata(t *testing.T) {
7980
},
8081
EphemeralResources: []fwserver.EphemeralResourceMetadata{},
8182
Functions: []fwserver.FunctionMetadata{},
83+
ListResources: []fwserver.ListResourceMetadata{},
8284
Resources: []fwserver.ResourceMetadata{},
8385
ServerCapabilities: &fwserver.ServerCapabilities{
8486
GetProviderSchemaOptional: true,
@@ -122,8 +124,9 @@ func TestServerGetMetadata(t *testing.T) {
122124
"This is always an issue with the provider and should be reported to the provider developers.",
123125
),
124126
},
125-
Functions: []fwserver.FunctionMetadata{},
126-
Resources: []fwserver.ResourceMetadata{},
127+
Functions: []fwserver.FunctionMetadata{},
128+
ListResources: []fwserver.ListResourceMetadata{},
129+
Resources: []fwserver.ResourceMetadata{},
127130
ServerCapabilities: &fwserver.ServerCapabilities{
128131
GetProviderSchemaOptional: true,
129132
MoveResourceState: true,
@@ -158,8 +161,9 @@ func TestServerGetMetadata(t *testing.T) {
158161
"This is always an issue with the provider and should be reported to the provider developers.",
159162
),
160163
},
161-
Functions: []fwserver.FunctionMetadata{},
162-
Resources: []fwserver.ResourceMetadata{},
164+
Functions: []fwserver.FunctionMetadata{},
165+
ListResources: []fwserver.ListResourceMetadata{},
166+
Resources: []fwserver.ResourceMetadata{},
163167
ServerCapabilities: &fwserver.ServerCapabilities{
164168
GetProviderSchemaOptional: true,
165169
MoveResourceState: true,
@@ -195,6 +199,7 @@ func TestServerGetMetadata(t *testing.T) {
195199
},
196200
EphemeralResources: []fwserver.EphemeralResourceMetadata{},
197201
Functions: []fwserver.FunctionMetadata{},
202+
ListResources: []fwserver.ListResourceMetadata{},
198203
Resources: []fwserver.ResourceMetadata{},
199204
ServerCapabilities: &fwserver.ServerCapabilities{
200205
GetProviderSchemaOptional: true,
@@ -237,8 +242,9 @@ func TestServerGetMetadata(t *testing.T) {
237242
TypeName: "test_ephemeral_resource2",
238243
},
239244
},
240-
Functions: []fwserver.FunctionMetadata{},
241-
Resources: []fwserver.ResourceMetadata{},
245+
Functions: []fwserver.FunctionMetadata{},
246+
ListResources: []fwserver.ListResourceMetadata{},
247+
Resources: []fwserver.ResourceMetadata{},
242248
ServerCapabilities: &fwserver.ServerCapabilities{
243249
GetProviderSchemaOptional: true,
244250
MoveResourceState: true,
@@ -281,8 +287,9 @@ func TestServerGetMetadata(t *testing.T) {
281287
"This is always an issue with the provider and should be reported to the provider developers.",
282288
),
283289
},
284-
Functions: []fwserver.FunctionMetadata{},
285-
Resources: []fwserver.ResourceMetadata{},
290+
Functions: []fwserver.FunctionMetadata{},
291+
ListResources: []fwserver.ListResourceMetadata{},
292+
Resources: []fwserver.ResourceMetadata{},
286293
ServerCapabilities: &fwserver.ServerCapabilities{
287294
GetProviderSchemaOptional: true,
288295
MoveResourceState: true,
@@ -317,8 +324,9 @@ func TestServerGetMetadata(t *testing.T) {
317324
"This is always an issue with the provider and should be reported to the provider developers.",
318325
),
319326
},
320-
Functions: []fwserver.FunctionMetadata{},
321-
Resources: []fwserver.ResourceMetadata{},
327+
Functions: []fwserver.FunctionMetadata{},
328+
ListResources: []fwserver.ListResourceMetadata{},
329+
Resources: []fwserver.ResourceMetadata{},
322330
ServerCapabilities: &fwserver.ServerCapabilities{
323331
GetProviderSchemaOptional: true,
324332
MoveResourceState: true,
@@ -353,8 +361,9 @@ func TestServerGetMetadata(t *testing.T) {
353361
TypeName: "testprovidertype_ephemeral_resource",
354362
},
355363
},
356-
Functions: []fwserver.FunctionMetadata{},
357-
Resources: []fwserver.ResourceMetadata{},
364+
Functions: []fwserver.FunctionMetadata{},
365+
ListResources: []fwserver.ListResourceMetadata{},
366+
Resources: []fwserver.ResourceMetadata{},
358367
ServerCapabilities: &fwserver.ServerCapabilities{
359368
GetProviderSchemaOptional: true,
360369
MoveResourceState: true,
@@ -397,7 +406,8 @@ func TestServerGetMetadata(t *testing.T) {
397406
Name: "function2",
398407
},
399408
},
400-
Resources: []fwserver.ResourceMetadata{},
409+
ListResources: []fwserver.ListResourceMetadata{},
410+
Resources: []fwserver.ResourceMetadata{},
401411
ServerCapabilities: &fwserver.ServerCapabilities{
402412
GetProviderSchemaOptional: true,
403413
MoveResourceState: true,
@@ -440,8 +450,9 @@ func TestServerGetMetadata(t *testing.T) {
440450
"This is always an issue with the provider and should be reported to the provider developers.",
441451
),
442452
},
443-
Functions: []fwserver.FunctionMetadata{},
444-
Resources: []fwserver.ResourceMetadata{},
453+
Functions: []fwserver.FunctionMetadata{},
454+
ListResources: []fwserver.ListResourceMetadata{},
455+
Resources: []fwserver.ResourceMetadata{},
445456
ServerCapabilities: &fwserver.ServerCapabilities{
446457
GetProviderSchemaOptional: true,
447458
MoveResourceState: true,
@@ -476,8 +487,9 @@ func TestServerGetMetadata(t *testing.T) {
476487
"This is always an issue with the provider and should be reported to the provider developers.",
477488
),
478489
},
479-
Functions: []fwserver.FunctionMetadata{},
480-
Resources: []fwserver.ResourceMetadata{},
490+
Functions: []fwserver.FunctionMetadata{},
491+
ListResources: []fwserver.ListResourceMetadata{},
492+
Resources: []fwserver.ResourceMetadata{},
481493
ServerCapabilities: &fwserver.ServerCapabilities{
482494
GetProviderSchemaOptional: true,
483495
MoveResourceState: true,
@@ -513,6 +525,7 @@ func TestServerGetMetadata(t *testing.T) {
513525
DataSources: []fwserver.DataSourceMetadata{},
514526
EphemeralResources: []fwserver.EphemeralResourceMetadata{},
515527
Functions: []fwserver.FunctionMetadata{},
528+
ListResources: []fwserver.ListResourceMetadata{},
516529
Resources: []fwserver.ResourceMetadata{
517530
{
518531
TypeName: "test_resource1",
@@ -563,8 +576,9 @@ func TestServerGetMetadata(t *testing.T) {
563576
"This is always an issue with the provider and should be reported to the provider developers.",
564577
),
565578
},
566-
Functions: []fwserver.FunctionMetadata{},
567-
Resources: []fwserver.ResourceMetadata{},
579+
Functions: []fwserver.FunctionMetadata{},
580+
ListResources: []fwserver.ListResourceMetadata{},
581+
Resources: []fwserver.ResourceMetadata{},
568582
ServerCapabilities: &fwserver.ServerCapabilities{
569583
GetProviderSchemaOptional: true,
570584
MoveResourceState: true,
@@ -599,8 +613,9 @@ func TestServerGetMetadata(t *testing.T) {
599613
"This is always an issue with the provider and should be reported to the provider developers.",
600614
),
601615
},
602-
Functions: []fwserver.FunctionMetadata{},
603-
Resources: []fwserver.ResourceMetadata{},
616+
Functions: []fwserver.FunctionMetadata{},
617+
ListResources: []fwserver.ListResourceMetadata{},
618+
Resources: []fwserver.ResourceMetadata{},
604619
ServerCapabilities: &fwserver.ServerCapabilities{
605620
GetProviderSchemaOptional: true,
606621
MoveResourceState: true,
@@ -632,6 +647,7 @@ func TestServerGetMetadata(t *testing.T) {
632647
DataSources: []fwserver.DataSourceMetadata{},
633648
EphemeralResources: []fwserver.EphemeralResourceMetadata{},
634649
Functions: []fwserver.FunctionMetadata{},
650+
ListResources: []fwserver.ListResourceMetadata{},
635651
Resources: []fwserver.ResourceMetadata{
636652
{
637653
TypeName: "testprovidertype_resource",

internal/logging/keys.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const (
3737
// The type of resource being operated on, such as "random_pet"
3838
KeyResourceType = "tf_resource_type"
3939

40+
// The type of list resource being operated on, such as "random_pet"
41+
KeyListResourceType = "tf_list_resource_type"
42+
4043
// The type of value being operated on, such as "JSONStringValue".
4144
KeyValueType = "tf_value_type"
4245
)

0 commit comments

Comments
 (0)