Skip to content

Commit ccaca32

Browse files
committed
review changes
Signed-off-by: Mauritz Uphoff <[email protected]>
1 parent e0c855a commit ccaca32

File tree

8 files changed

+155
-284
lines changed

8 files changed

+155
-284
lines changed

docs/data-sources/resourcemanager_folder.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ page_title: "stackit_resourcemanager_folder Data Source - stackit"
44
subcategory: ""
55
description: |-
66
Resource Manager folder data source schema. To identify the folder, you need to provider the container_id.
7+
~> This datasource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
78
---
89

910
# stackit_resourcemanager_folder (Data Source)
1011

1112
Resource Manager folder data source schema. To identify the folder, you need to provider the container_id.
1213

14+
~> This datasource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
15+
1316
## Example Usage
1417

1518
```terraform

docs/resources/resourcemanager_folder.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ resource "stackit_resourcemanager_project" "example_project" {
3232
owner_email = "[email protected]"
3333
parent_container_id = stackit_resourcemanager_folder.example.container_id
3434
}
35+
36+
# Only use the import statement, if you want to import an existing resourcemanager folder
37+
# Note: There will be a conflict which needs to be resolved manually.
38+
# Must set a configuration value for the owner_email attribute as the provider has marked it as required.
39+
import {
40+
to = stackit_resourcemanager_folder.import-example
41+
id = var.container_id
42+
}
3543
```
3644

3745
<!-- schema generated by tfplugindocs -->

examples/resources/stackit_resourcemanager_folder/resource.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,12 @@ resource "stackit_resourcemanager_project" "example_project" {
1313
name = "example-project"
1414
owner_email = "[email protected]"
1515
parent_container_id = stackit_resourcemanager_folder.example.container_id
16+
}
17+
18+
# Only use the import statement, if you want to import an existing resourcemanager folder
19+
# Note: There will be a conflict which needs to be resolved manually.
20+
# Must set a configuration value for the owner_email attribute as the provider has marked it as required.
21+
import {
22+
to = stackit_resourcemanager_folder.import-example
23+
id = var.container_id
1624
}

