Skip to content

Commit 944dfaf

Browse files
authored
List Implementation - add interface and update existing list resources (#31029)
1 parent 0ba9dde commit 944dfaf

File tree

10 files changed

+129
-126
lines changed

10 files changed

+129
-126
lines changed

internal/provider/framework/provider.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,13 @@ func (p *azureRmFrameworkProvider) ListResources(_ context.Context) []func() lis
591591
var output []func() list.ListResource
592592

593593
for _, service := range pluginsdkprovider.SupportedFrameworkServices() {
594-
output = append(output, service.ListResources()...)
594+
for _, l := range service.ListResources() {
595+
fwl := sdk.FrameworkListResourceWrapper{
596+
ResourceMetadata: sdk.ResourceMetadata{},
597+
FrameworkListWrappedResource: l,
598+
}
599+
output = append(output, fwl.Resource())
600+
}
595601
}
596602

597603
return output

internal/sdk/framework_service_registration.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package sdk
66
import (
77
"github.com/hashicorp/terraform-plugin-framework/action"
88
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
9-
"github.com/hashicorp/terraform-plugin-framework/list"
109
)
1110

1211
type FrameworkServiceRegistration interface {
@@ -18,5 +17,5 @@ type FrameworkServiceRegistration interface {
1817

1918
EphemeralResources() []func() ephemeral.EphemeralResource
2019

21-
ListResources() []func() list.ListResource
20+
ListResources() []FrameworkListWrappedResource
2221
}

internal/sdk/list_resource.go

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,108 @@
44
package sdk
55

66
import (
7+
"context"
8+
"time"
9+
10+
"github.com/hashicorp/go-azure-helpers/framework/typehelpers"
11+
"github.com/hashicorp/go-azure-helpers/resourcemanager/resourcegroups"
712
"github.com/hashicorp/terraform-plugin-framework/list"
13+
listschema "github.com/hashicorp/terraform-plugin-framework/list/schema"
814
"github.com/hashicorp/terraform-plugin-framework/resource"
9-
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
10-
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
15+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
16+
"github.com/hashicorp/terraform-plugin-framework/types"
17+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
18+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
1119
)
1220

13-
type ListResource interface {
14-
list.ListResourceWithConfigure
21+
// FrameworkListResourceWrapper presents an interface to simplify the implementations for List Resources
22+
// it handles boilerplate code, and provides sensible defaults for the Azure Search APIs
23+
type FrameworkListResourceWrapper struct {
24+
ResourceMetadata
25+
26+
FrameworkListWrappedResource
1527
}
1628

17-
type ListResourceWithRawV5Schemas interface {
18-
ListResource
29+
type DefaultListModel struct {
30+
ResourceGroupName types.String `tfsdk:"resource_group_name"`
31+
SubscriptionId types.String `tfsdk:"subscription_id"`
32+
}
1933

20-
list.ListResourceWithRawV5Schemas
34+
func (r *FrameworkListResourceWrapper) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
35+
r.FrameworkListWrappedResource.Metadata(ctx, request, response)
2136
}
2237

23-
type ListResourceMetadata struct {
24-
Client *clients.Client
38+
func (r *FrameworkListResourceWrapper) ListResourceConfigSchema(ctx context.Context, request list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) {
39+
if l, ok := r.FrameworkListWrappedResource.(FrameworkListWrappedResourceWithConfig); ok {
40+
l.ListResourceConfigSchema(ctx, request, response)
41+
return
42+
}
43+
44+
// most resources default to RG and Subscription, so unless we need to customise that above, we can default it here.
45+
response.Schema = listschema.Schema{
46+
Attributes: map[string]listschema.Attribute{
47+
"resource_group_name": listschema.StringAttribute{
48+
Optional: true,
49+
Validators: []validator.String{
50+
typehelpers.WrappedStringValidator{
51+
Func: resourcegroups.ValidateName,
52+
},
53+
},
54+
},
55+
"subscription_id": listschema.StringAttribute{
56+
Optional: true,
57+
Validators: []validator.String{
58+
typehelpers.WrappedStringValidator{
59+
Func: validation.IsUUID,
60+
},
61+
},
62+
},
63+
},
64+
}
65+
}
2566

26-
SubscriptionId string
67+
func (r *FrameworkListResourceWrapper) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream) {
68+
ctx, cancel := context.WithTimeout(ctx, time.Minute*60) // TODO - Custom Timeouts
69+
defer cancel()
2770

28-
Features features.UserFeatures
71+
r.FrameworkListWrappedResource.List(ctx, request, stream, r.ResourceMetadata)
2972
}
3073

31-
func (r *ListResourceMetadata) Defaults(request resource.ConfigureRequest, response *resource.ConfigureResponse) {
32-
if request.ProviderData == nil {
33-
return
34-
}
74+
func (r *FrameworkListResourceWrapper) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, response *list.RawV5SchemaResponse) {
75+
res := r.FrameworkListWrappedResource.ResourceFunc()
76+
response.ProtoV5Schema = res.ProtoSchema(ctx)()
77+
response.ProtoV5IdentitySchema = res.ProtoIdentitySchema(ctx)()
78+
}
3579

36-
c, ok := request.ProviderData.(*clients.Client)
37-
if !ok {
38-
response.Diagnostics.AddError("Client Provider Data Error", "invalid provider data supplied")
39-
return
80+
func (r *FrameworkListResourceWrapper) Resource() func() list.ListResource {
81+
return func() list.ListResource {
82+
return r
4083
}
84+
}
85+
86+
func (r *FrameworkListResourceWrapper) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
87+
r.Defaults(request, response)
88+
}
89+
90+
var (
91+
_ list.ListResourceWithConfigure = &FrameworkListResourceWrapper{}
92+
_ list.ListResourceWithRawV5Schemas = &FrameworkListResourceWrapper{}
93+
)
94+
95+
type FrameworkListWrappedResource interface {
96+
Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse)
97+
98+
List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream, metadata ResourceMetadata)
99+
100+
// RawV5Schemas(ctx context.Context, request list.RawV5SchemaRequest, response *list.RawV5SchemaResponse)
101+
102+
// ResourceFunc exposes the PluginSDKv2 resource function so that the RawV5Schema can be extracted
103+
// This should call the function that is used to register the resource in the provider that this List resource represents
104+
ResourceFunc() *pluginsdk.Resource
105+
}
106+
107+
type FrameworkListWrappedResourceWithConfig interface {
108+
FrameworkListWrappedResource
41109

42-
r.Client = c
43-
r.SubscriptionId = c.Account.SubscriptionId
44-
r.Features = c.Features
110+
ListResourceConfigSchema(ctx context.Context, request list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse)
45111
}

internal/services/compute/registration.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package compute
66
import (
77
"github.com/hashicorp/terraform-plugin-framework/action"
88
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
9-
"github.com/hashicorp/terraform-plugin-framework/list"
109
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
1110
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
1211
)
@@ -126,6 +125,6 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource
126125
return []func() ephemeral.EphemeralResource{}
127126
}
128127

