Skip to content

Commit 9642d63

Browse files
authored
WIRE-1038: Add scopes field for role bindings (#472)
* WIRE-1038: Add scopes field for role bindings * Fix docs * Rebase on master * Add unit tests * Fix sdk generate * Address comments * Regenerate docs after rebase on master
1 parent d9f3ee6 commit 9642d63

File tree

8 files changed

+615
-110
lines changed

8 files changed

+615
-110
lines changed

castai/reservations/mapping_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package reservations
22

33
import (
4+
"testing"
5+
"time"
6+
47
"github.com/castai/terraform-provider-castai/castai/sdk"
58
"github.com/samber/lo"
69
"github.com/stretchr/testify/require"
7-
"testing"
8-
"time"
910
)
1011

1112
func TestMapCsvRecordsToReservationResources(t *testing.T) {

castai/resource_role_bindings.go

Lines changed: 121 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const (
2222
FieldRoleBindingsDescription = "description"
2323
FieldRoleBindingsRoleID = "role_id"
2424
FieldRoleBindingsScope = "scope"
25+
FieldRoleBindingsScopes = "scopes"
2526
FieldRoleBindingsScopeKind = "kind"
2627
FieldRoleBindingsScopeResourceID = "resource_id"
2728
FieldRoleBindingsSubjects = "subjects"
@@ -84,9 +85,33 @@ func resourceRoleBindings() *schema.Resource {
8485
},
8586
FieldRoleBindingsScope: {
8687
Type: schema.TypeList,
87-
Required: true,
88+
Optional: true,
8889
MaxItems: 1,
8990
Description: "Scope of the role binding.",
91+
Deprecated: "this field is deprecated and will be removed in future versions, use `scopes` field instead",
92+
Elem: &schema.Resource{
93+
Schema: map[string]*schema.Schema{
94+
FieldRoleBindingsScopeKind: {
95+
Type: schema.TypeString,
96+
Required: true,
97+
Description: fmt.Sprintf("Scope of the role binding Supported values include: %s.", strings.Join(supportedScopeKinds, ", ")),
98+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(supportedScopeKinds, true)),
99+
DiffSuppressFunc: func(k, oldValue, newValue string, d *schema.ResourceData) bool {
100+
return strings.EqualFold(oldValue, newValue)
101+
},
102+
},
103+
FieldRoleBindingsScopeResourceID: {
104+
Type: schema.TypeString,
105+
Required: true,
106+
Description: "ID of the scope resource.",
107+
},
108+
},
109+
},
110+
},
111+
FieldRoleBindingsScopes: {
112+
Type: schema.TypeList,
113+
Optional: true,
114+
Description: "Scopes of the role binding.",
90115
Elem: &schema.Resource{
91116
Schema: map[string]*schema.Schema{
92117
FieldRoleBindingsScopeKind: {
@@ -199,12 +224,18 @@ func resourceRoleBindingsCreate(ctx context.Context, data *schema.ResourceData,
199224
return diag.FromErr(err)
200225
}
201226
scope := convertScopeToSDK(data)
227+
scopes := convertScopesToSDK(data)
228+
229+
if scope == nil && len(scopes) == 0 {
230+
return diag.Errorf("role binding scopes were not provided")
231+
}
202232

203233
resp, err := client.RbacServiceAPICreateRoleBindingsWithResponse(ctx, organizationID, sdk.RbacServiceAPICreateRoleBindingsJSONRequestBody{
204234
{
205235
Definition: sdk.CastaiRbacV1beta1RoleBindingDefinition{
206236
RoleId: data.Get(FieldRoleBindingsRoleID).(string),
207-
Scope: &scope,
237+
Scope: scope,
238+
Scopes: &scopes,
208239
Subjects: &subjects,
209240
},
210241
Description: lo.ToPtr(data.Get(FieldRoleBindingsDescription).(string)),
@@ -247,11 +278,17 @@ func resourceRoleBindingsUpdate(ctx context.Context, data *schema.ResourceData,
247278
return diag.FromErr(err)
248279
}
249280
scope := convertScopeToSDK(data)
281+
scopes := convertScopesToSDK(data)
282+
283+
if scope == nil && len(scopes) == 0 {
284+
return diag.Errorf("role binding scopes were not provided")
285+
}
250286

251287
resp, err := client.RbacServiceAPIUpdateRoleBindingWithResponse(ctx, organizationID, roleBindingID, sdk.RbacServiceAPIUpdateRoleBindingJSONRequestBody{
252288
Definition: sdk.CastaiRbacV1beta1RoleBindingDefinition{
253289
RoleId: data.Get(FieldRoleBindingsRoleID).(string),
254-
Scope: &scope,
290+
Scope: scope,
291+
Scopes: &scopes,
255292
Subjects: &subjects,
256293
},
257294
Description: lo.ToPtr(data.Get(FieldRoleBindingsDescription).(string)),
@@ -321,28 +358,55 @@ func assignRoleBindingData(roleBinding *sdk.CastaiRbacV1beta1RoleBinding, data *
321358
return fmt.Errorf("setting role binding role id: %w", err)
322359
}
323360

324-
if roleBinding.Definition.Scope != nil && roleBinding.Definition.Scope.Organization != nil {
325-
err := data.Set(FieldRoleBindingsScope, []any{
326-
map[string]any{
327-
FieldRoleBindingsScopeKind: RoleBindingScopeKindOrganization,
328-
FieldRoleBindingsScopeResourceID: roleBinding.Definition.Scope.Organization.Id,
329-
},
330-
})
331-
if err != nil {
332-
return fmt.Errorf("parsing scope organization: %w", err)
361+
if roleBinding.Definition.Scope != nil {
362+
if roleBinding.Definition.Scope.Organization != nil {
363+
err := data.Set(FieldRoleBindingsScope, []any{
364+
map[string]any{
365+
FieldRoleBindingsScopeKind: RoleBindingScopeKindOrganization,
366+
FieldRoleBindingsScopeResourceID: roleBinding.Definition.Scope.Organization.Id,
367+
},
368+
})
369+
if err != nil {
370+
return fmt.Errorf("parsing scope organization: %w", err)
371+
}
372+
} else if roleBinding.Definition.Scope.Cluster != nil {
373+
err := data.Set(FieldRoleBindingsScope, []any{
374+
map[string]any{
375+
FieldRoleBindingsScopeKind: RoleBindingScopeKindCluster,
376+
FieldRoleBindingsScopeResourceID: roleBinding.Definition.Scope.Cluster.Id,
377+
},
378+
})
379+
if err != nil {
380+
return fmt.Errorf("parsing scope cluster: %w", err)
381+
}
333382
}
334-
} else if roleBinding.Definition.Scope != nil && roleBinding.Definition.Scope.Cluster != nil {
335-
err := data.Set(FieldRoleBindingsScope, []any{
336-
map[string]any{
337-
FieldRoleBindingsScopeKind: RoleBindingScopeKindCluster,
338-
FieldRoleBindingsScopeResourceID: roleBinding.Definition.Scope.Cluster.Id,
339-
},
340-
})
341-
if err != nil {
342-
return fmt.Errorf("parsing scope cluster: %w", err)
383+
}
384+
385+
scopes := []any{}
386+
if roleBinding.Definition.Scopes != nil {
387+
for _, scope := range *roleBinding.Definition.Scopes {
388+
if scope.Organization != nil {
389+
scopes = append(scopes,
390+
map[string]any{
391+
FieldRoleBindingsScopeKind: RoleBindingScopeKindOrganization,
392+
FieldRoleBindingsScopeResourceID: scope.Organization.Id,
393+
},
394+
)
395+
} else if scope.Cluster != nil {
396+
scopes = append(scopes,
397+
map[string]any{
398+
FieldRoleBindingsScopeKind: RoleBindingScopeKindCluster,
399+
FieldRoleBindingsScopeResourceID: scope.Cluster.Id,
400+
},
401+
)
402+
}
343403
}
344404
}
345405

406+
if err := data.Set(FieldRoleBindingsScopes, scopes); err != nil {
407+
return fmt.Errorf("parsing scopes: %w", err)
408+
}
409+
346410
if roleBinding.Definition.Subjects != nil {
347411
var subjects []map[string]string
348412
for _, subject := range *roleBinding.Definition.Subjects {
@@ -377,30 +441,61 @@ func assignRoleBindingData(roleBinding *sdk.CastaiRbacV1beta1RoleBinding, data *
377441
return nil
378442
}
379443

380-
func convertScopeToSDK(data *schema.ResourceData) sdk.CastaiRbacV1beta1Scope {
444+
func convertScopeToSDK(data *schema.ResourceData) *sdk.CastaiRbacV1beta1Scope {
381445
scopes := data.Get(FieldRoleBindingsScope).([]any)
382446
if len(scopes) == 0 {
383-
return sdk.CastaiRbacV1beta1Scope{}
447+
return nil
384448
}
385449

386450
scope := scopes[0].(map[string]any)
387451

388452
switch scope[FieldRoleBindingsScopeKind].(string) {
389453
case RoleBindingScopeKindOrganization:
390-
return sdk.CastaiRbacV1beta1Scope{
454+
return &sdk.CastaiRbacV1beta1Scope{
391455
Organization: &sdk.CastaiRbacV1beta1OrganizationScope{
392456
Id: scope[FieldRoleBindingsScopeResourceID].(string),
393457
},
394458
}
395459
case RoleBindingScopeKindCluster:
396-
return sdk.CastaiRbacV1beta1Scope{
460+
return &sdk.CastaiRbacV1beta1Scope{
397461
Cluster: &sdk.CastaiRbacV1beta1ClusterScope{
398462
Id: scope[FieldRoleBindingsScopeResourceID].(string),
399463
},
400464
}
401465
default:
402-
return sdk.CastaiRbacV1beta1Scope{}
466+
return nil
467+
}
468+
}
469+
470+
func convertScopesToSDK(data *schema.ResourceData) []sdk.CastaiRbacV1beta1Scope {
471+
result := []sdk.CastaiRbacV1beta1Scope{}
472+
473+
scopes := data.Get(FieldRoleBindingsScopes).([]any)
474+
if len(scopes) == 0 {
475+
return result
476+
}
477+
478+
for _, scope := range scopes {
479+
scp := scope.(map[string]any)
480+
481+
switch scp[FieldRoleBindingsScopeKind].(string) {
482+
case RoleBindingScopeKindOrganization:
483+
result = append(result, sdk.CastaiRbacV1beta1Scope{
484+
Organization: &sdk.CastaiRbacV1beta1OrganizationScope{
485+
Id: scp[FieldRoleBindingsScopeResourceID].(string),
486+
},
487+
})
488+
case RoleBindingScopeKindCluster:
489+
result = append(result, sdk.CastaiRbacV1beta1Scope{
490+
Cluster: &sdk.CastaiRbacV1beta1ClusterScope{
491+
Id: scp[FieldRoleBindingsScopeResourceID].(string),
492+
},
493+
})
494+
default:
495+
result = append(result, sdk.CastaiRbacV1beta1Scope{})
496+
}
403497
}
498+
return result
404499
}
405500

406501
func convertSubjectsToSDK(data *schema.ResourceData) ([]sdk.CastaiRbacV1beta1Subject, error) {

0 commit comments

Comments
 (0)