stackit/internal/services/resourcemanager/folder/datasource.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import (
2424

2525
// Ensure the implementation satisfies the expected interfaces.
2626
var (
27-
_ datasource.DataSource = &folderDataSource{}
27+
_ datasource.DataSource = &folderDataSource{}
28+
_ datasource.DataSourceWithConfigure = &folderDataSource{}
2829
)
2930

3031
// NewFolderDataSource is a helper function to simplify the provider implementation.
@@ -77,7 +78,7 @@ func (d *folderDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
7778
}
7879

7980
resp.Schema = schema.Schema{
80-
Description: descriptions["main"],
81+
Description: features.AddBetaDescription(descriptions["main"], core.Datasource),
8182
Attributes: map[string]schema.Attribute{
8283
"id": schema.StringAttribute{
8384
Description: descriptions["id"],
@@ -169,7 +170,7 @@ func (d *folderDataSource) Read(ctx context.Context, req datasource.ReadRequest,
169170
return
170171
}
171172

172-
err = mapFolderDetailsFields(ctx, folderResp, &model, &resp.State)
173+
err = mapFolderFields(ctx, folderResp, &model, &resp.State)
173174
if err != nil {
174175
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading folder", fmt.Sprintf("Processing API response: %v", err))
175176
return

stackit/internal/services/resourcemanager/folder/resource.go

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -209,21 +209,32 @@ func (r *folderResource) Create(ctx context.Context, req resource.CreateRequest,
209209
return
210210
}
211211

212-
folderResp, err := r.client.CreateFolder(ctx).CreateFolderPayload(*payload).Execute()
212+
folderCreateResp, err := r.client.CreateFolder(ctx).CreateFolderPayload(*payload).Execute()
213213
if err != nil {
214214
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating folder", fmt.Sprintf("Calling API: %v", err))
215215
return
216216
}
217217

218-
err = mapFolderCreateFields(ctx, folderResp, &model.Model, &resp.State)
219-
if err != nil {
220-
core.LogAndAddError(ctx, &resp.Diagnostics, "API response processing error", err.Error())
218+
if folderCreateResp.ContainerId == nil || *folderCreateResp.ContainerId == "" {
219+
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating folder", "Container ID is missing")
221220
return
222221
}
223222

224223
// This sleep is currently needed due to the IAM Cache.
225224
time.Sleep(10 * time.Second)
226225

226+
folderGetResponse, err := r.client.GetFolderDetails(ctx, *folderCreateResp.ContainerId).Execute()
227+
if err != nil {
228+
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating folder", fmt.Sprintf("Calling API: %v", err))
229+
return
230+
}
231+
232+
err = mapFolderFields(ctx, folderGetResponse, &model.Model, &resp.State)
233+
if err != nil {
234+
core.LogAndAddError(ctx, &resp.Diagnostics, "API response processing error", err.Error())
235+
return
236+
}
237+
227238
resp.Diagnostics.Append(resp.State.Set(ctx, model)...)
228239
tflog.Info(ctx, "Folder created")
229240
}
@@ -253,7 +264,7 @@ func (r *folderResource) Read(ctx context.Context, req resource.ReadRequest, res
253264
return
254265
}
255266

256-
err = mapFolderDetailsFields(ctx, folderResp, &model.Model, &resp.State)
267+
err = mapFolderFields(ctx, folderResp, &model.Model, &resp.State)
257268
if err != nil {
258269
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading folder", fmt.Sprintf("Processing API response: %v", err))
259270
return
@@ -300,7 +311,7 @@ func (r *folderResource) Update(ctx context.Context, req resource.UpdateRequest,
300311
return
301312
}
302313

303-
err = mapFolderDetailsFields(ctx, folderResp, &model.Model, &resp.State)
314+
err = mapFolderFields(ctx, folderResp, &model.Model, &resp.State)
304315
if err != nil {
305316
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating folder", fmt.Sprintf("Processing API response: %v", err))
306317
return
@@ -334,7 +345,7 @@ func (r *folderResource) Delete(ctx context.Context, req resource.DeleteRequest,
334345
ctx,
335346
&resp.Diagnostics,
336347
"Error deleting folder. Deletion may fail because associated projects remain hidden for up to 7 days after user deletion due to technical requirements.",
337-
fmt.Sprintf("API call failed: %v", err),
348+
fmt.Sprintf("Calling API: %v", err),
338349
)
339350
return
340351
}
@@ -363,22 +374,36 @@ func (r *folderResource) ImportState(ctx context.Context, req resource.ImportSta
363374
// mapFolderFields maps folder fields from a response into the Terraform model and optionally updates state.
364375
func mapFolderFields(
365376
ctx context.Context,
366-
containerId, name, folderId *string,
367-
labels *map[string]string, //nolint:gocritic
368-
containerParent *resourcemanager.Parent,
369-
creationTime *time.Time,
370-
updateTime *time.Time,
377+
folderGetResponse *resourcemanager.GetFolderDetailsResponse,
371378
model *Model,
372379
state *tfsdk.State,
373380
) error {
374-
if containerId == nil || *containerId == "" {
375-
return fmt.Errorf("container id is present")
381+
if folderGetResponse == nil {
382+
return fmt.Errorf("folder get response is nil")
383+
}
384+
385+
var folderId string
386+
if model.FolderId.ValueString() != "" {
387+
folderId = model.FolderId.ValueString()
388+
} else if folderGetResponse.FolderId != nil {
389+
folderId = *folderGetResponse.FolderId
390+
} else {
391+
return fmt.Errorf("folder id not present")
392+
}
393+
394+
var containerId string
395+
if model.ContainerId.ValueString() != "" {
396+
containerId = model.ContainerId.ValueString()
397+
} else if folderGetResponse.ContainerId != nil {
398+
containerId = *folderGetResponse.ContainerId
399+
} else {
400+
return fmt.Errorf("container id not present")
376401
}
377402

378403
var err error
379404
var tfLabels basetypes.MapValue
380-
if labels != nil && len(*labels) > 0 {
381-
tfLabels, err = conversion.ToTerraformStringMap(ctx, *labels)
405+
if folderGetResponse.Labels != nil && len(*folderGetResponse.Labels) > 0 {
406+
tfLabels, err = conversion.ToTerraformStringMap(ctx, *folderGetResponse.Labels)
382407
if err != nil {
383408
return fmt.Errorf("converting to StringValue map: %w", err)
384409
}
@@ -387,26 +412,26 @@ func mapFolderFields(
387412
}
388413

389414
var containerParentIdTF basetypes.StringValue
390-
if containerParent != nil {
415+
if folderGetResponse.Parent != nil {
391416
if _, err := uuid.Parse(model.ContainerParentId.ValueString()); err == nil {
392417
// the provided containerParent is the UUID identifier
393-
containerParentIdTF = types.StringPointerValue(containerParent.Id)
418+
containerParentIdTF = types.StringPointerValue(folderGetResponse.Parent.Id)
394419
} else {
395420
// the provided containerParent is the user-friendly container id
396-
containerParentIdTF = types.StringPointerValue(containerParent.ContainerId)
421+
containerParentIdTF = types.StringPointerValue(folderGetResponse.Parent.ContainerId)
397422
}
398423
} else {
399424
containerParentIdTF = types.StringNull()
400425
}
401426

402-
model.Id = types.StringValue(*containerId)
403-
model.FolderId = types.StringValue(*folderId)
404-
model.ContainerId = types.StringValue(*containerId)
427+
model.Id = types.StringValue(containerId)
428+
model.FolderId = types.StringValue(folderId)
429+
model.ContainerId = types.StringValue(containerId)
405430
model.ContainerParentId = containerParentIdTF
406-
model.Name = types.StringPointerValue(name)
431+
model.Name = types.StringPointerValue(folderGetResponse.Name)
407432
model.Labels = tfLabels
408-
model.CreationTime = types.StringValue(creationTime.Format(time.RFC3339))
409-
model.UpdateTime = types.StringValue(updateTime.Format(time.RFC3339))
433+
model.CreationTime = types.StringValue(folderGetResponse.CreationTime.Format(time.RFC3339))
434+
model.UpdateTime = types.StringValue(folderGetResponse.UpdateTime.Format(time.RFC3339))
410435

411436
if state != nil {
412437
diags := diag.Diagnostics{}
@@ -426,16 +451,6 @@ func mapFolderFields(
426451
return nil
427452
}
428453

429-
// mapFolderCreateFields maps the Create Folder API response to the Terraform model and update the Terraform state
430-
func mapFolderCreateFields(ctx context.Context, resp *resourcemanager.FolderResponse, model *Model, state *tfsdk.State) error {
431-
return mapFolderFields(ctx, resp.ContainerId, resp.Name, resp.FolderId, resp.Labels, resp.Parent, resp.CreationTime, resp.UpdateTime, model, state)
432-
}
433-
434-
// mapFolderDetailsFields maps the GetDetails API response to the Terraform model and update the Terraform state
435-
func mapFolderDetailsFields(ctx context.Context, resp *resourcemanager.GetFolderDetailsResponse, model *Model, state *tfsdk.State) error {
436-
return mapFolderFields(ctx, resp.ContainerId, resp.Name, resp.FolderId, resp.Labels, resp.Parent, resp.CreationTime, resp.UpdateTime, model, state)
437-
}
438-
439454
func toMembersPayload(model *ResourceModel) (*[]resourcemanager.Member, error) {
440455
if model == nil {
441456
return nil, fmt.Errorf("nil model")

0 commit comments

Comments
 (0)