-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathdatasource.go
More file actions
248 lines (221 loc) · 8.53 KB
/
datasource.go
File metadata and controls
248 lines (221 loc) · 8.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
package instances
import (
"context"
"fmt"
"net/http"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
edge "github.com/stackitcloud/stackit-sdk-go/services/edge/v1beta1api"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
edgeutils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/edgecloud/utils"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &instancesDataSource{}
)
// DataSourceModel maps the data source schema data.
type DataSourceModel struct {
Id types.String `tfsdk:"id"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Instances types.List `tfsdk:"instances"` // Changed from Map to List
}
// instanceTypes defines the attribute types for a single instance object.
var instanceTypes = map[string]attr.Type{
"instance_id": types.StringType,
"display_name": types.StringType,
"created": types.StringType,
"frontend_url": types.StringType,
"region": types.StringType,
"plan_id": types.StringType,
"description": types.StringType,
"status": types.StringType,
}
// NewInstancesDataSource creates a new instance of the instancesDataSource.
func NewInstancesDataSource() datasource.DataSource {
return &instancesDataSource{}
}
// instancesDataSource is the data source implementation.
type instancesDataSource struct {
client *edge.APIClient
providerData core.ProviderData
}
// Configure sets up the API client for the Edge Cloud instance data source.
func (d *instancesDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
var ok bool
d.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
if !ok {
return
}
features.CheckBetaResourcesEnabled(ctx, &d.providerData, &resp.Diagnostics, "stackit_edgecloud_instances", "datasource")
if resp.Diagnostics.HasError() {
return
}
apiClient := edgeutils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics)
if resp.Diagnostics.HasError() {
return
}
d.client = apiClient
tflog.Info(ctx, "edge cloud client configured")
}
// Metadata provides metadata for the edge datasource.
func (d *instancesDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_edgecloud_instances"
}
// Schema defines the schema for the Edge Cloud instances data source.
func (d *instancesDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: features.AddBetaDescription("Edge Cloud is in private Beta and not generally available.\n You can contact support if you are interested in trying it out.", core.Datasource),
Description: "edge cloud instances datasource schema.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "Terraform's internal data source ID, structured as `project_id`,`region`.",
Computed: true,
},
"project_id": schema.StringAttribute{
Description: "STACKIT project ID to which the Edge Cloud instances are associated.",
Required: true,
Validators: []validator.String{
validate.UUID(),
},
},
"region": schema.StringAttribute{
Description: "The resource region. If not defined, the provider region is used.",
Optional: true,
},
"instances": schema.ListNestedAttribute{
Description: "A list of Edge Cloud instances.",
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"instance_id": schema.StringAttribute{
Description: "The ID of the instance.",
Computed: true,
},
"display_name": schema.StringAttribute{
Description: "The display name of the instance.",
Computed: true,
},
"created": schema.StringAttribute{
Description: "The date and time the instance was created.",
Computed: true,
},
"frontend_url": schema.StringAttribute{
Description: "Frontend URL for the Edge Cloud instance.",
Computed: true,
},
"region": schema.StringAttribute{
Description: "The region where the instance is located.",
Computed: true,
},
"plan_id": schema.StringAttribute{
Description: "The plan ID for the instance.",
Computed: true,
},
"description": schema.StringAttribute{
Description: "Description of the instance.",
Computed: true,
},
"status": schema.StringAttribute{
Description: "The status of the instance.",
Computed: true,
},
},
},
},
},
}
}
// Read fetches the list of Edge Cloud instances and populates the data source.
func (d *instancesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
var state DataSourceModel
diags := req.Config.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := state.ProjectId.ValueString()
region := d.providerData.GetRegionWithOverride(state.Region)
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
// Fetch all instances for the project and region
instancesResp, err := d.client.DefaultAPI.ListInstances(ctx, projectId, region).Execute()
if err != nil {
utils.LogError(
ctx,
&resp.Diagnostics,
err,
"Error reading instances:",
fmt.Sprintf("Calling API: %v", err),
map[int]string{
http.StatusNotFound: fmt.Sprintf("Project %q or region %q not found", projectId, region),
},
)
return
}
ctx = core.LogResponse(ctx)
if instancesResp == nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instances", "API response is nil")
return
}
if instancesResp.Instances == nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instances", "instance field in the API response is nil")
return
}
instancesList := buildInstancesList(ctx, instancesResp.Instances, region, &resp.Diagnostics)
if resp.Diagnostics.HasError() {
return
}
// Create ListValue
instancesListValue, diags := types.ListValue(types.ObjectType{AttrTypes: instanceTypes}, instancesList)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// Set the Terraform state
state.Id = types.StringValue(fmt.Sprintf("%s,%s", projectId, region))
state.Instances = instancesListValue
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "read all edgecloud instances")
}
// buildInstancesList constructs a list of instance attributes
func buildInstancesList(_ context.Context, instances []edge.Instance, region string, diags *diag.Diagnostics) []attr.Value {
var instancesList []attr.Value
for _, instance := range instances {
instanceAttrs := mapInstanceToAttrs(&instance, region)
instanceObjectValue, objDiags := types.ObjectValue(instanceTypes, instanceAttrs)
diags.Append(objDiags...)
if objDiags.HasError() {
continue
}
instancesList = append(instancesList, instanceObjectValue)
}
return instancesList
}
func mapInstanceToAttrs(instance *edge.Instance, region string) map[string]attr.Value {
attrs := map[string]attr.Value{
"instance_id": types.StringValue(instance.Id),
"display_name": types.StringValue(instance.DisplayName),
"region": types.StringValue(region),
"plan_id": types.StringValue(instance.PlanId),
"frontend_url": types.StringValue(instance.FrontendUrl),
"status": types.StringValue(instance.Status),
"created": types.StringValue(instance.Created.String()),
"description": types.StringPointerValue(instance.Description),
}
return attrs
}