Skip to content

Commit 9b35052

Browse files
committed
Add ListResource to testsdk
1 parent ad8caea commit 9b35052

File tree

8 files changed

+178
-9
lines changed

8 files changed

+178
-9
lines changed

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/hashicorp/logutils v1.0.0
1616
github.com/hashicorp/terraform-exec v0.23.0
1717
github.com/hashicorp/terraform-json v0.25.0
18-
github.com/hashicorp/terraform-plugin-go v0.28.0
18+
github.com/hashicorp/terraform-plugin-go v0.29.0-alpha.1
1919
github.com/hashicorp/terraform-plugin-log v0.9.0
2020
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0
2121
github.com/mitchellh/go-testing-interface v1.14.1
@@ -36,7 +36,7 @@ require (
3636
github.com/hashicorp/go-multierror v1.1.1 // indirect
3737
github.com/hashicorp/go-plugin v1.6.3 // indirect
3838
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
39-
github.com/hashicorp/terraform-registry-address v0.2.5 // indirect
39+
github.com/hashicorp/terraform-registry-address v0.3.0 // indirect
4040
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
4141
github.com/hashicorp/yamux v0.1.1 // indirect
4242
github.com/mattn/go-colorable v0.1.13 // indirect
@@ -50,13 +50,13 @@ require (
5050
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
5151
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
5252
golang.org/x/mod v0.25.0 // indirect
53-
golang.org/x/net v0.40.0 // indirect
53+
golang.org/x/net v0.41.0 // indirect
5454
golang.org/x/sync v0.15.0 // indirect
5555
golang.org/x/sys v0.33.0 // indirect
5656
golang.org/x/text v0.26.0 // indirect
5757
golang.org/x/tools v0.33.0 // indirect
5858
google.golang.org/appengine v1.6.8 // indirect
59-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
60-
google.golang.org/grpc v1.72.1 // indirect
59+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
60+
google.golang.org/grpc v1.73.0 // indirect
6161
google.golang.org/protobuf v1.36.6 // indirect
6262
)

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,15 @@ github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGo
8282
github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc=
8383
github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA=
8484
github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o=
85+
github.com/hashicorp/terraform-plugin-go v0.29.0-alpha.1 h1:ZId6oWG8VTKhz207quE/Xh8a3HuoLtM/QkcSSypekIQ=
86+
github.com/hashicorp/terraform-plugin-go v0.29.0-alpha.1/go.mod h1:hL//wLEfYo0YVt0TC/VLzia/ADQQto3HEm4/jX2gkdY=
8587
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
8688
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
8789
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM=
8890
github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA=
8991
github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M=
9092
github.com/hashicorp/terraform-registry-address v0.2.5/go.mod h1:PpzXWINwB5kuVS5CA7m1+eO2f1jKb5ZDIxrOPfpnGkg=
93+
github.com/hashicorp/terraform-registry-address v0.3.0/go.mod h1:jRGCMiLaY9zii3GLC7hqpSnwhfnCN5yzvY0hh4iCGbM=
9194
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
9295
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
9396
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
@@ -175,6 +178,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
175178
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
176179
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
177180
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
181+
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
178182
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
179183
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
180184
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -216,8 +220,10 @@ google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAs
216220
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
217221
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
218222
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
223+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
219224
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
220225
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
226+
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
221227
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
222228
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
223229
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package testprovider
5+
6+
import (
7+
"context"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
10+
)
11+
12+
var _ list.ListResource = ListResource{}
13+
14+
type ListResource struct {
15+
SchemaResponse *list.SchemaResponse
16+
ListResultsStream *list.ListResultsStream
17+
ValidateListConfigResponse *list.ValidateListConfigResponse
18+
}
19+
20+
func (r ListResource) Schema(ctx context.Context, req list.SchemaRequest, resp *list.SchemaResponse) {
21+
if r.SchemaResponse != nil {
22+
resp.Diagnostics = r.SchemaResponse.Diagnostics
23+
resp.Schema = r.SchemaResponse.Schema
24+
}
25+
}
26+
func (r ListResource) List(ctx context.Context, req list.ListRequest, stream *list.ListResultsStream) {
27+
stream.Results = r.ListResultsStream.Results
28+
}

internal/testing/testprovider/provider.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
1010
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource"
11+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
1112
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/provider"
1213
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource"
1314
)
@@ -19,6 +20,7 @@ var _ provider.Provider = Provider{}
1920
type Provider struct {
2021
ConfigureResponse *provider.ConfigureResponse
2122
DataSources map[string]DataSource
23+
ListResources map[string]ListResource
2224
Resources map[string]Resource
2325
SchemaResponse *provider.SchemaResponse
2426
StopResponse *provider.StopResponse
@@ -41,6 +43,16 @@ func (p Provider) DataSourcesMap() map[string]datasource.DataSource {
4143
return datasources
4244
}
4345

46+
func (p Provider) ListResourcesMap() map[string]list.ListResource {
47+
listResources := make(map[string]list.ListResource, len(p.ListResources))
48+
49+
for typeName, d := range p.ListResources {
50+
listResources[typeName] = d
51+
}
52+
53+
return listResources
54+
}
55+
4456
func (p Provider) ResourcesMap() map[string]resource.Resource {
4557
resources := make(map[string]resource.Resource, len(p.Resources))
4658

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package list
2+
3+
import (
4+
"context"
5+
"iter"
6+
7+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
8+
)
9+
10+
type ListResource interface {
11+
Schema(context.Context, SchemaRequest, *SchemaResponse)
12+
List(context.Context, ListRequest, *ListResultsStream)
13+
}
14+
15+
type ListRequest struct {
16+
}
17+
18+
type ListResultsStream struct {
19+
Results iter.Seq[ListResult]
20+
}
21+
22+
type ListResult struct {
23+
}
24+
25+
type ValidateListConfigResponse struct {
26+
}
27+
28+
type SchemaRequest struct{}
29+
30+
type SchemaResponse struct {
31+
Diagnostics []*tfprotov6.Diagnostic
32+
Schema *tfprotov6.Schema
33+
}

internal/testing/testsdk/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import (
99
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
1010
"github.com/hashicorp/terraform-plugin-go/tftypes"
1111
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource"
12+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
1213
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource"
1314
)
1415

1516
type Provider interface {
1617
Configure(context.Context, ConfigureRequest, *ConfigureResponse)
1718
DataSourcesMap() map[string]datasource.DataSource
19+
ListResourcesMap() map[string]list.ListResource
1820
ResourcesMap() map[string]resource.Resource
1921
Schema(context.Context, SchemaRequest, *SchemaResponse)
2022
Stop(context.Context, StopRequest, *StopResponse)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package providerserver
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
8+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
9+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/provider"
10+
)
11+
12+
func ProviderListResource(p provider.Provider, typeName string) (list.ListResource, *tfprotov6.Diagnostic) {
13+
r, ok := p.ListResourcesMap()[typeName]
14+
15+
if !ok {
16+
return nil, &tfprotov6.Diagnostic{
17+
Severity: tfprotov6.DiagnosticSeverityError,
18+
Summary: "Missing List Resource Type",
19+
Detail: "The provider does not define the list resource type: " + typeName,
20+
}
21+
}
22+
23+
return r, nil
24+
}

internal/testing/testsdk/providerserver/providerserver.go

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import (
1212
"github.com/hashicorp/terraform-plugin-go/tftypes"
1313

1414
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource"
15+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/list"
1516
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/provider"
1617
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource"
1718
)
1819

1920
var _ tfprotov6.ProviderServer = ProviderServer{}
21+
var _ tfprotov6.ProviderServerWithListResource = ProviderServer{}
2022

2123
// NewProviderServer returns a lightweight protocol version 6 provider server
2224
// for consumption with ProtoV6ProviderFactories.
@@ -86,6 +88,12 @@ func (s ProviderServer) GetMetadata(ctx context.Context, request *tfprotov6.GetM
8688
})
8789
}
8890

