Skip to content

Commit 549ea76

Browse files
chore(scf): switch to new SDK structure (#1400)
* chore(scf): Migrate to new SDK structure * chore(scf): update Acc test to use CheckAttrHasPrefix for console_url validation * refactor(scf): use std lib instead of utils * chore(scf): go mod tidy * refactor(scf): remove unnecessary zero value checks * fix(scf): fix check for id mismatch * refactor(tests): remove redundant test cases --------- Co-authored-by: cgoetz-inovex <carlo.goetz@inovex.de>
1 parent 50ee4f4 commit 549ea76

14 files changed

Lines changed: 181 additions & 406 deletions

File tree

stackit/internal/services/scf/organization/datasource.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1111
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1212
"github.com/hashicorp/terraform-plugin-log/tflog"
13-
"github.com/stackitcloud/stackit-sdk-go/services/scf"
13+
scf "github.com/stackitcloud/stackit-sdk-go/services/scf/v1api"
1414

1515
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
1616
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
@@ -149,7 +149,7 @@ func (s *scfOrganizationDataSource) Read(ctx context.Context, request datasource
149149
ctx = tflog.SetField(ctx, "region", region)
150150

151151
// Read the current scf organization via orgId
152-
scfOrgResponse, err := s.client.GetOrganization(ctx, projectId, region, orgId).Execute()
152+
scfOrgResponse, err := s.client.DefaultAPI.GetOrganization(ctx, projectId, region, orgId).Execute()
153153
if err != nil {
154154
utils.LogError(
155155
ctx,

stackit/internal/services/scf/organization/resource.go

Lines changed: 26 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import (
1717
"github.com/hashicorp/terraform-plugin-framework/types"
1818
"github.com/hashicorp/terraform-plugin-log/tflog"
1919
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
20-
"github.com/stackitcloud/stackit-sdk-go/services/scf"
21-
"github.com/stackitcloud/stackit-sdk-go/services/scf/wait"
20+
scf "github.com/stackitcloud/stackit-sdk-go/services/scf/v1api"
21+
"github.com/stackitcloud/stackit-sdk-go/services/scf/v1api/wait"
2222

2323
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
2424
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
@@ -249,7 +249,7 @@ func (s *scfOrganizationResource) Create(ctx context.Context, request resource.C
249249
}
250250

251251
// Create the new scf organization via the API client.
252-
scfOrgCreateResponse, err := s.client.CreateOrganization(ctx, projectId, region).
252+
scfOrgCreateResponse, err := s.client.DefaultAPI.CreateOrganization(ctx, projectId, region).
253253
CreateOrganizationPayload(payload).
254254
Execute()
255255
if err != nil {
@@ -259,11 +259,7 @@ func (s *scfOrganizationResource) Create(ctx context.Context, request resource.C
259259

260260
ctx = core.LogResponse(ctx)
261261

262-
if scfOrgCreateResponse.Guid == nil {
263-
core.LogAndAddError(ctx, &response.Diagnostics, "Error creating scf organization", "API response did not include org ID")
264-
return
265-
}
266-
orgId := *scfOrgCreateResponse.Guid
262+
orgId := scfOrgCreateResponse.Guid
267263

268264
ctx = utils.SetAndLogStateFields(ctx, &response.Diagnostics, &response.State, map[string]any{
269265
"project_id": projectId,
@@ -273,19 +269,19 @@ func (s *scfOrganizationResource) Create(ctx context.Context, request resource.C
273269

274270
// Apply the org quota if provided
275271
if quotaId != "" {
276-
applyOrgQuota, err := s.client.ApplyOrganizationQuota(ctx, projectId, region, orgId).ApplyOrganizationQuotaPayload(
272+
applyOrgQuota, err := s.client.DefaultAPI.ApplyOrganizationQuota(ctx, projectId, region, orgId).ApplyOrganizationQuotaPayload(
277273
scf.ApplyOrganizationQuotaPayload{
278-
QuotaId: &quotaId,
274+
QuotaId: quotaId,
279275
}).Execute()
280276
if err != nil {
281277
core.LogAndAddError(ctx, &response.Diagnostics, "Error creating scf organization", fmt.Sprintf("Calling API to apply quota: %v", err))
282278
return
283279
}
284-
model.QuotaId = types.StringPointerValue(applyOrgQuota.QuotaId)
280+
model.QuotaId = types.StringValue(applyOrgQuota.QuotaId)
285281
}
286282

287283
if suspended {
288-
_, err := s.client.UpdateOrganization(ctx, projectId, region, orgId).UpdateOrganizationPayload(
284+
_, err := s.client.DefaultAPI.UpdateOrganization(ctx, projectId, region, orgId).UpdateOrganizationPayload(
289285

290286
scf.UpdateOrganizationPayload{
291287
Suspended: &suspended,
@@ -297,7 +293,7 @@ func (s *scfOrganizationResource) Create(ctx context.Context, request resource.C
297293
}
298294

299295
// Load the newly created scf organization
300-
scfOrgResponse, err := s.client.GetOrganization(ctx, projectId, region, orgId).Execute()
296+
scfOrgResponse, err := s.client.DefaultAPI.GetOrganization(ctx, projectId, region, orgId).Execute()
301297
if err != nil {
302298
core.LogAndAddError(ctx, &response.Diagnostics, "Error creating scf organization", fmt.Sprintf("Calling API to load created org: %v", err))
303299
return
@@ -339,7 +335,7 @@ func (s *scfOrganizationResource) Read(ctx context.Context, request resource.Rea
339335
ctx = tflog.SetField(ctx, "org_id", orgId)
340336
ctx = tflog.SetField(ctx, "region", region)
341337
// Read the current scf organization via guid
342-
scfOrgResponse, err := s.client.GetOrganization(ctx, projectId, region, orgId).Execute()
338+
scfOrgResponse, err := s.client.DefaultAPI.GetOrganization(ctx, projectId, region, orgId).Execute()
343339
if err != nil {
344340
var oapiErr *oapierror.GenericOpenAPIError
345341
ok := errors.As(err, &oapiErr)
@@ -388,15 +384,15 @@ func (s *scfOrganizationResource) Update(ctx context.Context, request resource.U
388384
ctx = tflog.SetField(ctx, "org_id", orgId)
389385
ctx = tflog.SetField(ctx, "region", region)
390386

391-
org, err := s.client.GetOrganization(ctx, projectId, region, orgId).Execute()
387+
org, err := s.client.DefaultAPI.GetOrganization(ctx, projectId, region, orgId).Execute()
392388
if err != nil {
393389
core.LogAndAddError(ctx, &response.Diagnostics, "Error retrieving organization state", fmt.Sprintf("Getting organization state: %v", err))
394390
return
395391
}
396392

397393
// handle a change of the organization name or the suspended flag
398394
if name != org.GetName() || suspended != org.GetSuspended() {
399-
updatedOrg, err := s.client.UpdateOrganization(ctx, projectId, region, orgId).UpdateOrganizationPayload(
395+
updatedOrg, err := s.client.DefaultAPI.UpdateOrganization(ctx, projectId, region, orgId).UpdateOrganizationPayload(
400396
scf.UpdateOrganizationPayload{
401397
Name: &name,
402398
Suspended: &suspended,
@@ -412,9 +408,9 @@ func (s *scfOrganizationResource) Update(ctx context.Context, request resource.U
412408

413409
// handle a quota change of the org
414410
if quotaId != org.GetQuotaId() {
415-
applyOrgQuota, err := s.client.ApplyOrganizationQuota(ctx, projectId, region, orgId).ApplyOrganizationQuotaPayload(
411+
applyOrgQuota, err := s.client.DefaultAPI.ApplyOrganizationQuota(ctx, projectId, region, orgId).ApplyOrganizationQuotaPayload(
416412
scf.ApplyOrganizationQuotaPayload{
417-
QuotaId: &quotaId,
413+
QuotaId: quotaId,
418414
}).Execute()
419415
if err != nil {
420416
core.LogAndAddError(ctx, &response.Diagnostics, "Error applying organization quota", fmt.Sprintf("Processing API payload: %v", err))
@@ -460,15 +456,15 @@ func (s *scfOrganizationResource) Delete(ctx context.Context, request resource.D
460456
ctx = tflog.SetField(ctx, "region", region)
461457

462458
// Call API to delete the existing scf organization.
463-
_, err := s.client.DeleteOrganization(ctx, projectId, region, orgId).Execute()
459+
_, err := s.client.DefaultAPI.DeleteOrganization(ctx, projectId, region, orgId).Execute()
464460
if err != nil {
465461
core.LogAndAddError(ctx, &response.Diagnostics, "Error deleting scf organization", fmt.Sprintf("Calling API: %v", err))
466462
return
467463
}
468464

469465
ctx = core.LogResponse(ctx)
470466

471-
_, err = wait.DeleteOrganizationWaitHandler(ctx, s.client, projectId, model.Region.ValueString(), orgId).WaitWithContext(ctx)
467+
_, err = wait.DeleteOrganizationWaitHandler(ctx, s.client.DefaultAPI, projectId, model.Region.ValueString(), orgId).WaitWithContext(ctx)
472468
if err != nil {
473469
core.LogAndAddError(ctx, &response.Diagnostics, "Error waiting for scf org deletion", fmt.Sprintf("SCFOrganization deleting waiting: %v", err))
474470
return
@@ -511,43 +507,16 @@ func mapFields(response *scf.Organization, model *Model) error {
511507
return fmt.Errorf("model input is nil")
512508
}
513509

514-
var orgId string
515-
if response.Guid != nil {
516-
orgId = *response.Guid
517-
} else if model.OrgId.ValueString() != "" {
518-
orgId = model.OrgId.ValueString()
519-
} else {
520-
return fmt.Errorf("org id is not present")
521-
}
522-
523-
var projectId string
524-
if response.ProjectId != nil {
525-
projectId = *response.ProjectId
526-
} else if model.ProjectId.ValueString() != "" {
527-
projectId = model.ProjectId.ValueString()
528-
} else {
529-
return fmt.Errorf("project id is not present")
530-
}
531-
532-
var region string
533-
if response.Region != nil {
534-
region = *response.Region
535-
} else if model.Region.ValueString() != "" {
536-
region = model.Region.ValueString()
537-
} else {
538-
return fmt.Errorf("region is not present")
539-
}
540-
541510
// Build the ID by combining the project ID and organization id and assign the model's fields.
542-
model.Id = utils.BuildInternalTerraformId(projectId, region, orgId)
543-
model.ProjectId = types.StringValue(projectId)
544-
model.Region = types.StringValue(region)
545-
model.PlatformId = types.StringPointerValue(response.PlatformId)
546-
model.OrgId = types.StringValue(orgId)
547-
model.Name = types.StringPointerValue(response.Name)
548-
model.Status = types.StringPointerValue(response.Status)
549-
model.Suspended = types.BoolPointerValue(response.Suspended)
550-
model.QuotaId = types.StringPointerValue(response.QuotaId)
511+
model.Id = utils.BuildInternalTerraformId(response.ProjectId, response.Region, response.Guid)
512+
model.ProjectId = types.StringValue(response.ProjectId)
513+
model.Region = types.StringValue(response.Region)
514+
model.PlatformId = types.StringValue(response.PlatformId)
515+
model.OrgId = types.StringValue(response.Guid)
516+
model.Name = types.StringValue(response.Name)
517+
model.Status = types.StringValue(response.Status)
518+
model.Suspended = types.BoolValue(response.Suspended)
519+
model.QuotaId = types.StringValue(response.QuotaId)
551520
model.CreateAt = types.StringValue(response.CreatedAt.String())
552521
model.UpdatedAt = types.StringValue(response.UpdatedAt.String())
553522
return nil
@@ -560,7 +529,7 @@ func toCreatePayload(model *Model) (scf.CreateOrganizationPayload, error) {
560529
}
561530

562531
payload := scf.CreateOrganizationPayload{
563-
Name: model.Name.ValueStringPointer(),
532+
Name: model.Name.ValueString(),
564533
}
565534
if !model.PlatformId.IsNull() && !model.PlatformId.IsUnknown() {
566535
payload.PlatformId = model.PlatformId.ValueStringPointer()

stackit/internal/services/scf/organization/resource_test.go

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/google/go-cmp/cmp"
99
"github.com/google/uuid"
1010
"github.com/hashicorp/terraform-plugin-framework/types"
11-
"github.com/stackitcloud/stackit-sdk-go/services/scf"
11+
scf "github.com/stackitcloud/stackit-sdk-go/services/scf/v1api"
1212
)
1313

1414
var (
@@ -34,23 +34,23 @@ func TestMapFields(t *testing.T) {
3434
{
3535
description: "minimal_input",
3636
input: &scf.Organization{
37-
Guid: new(testOrgId),
38-
Name: new("scf-org-min-instance"),
39-
Region: new(testRegion),
40-
CreatedAt: &createdTime,
41-
UpdatedAt: &createdTime,
42-
ProjectId: new(testProjectId),
37+
Guid: testOrgId,
38+
Name: "scf-org-min-instance",
39+
Region: testRegion,
40+
CreatedAt: createdTime,
41+
UpdatedAt: createdTime,
42+
ProjectId: testProjectId,
4343
},
4444
expected: &Model{
4545
Id: types.StringValue(fmt.Sprintf("%s,%s,%s", testProjectId, testRegion, testOrgId)),
4646
ProjectId: types.StringValue(testProjectId),
4747
Region: types.StringValue(testRegion),
4848
Name: types.StringValue("scf-org-min-instance"),
49-
PlatformId: types.StringNull(),
49+
PlatformId: types.StringValue(""),
5050
OrgId: types.StringValue(testOrgId),
51-
QuotaId: types.StringNull(),
52-
Status: types.StringNull(),
53-
Suspended: types.BoolNull(),
51+
QuotaId: types.StringValue(""),
52+
Status: types.StringValue(""),
53+
Suspended: types.BoolValue(false),
5454
CreateAt: types.StringValue("2025-01-01 00:00:00 +0000 UTC"),
5555
UpdatedAt: types.StringValue("2025-01-01 00:00:00 +0000 UTC"),
5656
},
@@ -59,16 +59,16 @@ func TestMapFields(t *testing.T) {
5959
{
6060
description: "max_input",
6161
input: &scf.Organization{
62-
CreatedAt: &createdTime,
63-
Guid: new(testOrgId),
64-
Name: new("scf-full-org"),
65-
PlatformId: new(testPlatformId),
66-
ProjectId: new(testProjectId),
67-
QuotaId: new(testQuotaId),
68-
Region: new(testRegion),
69-
Status: nil,
70-
Suspended: new(true),
71-
UpdatedAt: &createdTime,
62+
CreatedAt: createdTime,
63+
Guid: testOrgId,
64+
Name: "scf-full-org",
65+
PlatformId: testPlatformId,
66+
ProjectId: testProjectId,
67+
QuotaId: testQuotaId,
68+
Region: testRegion,
69+
Status: "",
70+
Suspended: true,
71+
UpdatedAt: createdTime,
7272
},
7373
expected: &Model{
7474
Id: types.StringValue(fmt.Sprintf("%s,%s,%s", testProjectId, testRegion, testOrgId)),
@@ -80,7 +80,7 @@ func TestMapFields(t *testing.T) {
8080
CreateAt: types.StringValue("2025-01-01 00:00:00 +0000 UTC"),
8181
UpdatedAt: types.StringValue("2025-01-01 00:00:00 +0000 UTC"),
8282
QuotaId: types.StringValue(testQuotaId),
83-
Status: types.StringNull(),
83+
Status: types.StringValue(""),
8484
Suspended: types.BoolValue(true),
8585
},
8686
isValid: true,
@@ -91,20 +91,6 @@ func TestMapFields(t *testing.T) {
9191
expected: nil,
9292
isValid: false,
9393
},
94-
{
95-
description: "empty_org",
96-
input: &scf.Organization{},
97-
expected: nil,
98-
isValid: false,
99-
},
100-
{
101-
description: "missing_id",
102-
input: &scf.Organization{
103-
Name: new("scf-missing-id"),
104-
},
105-
expected: nil,
106-
isValid: false,
107-
},
10894
}
10995
for _, tt := range tests {
11096
t.Run(tt.description, func(t *testing.T) {
@@ -143,8 +129,8 @@ func TestToCreatePayload(t *testing.T) {
143129
PlatformId: types.StringValue(testPlatformId),
144130
},
145131
expected: scf.CreateOrganizationPayload{
146-
Name: new("example-org"),
147-
PlatformId: new(testPlatformId),
132+
Name: "example-org",
133+
PlatformId: &testPlatformId,
148134
},
149135
expectError: false,
150136
},

stackit/internal/services/scf/organizationmanager/datasource.go

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1212
"github.com/hashicorp/terraform-plugin-framework/types"
1313
"github.com/hashicorp/terraform-plugin-log/tflog"
14-
"github.com/stackitcloud/stackit-sdk-go/services/scf"
14+
scf "github.com/stackitcloud/stackit-sdk-go/services/scf/v1api"
1515

1616
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
1717
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
@@ -152,7 +152,7 @@ func (s *scfOrganizationManagerDataSource) Read(ctx context.Context, request dat
152152
ctx = tflog.SetField(ctx, "org_id", orgId)
153153
ctx = tflog.SetField(ctx, "region", region)
154154
// Read the current scf organization manager via orgId
155-
ScfOrgManager, err := s.client.GetOrgManagerExecute(ctx, projectId, region, orgId)
155+
ScfOrgManager, err := s.client.DefaultAPI.GetOrgManager(ctx, projectId, region, orgId).Execute()
156156
if err != nil {
157157
utils.LogError(
158158
ctx,
@@ -189,53 +189,17 @@ func mapFieldsDataSource(response *scf.OrgManager, model *DataSourceModel) error
189189
if model == nil {
190190
return fmt.Errorf("model input is nil")
191191
}
192-
193-
var projectId string
194-
if response.ProjectId != nil {
195-
projectId = *response.ProjectId
196-
} else if model.ProjectId.ValueString() != "" {
197-
projectId = model.ProjectId.ValueString()
198-
} else {
199-
return fmt.Errorf("project id is not present")
200-
}
201-
202-
var region string
203-
if response.Region != nil {
204-
region = *response.Region
205-
} else if model.Region.ValueString() != "" {
206-
region = model.Region.ValueString()
207-
} else {
208-
return fmt.Errorf("region is not present")
209-
}
210-
211-
var orgId string
212-
if response.OrgId != nil {
213-
orgId = *response.OrgId
214-
} else if model.OrgId.ValueString() != "" {
215-
orgId = model.OrgId.ValueString()
216-
} else {
217-
return fmt.Errorf("org id is not present")
218-
}
219-
220-
var userId string
221-
if response.Guid != nil {
222-
userId = *response.Guid
223-
if model.UserId.ValueString() != "" && userId != model.UserId.ValueString() {
224-
return fmt.Errorf("user id mismatch in response and model")
225-
}
226-
} else if model.UserId.ValueString() != "" {
227-
userId = model.UserId.ValueString()
228-
} else {
229-
return fmt.Errorf("user id is not present")
192+
if userId := model.UserId.ValueString(); userId != "" && userId != response.Guid {
193+
return fmt.Errorf("user id mismatch in response and model")
230194
}
231195

232-
model.Id = utils.BuildInternalTerraformId(projectId, region, orgId, userId)
233-
model.Region = types.StringValue(region)
234-
model.PlatformId = types.StringPointerValue(response.PlatformId)
235-
model.ProjectId = types.StringValue(projectId)
236-
model.OrgId = types.StringValue(orgId)
237-
model.UserId = types.StringValue(userId)
238-
model.UserName = types.StringPointerValue(response.Username)
196+
model.Id = utils.BuildInternalTerraformId(response.ProjectId, response.Region, response.OrgId, response.Guid)
197+
model.Region = types.StringValue(response.Region)
198+
model.PlatformId = types.StringValue(response.PlatformId)
199+
model.ProjectId = types.StringValue(response.ProjectId)
200+
model.OrgId = types.StringValue(response.OrgId)
201+
model.UserId = types.StringValue(response.Guid)
202+
model.UserName = types.StringValue(response.Username)
239203
model.CreateAt = types.StringValue(response.CreatedAt.String())
240204
model.UpdatedAt = types.StringValue(response.UpdatedAt.String())
241205
return nil

0 commit comments

Comments
 (0)