129-
func (r Registration) ListResources() []func() list.ListResource {
130-
return []func() list.ListResource{}
128+
func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
129+
return []sdk.FrameworkListWrappedResource{}
131130
}

internal/services/keyvault/registration.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package keyvault
66
import (
77
"github.com/hashicorp/terraform-plugin-framework/action"
88
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
9-
"github.com/hashicorp/terraform-plugin-framework/list"
109
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
1110
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
1211
)
@@ -95,6 +94,6 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource
9594
}
9695
}
9796

98-
func (r Registration) ListResources() []func() list.ListResource {
99-
return []func() list.ListResource{}
97+
func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
98+
return []sdk.FrameworkListWrappedResource{}
10099
}

internal/services/network/registration.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package network
66
import (
77
"github.com/hashicorp/terraform-plugin-framework/action"
88
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
9-
"github.com/hashicorp/terraform-plugin-framework/list"
109
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
1110
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
1211
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
@@ -198,9 +197,9 @@ func (r Registration) Actions() []func() action.Action {
198197
return []func() action.Action{}
199198
}
200199

201-
func (r Registration) ListResources() []func() list.ListResource {
202-
return []func() list.ListResource{
203-
NewVirtualNetworkListResource,
200+
func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
201+
return []sdk.FrameworkListWrappedResource{
202+
VirtualNetworkListResource{},
204203
}
205204
}
206205

internal/services/network/virtual_network_resource_list.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package network
66
import (
77
"context"
88
"fmt"
9-
"time"
109

1110
"github.com/hashicorp/go-azure-helpers/framework/typehelpers"
1211
"github.com/hashicorp/go-azure-helpers/lang/pointer"
@@ -19,33 +18,26 @@ import (
1918
"github.com/hashicorp/terraform-plugin-framework/types"
2019
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
2120
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
21+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
2222
)
2323

24-
type VirtualNetworkListResource struct {
25-
sdk.ListResourceMetadata
24+
type VirtualNetworkListResource struct{}
25+
26+
func (r VirtualNetworkListResource) ResourceFunc() *pluginsdk.Resource {
27+
return resourceVirtualNetwork()
2628
}
2729

28-
var _ sdk.ListResourceWithRawV5Schemas = &VirtualNetworkListResource{}
30+
var _ sdk.FrameworkListWrappedResource = &VirtualNetworkListResource{}
2931

3032
type VirtualNetworkListModel struct {
3133
ResourceGroupName types.String `tfsdk:"resource_group_name"`
3234
}
3335

34-
func NewVirtualNetworkListResource() list.ListResource {
35-
return &VirtualNetworkListResource{}
36-
}
37-
38-
func (r *VirtualNetworkListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) {
36+
func (r VirtualNetworkListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) {
3937
response.TypeName = VirtualNetworkResourceName
4038
}
4139

42-
func (r *VirtualNetworkListResource) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, response *list.RawV5SchemaResponse) {
43-
res := resourceVirtualNetwork()
44-
response.ProtoV5Schema = res.ProtoSchema(ctx)()
45-
response.ProtoV5IdentitySchema = res.ProtoIdentitySchema(ctx)()
46-
}
47-
48-
func (r *VirtualNetworkListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) {
40+
func (r VirtualNetworkListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) {
4941
response.Schema = listschema.Schema{
5042
Attributes: map[string]listschema.Attribute{
5143
"resource_group_name": listschema.StringAttribute{
@@ -60,10 +52,8 @@ func (r *VirtualNetworkListResource) ListResourceConfigSchema(_ context.Context,
6052
}
6153
}
6254

63-
func (r *VirtualNetworkListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream) {
64-
client := r.Client.Network.VirtualNetworks
65-
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute) // TODO - Is this long enough for a list call?
66-
defer cancel()
55+
func (r VirtualNetworkListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream, metadata sdk.ResourceMetadata) {
56+
client := metadata.Client.Network.VirtualNetworks
6757

6858
var data VirtualNetworkListModel
6959

@@ -73,7 +63,7 @@ func (r *VirtualNetworkListResource) List(ctx context.Context, request list.List
7363
return
7464
}
7565

76-
resp, err := client.ListComplete(ctx, commonids.NewResourceGroupID(r.SubscriptionId, data.ResourceGroupName.ValueString()))
66+
resp, err := client.ListComplete(ctx, commonids.NewResourceGroupID(metadata.SubscriptionId, data.ResourceGroupName.ValueString()))
7767
if err != nil {
7868
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing %s", VirtualNetworkResourceName), err)
7969
return
@@ -133,7 +123,3 @@ func (r *VirtualNetworkListResource) List(ctx context.Context, request list.List
133123
}
134124
}
135125
}
136-
137-
func (r *VirtualNetworkListResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
138-
r.Defaults(request, response)
139-
}

internal/services/storage/registration.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package storage
66
import (
77
"github.com/hashicorp/terraform-plugin-framework/action"
88
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
9-
"github.com/hashicorp/terraform-plugin-framework/list"
109
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
1110
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
1211
)
@@ -112,8 +111,8 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource
112111
return []func() ephemeral.EphemeralResource{}
113112
}
114113

115-
func (r Registration) ListResources() []func() list.ListResource {
116-
return []func() list.ListResource{
117-
NewStorageAccountListResource,
114+
func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
115+
return []sdk.FrameworkListWrappedResource{
116+
StorageAccountListResource{},
118117
}
119118
}

0 commit comments

Comments
 (0)