91+
for typeName := range s.Provider.ListResourcesMap() {
92+
resp.ListResources = append(resp.ListResources, tfprotov6.ListResourceMetadata{
93+
TypeName: typeName,
94+
})
95+
}
96+
8997
for typeName := range s.Provider.ResourcesMap() {
9098
resp.Resources = append(resp.Resources, tfprotov6.ResourceMetadata{
9199
TypeName: typeName,
@@ -304,10 +312,11 @@ func (s ProviderServer) GetProviderSchema(ctx context.Context, req *tfprotov6.Ge
304312
Functions: map[string]*tfprotov6.Function{},
305313
EphemeralResourceSchemas: map[string]*tfprotov6.Schema{},
306314

307-
DataSourceSchemas: map[string]*tfprotov6.Schema{},
308-
Diagnostics: providerResp.Diagnostics,
309-
Provider: providerResp.Schema,
310-
ResourceSchemas: map[string]*tfprotov6.Schema{},
315+
DataSourceSchemas: map[string]*tfprotov6.Schema{},
316+
Diagnostics: providerResp.Diagnostics,
317+
ListResourceSchemas: map[string]*tfprotov6.Schema{},
318+
Provider: providerResp.Schema,
319+
ResourceSchemas: map[string]*tfprotov6.Schema{},
311320
ServerCapabilities: &tfprotov6.ServerCapabilities{
312321
PlanDestroy: true,
313322
},
@@ -324,6 +333,17 @@ func (s ProviderServer) GetProviderSchema(ctx context.Context, req *tfprotov6.Ge
324333
resp.DataSourceSchemas[typeName] = schemaResp.Schema
325334
}
326335

336+
for typeName, l := range s.Provider.ListResourcesMap() {
337+
schemaReq := list.SchemaRequest{}
338+
schemaResp := &list.SchemaResponse{}
339+
340+
l.Schema(ctx, schemaReq, schemaResp)
341+
342+
resp.Diagnostics = append(resp.Diagnostics, schemaResp.Diagnostics...)
343+
344+
resp.ListResourceSchemas[typeName] = schemaResp.Schema
345+
}
346+
327347
for typeName, r := range s.Provider.ResourcesMap() {
328348
schemaReq := resource.SchemaRequest{}
329349
schemaResp := &resource.SchemaResponse{}
@@ -1017,3 +1037,47 @@ func (s ProviderServer) CloseEphemeralResource(ctx context.Context, req *tfproto
10171037
func (s ProviderServer) ValidateEphemeralResourceConfig(ctx context.Context, req *tfprotov6.ValidateEphemeralResourceConfigRequest) (*tfprotov6.ValidateEphemeralResourceConfigResponse, error) {
10181038
return &tfprotov6.ValidateEphemeralResourceConfigResponse{}, nil
10191039
}
1040+
1041+
func (s ProviderServer) ListResource(ctx context.Context, req *tfprotov6.ListResourceRequest) (*tfprotov6.ListResourceServerStream, error) {
1042+
resp := &tfprotov6.ListResourceServerStream{}
1043+
1044+
// Copy over identity if it's supported
1045+
identitySchemaReq := resource.IdentitySchemaRequest{}
1046+
identitySchemaResp := &resource.IdentitySchemaResponse{}
1047+
1048+
r, _ := ProviderResource(s.Provider, req.TypeName)
1049+
// TODO: diag
1050+
r.IdentitySchema(ctx, identitySchemaReq, identitySchemaResp)
1051+
1052+
results := func(push func(tfprotov6.ListResourceResult) bool) {
1053+
_, diag := ProviderListResource(s.Provider, req.TypeName)
1054+
if diag != nil {
1055+
push(tfprotov6.ListResourceResult{Diagnostics: []*tfprotov6.Diagnostic{diag}})
1056+
return
1057+
}
1058+
1059+
identityData := tftypes.NewValue(
1060+
tftypes.Object{
1061+
AttributeTypes: map[string]tftypes.Type{
1062+
"id": tftypes.String,
1063+
},
1064+
},
1065+
map[string]tftypes.Value{
1066+
"id": tftypes.NewValue(tftypes.String, "westeurope/somevalue"),
1067+
},
1068+
)
1069+
identity, _ := IdentityValuetoDynamicValue(identitySchemaResp.Schema, identityData) // TODO: diag
1070+
push(tfprotov6.ListResourceResult{
1071+
Identity: &tfprotov6.ResourceIdentityData{
1072+
IdentityData: identity,
1073+
},
1074+
})
1075+
}
1076+
1077+
resp.Results = results
1078+
return resp, nil
1079+
}
1080+
1081+
func (s ProviderServer) ValidateListResourceConfig(ctx context.Context, req *tfprotov6.ValidateListResourceConfigRequest) (*tfprotov6.ValidateListResourceConfigResponse, error) {
1082+
return &tfprotov6.ValidateListResourceConfigResponse{}, nil
1083+
}

0 commit comments

Comments
 (0)