internal/services/azapi_resource_list_data_source.go (133 lines of code) (raw):
package services
import (
"context"
"fmt"
"strings"
"time"
"github.com/Azure/terraform-provider-azapi/internal/clients"
"github.com/Azure/terraform-provider-azapi/internal/docstrings"
"github.com/Azure/terraform-provider-azapi/internal/retry"
"github.com/Azure/terraform-provider-azapi/internal/services/myvalidator"
"github.com/Azure/terraform-provider-azapi/internal/services/parse"
"github.com/Azure/terraform-provider-azapi/utils"
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
)
type ResourceListDataSourceModel struct {
ID types.String `tfsdk:"id"`
Type types.String `tfsdk:"type"`
ParentID types.String `tfsdk:"parent_id"`
ResponseExportValues types.Dynamic `tfsdk:"response_export_values"`
Output types.Dynamic `tfsdk:"output"`
Timeouts timeouts.Value `tfsdk:"timeouts"`
Retry retry.RetryValue `tfsdk:"retry"`
Headers types.Map `tfsdk:"headers"`
QueryParameters types.Map `tfsdk:"query_parameters"`
}
type ResourceListDataSource struct {
ProviderData *clients.Client
}
var _ datasource.DataSource = &ResourceListDataSource{}
var _ datasource.DataSourceWithConfigure = &ResourceListDataSource{}
func (r *ResourceListDataSource) Configure(ctx context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) {
if v, ok := request.ProviderData.(*clients.Client); ok {
r.ProviderData = v
}
}
func (r *ResourceListDataSource) Metadata(ctx context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) {
response.TypeName = request.ProviderTypeName + "_resource_list"
}
func (r *ResourceListDataSource) Schema(ctx context.Context, request datasource.SchemaRequest, response *datasource.SchemaResponse) {
response.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: docstrings.ID(),
},
"type": schema.StringAttribute{
Required: true,
Validators: []validator.String{
myvalidator.StringIsResourceType(),
},
MarkdownDescription: docstrings.Type(),
},
"parent_id": schema.StringAttribute{
Required: true,
Validators: []validator.String{
myvalidator.StringIsResourceID(),
},
MarkdownDescription: docstrings.ParentID(),
},
"response_export_values": schema.DynamicAttribute{
Optional: true,
MarkdownDescription: docstrings.ResponseExportValuesForResourceList(),
},
"output": schema.DynamicAttribute{
Computed: true,
MarkdownDescription: docstrings.Output("data.azapi_resource_list"),
},
"retry": retry.RetrySchema(ctx),
"headers": schema.MapAttribute{
ElementType: types.StringType,
Optional: true,
MarkdownDescription: "A map of headers to include in the request",
},
"query_parameters": schema.MapAttribute{
ElementType: types.ListType{
ElemType: types.StringType,
},
Optional: true,
MarkdownDescription: "A map of query parameters to include in the request",
},
},
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(ctx, timeouts.Opts{
Read: true,
}),
},
}
}
func (r *ResourceListDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
var model ResourceListDataSourceModel
if response.Diagnostics.Append(request.Config.Get(ctx, &model)...); response.Diagnostics.HasError() {
return
}
readTimeout, diags := model.Timeouts.Read(ctx, 5*time.Minute)
response.Diagnostics.Append(diags...)
if response.Diagnostics.HasError() {
return
}
ctx, cancel := context.WithTimeout(ctx, readTimeout)
defer cancel()
id, err := parse.NewResourceIDSkipScopeValidation("", model.ParentID.ValueString(), model.Type.ValueString())
if err != nil {
response.Diagnostics.AddError("Invalid configuration", err.Error())
return
}
ctx = tflog.SetField(ctx, "resource_id", id.ID())
listUrl := strings.TrimSuffix(id.AzureResourceId, "/")
// Ensure the context deadline has been set before calling ConfigureClientWithCustomRetry().
client := r.ProviderData.ResourceClient.ConfigureClientWithCustomRetry(ctx, model.Retry, false)
responseBody, err := client.List(ctx, listUrl, id.ApiVersion, clients.NewRequestOptions(AsMapOfString(model.Headers), AsMapOfLists(model.QueryParameters)))
if err != nil {
response.Diagnostics.AddError("Failed to list resources", fmt.Sprintf("Failed to list resources, url: %s, error: %s", listUrl, err.Error()))
return
}
model.ID = basetypes.NewStringValue(listUrl)
var defaultOutput interface{}
if !r.ProviderData.Features.DisableDefaultOutput {
defaultOutput = responseBody
defaultOutput = utils.RemoveFields(defaultOutput, volatileFieldList())
}
output, err := buildOutputFromBody(responseBody, model.ResponseExportValues, defaultOutput)
if err != nil {
response.Diagnostics.AddError("Failed to build output", err.Error())
return
}
model.Output = output
response.Diagnostics.Append(response.State.Set(ctx, &model)...)
}