55 "fmt"
66 "regexp"
77
8+ "github.com/coder/coder/v2/coderd/util/slice"
89 "github.com/coder/coder/v2/codersdk"
910 "github.com/coder/terraform-provider-coderd/internal/codersdkvalidator"
1011 "github.com/google/uuid"
@@ -40,8 +41,9 @@ type OrganizationResourceModel struct {
4041 Description types.String `tfsdk:"description"`
4142 Icon types.String `tfsdk:"icon"`
4243
43- GroupSync types.Object `tfsdk:"group_sync"`
44- RoleSync types.Object `tfsdk:"role_sync"`
44+ OrgSyncIdpGroups types.Set `tfsdk:"org_sync_idp_groups"`
45+ GroupSync types.Object `tfsdk:"group_sync"`
46+ RoleSync types.Object `tfsdk:"role_sync"`
4547}
4648
4749type GroupSyncModel struct {
@@ -134,6 +136,12 @@ This resource is only compatible with Coder version [2.16.0](https://github.com/
134136 Computed : true ,
135137 Default : stringdefault .StaticString ("" ),
136138 },
139+
140+ "org_sync_idp_groups" : schema.SetAttribute {
141+ ElementType : types .StringType ,
142+ Optional : true ,
143+ MarkdownDescription : "Claims from the IdP provider that will give users access to this organization." ,
144+ },
137145 },
138146
139147 Blocks : map [string ]schema.Block {
@@ -361,21 +369,38 @@ func (r *OrganizationResource) Create(ctx context.Context, req resource.CreateRe
361369 // default it.
362370 data .DisplayName = types .StringValue (org .DisplayName )
363371
364- // Now apply group and role sync settings, if specified
365372 orgID := data .ID .ValueUUID ()
366- tflog .Trace (ctx , "updating group sync" , map [string ]any {
367- "orgID" : orgID ,
368- })
373+
374+ // Apply org sync patches, if specified
375+ if ! data .OrgSyncIdpGroups .IsNull () {
376+ tflog .Trace (ctx , "updating org sync" , map [string ]any {
377+ "orgID" : orgID ,
378+ })
379+
380+ var claims []string
381+ resp .Diagnostics .Append (data .OrgSyncIdpGroups .ElementsAs (ctx , & claims , false )... )
382+ if resp .Diagnostics .HasError () {
383+ return
384+ }
385+
386+ resp .Diagnostics .Append (r .patchOrgSyncMapping (ctx , orgID , []string {}, claims )... )
387+ }
388+
389+ // Apply group and role sync settings, if specified
369390 if ! data .GroupSync .IsNull () {
391+ tflog .Trace (ctx , "updating group sync" , map [string ]any {
392+ "orgID" : orgID ,
393+ })
394+
370395 resp .Diagnostics .Append (r .patchGroupSync (ctx , orgID , data .GroupSync )... )
371396 if resp .Diagnostics .HasError () {
372397 return
373398 }
374399 }
375- tflog .Trace (ctx , "updating role sync" , map [string ]any {
376- "orgID" : orgID ,
377- })
378400 if ! data .RoleSync .IsNull () {
401+ tflog .Trace (ctx , "updating role sync" , map [string ]any {
402+ "orgID" : orgID ,
403+ })
379404 resp .Diagnostics .Append (r .patchRoleSync (ctx , orgID , data .RoleSync )... )
380405 if resp .Diagnostics .HasError () {
381406 return
@@ -423,19 +448,42 @@ func (r *OrganizationResource) Update(ctx context.Context, req resource.UpdateRe
423448 "icon" : org .Icon ,
424449 })
425450
426- tflog .Trace (ctx , "updating group sync" , map [string ]any {
427- "orgID" : orgID ,
428- })
451+ // Apply org sync patches, if specified
452+ if ! data .OrgSyncIdpGroups .IsNull () {
453+ tflog .Trace (ctx , "updating org sync mappings" , map [string ]any {
454+ "orgID" : orgID ,
455+ })
456+
457+ var state OrganizationResourceModel
458+ resp .Diagnostics .Append (req .State .Get (ctx , & state )... )
459+ var currentClaims []string
460+ resp .Diagnostics .Append (state .OrgSyncIdpGroups .ElementsAs (ctx , & currentClaims , false )... )
461+
462+ var plannedClaims []string
463+ resp .Diagnostics .Append (data .OrgSyncIdpGroups .ElementsAs (ctx , & plannedClaims , false )... )
464+ if resp .Diagnostics .HasError () {
465+ return
466+ }
467+
468+ resp .Diagnostics .Append (r .patchOrgSyncMapping (ctx , orgID , currentClaims , plannedClaims )... )
469+ if resp .Diagnostics .HasError () {
470+ return
471+ }
472+ }
473+
429474 if ! data .GroupSync .IsNull () {
475+ tflog .Trace (ctx , "updating group sync" , map [string ]any {
476+ "orgID" : orgID ,
477+ })
430478 resp .Diagnostics .Append (r .patchGroupSync (ctx , orgID , data .GroupSync )... )
431479 if resp .Diagnostics .HasError () {
432480 return
433481 }
434482 }
435- tflog .Trace (ctx , "updating role sync" , map [string ]any {
436- "orgID" : orgID ,
437- })
438483 if ! data .RoleSync .IsNull () {
484+ tflog .Trace (ctx , "updating role sync" , map [string ]any {
485+ "orgID" : orgID ,
486+ })
439487 resp .Diagnostics .Append (r .patchRoleSync (ctx , orgID , data .RoleSync )... )
440488 if resp .Diagnostics .HasError () {
441489 return
@@ -456,6 +504,21 @@ func (r *OrganizationResource) Delete(ctx context.Context, req resource.DeleteRe
456504
457505 orgID := data .ID .ValueUUID ()
458506
507+ // Remove org sync mappings, if we were managing them
508+ if ! data .OrgSyncIdpGroups .IsNull () {
509+ tflog .Trace (ctx , "deleting org sync mappings" , map [string ]any {
510+ "orgID" : orgID ,
511+ })
512+
513+ var claims []string
514+ resp .Diagnostics .Append (data .OrgSyncIdpGroups .ElementsAs (ctx , & claims , false )... )
515+ if resp .Diagnostics .HasError () {
516+ return
517+ }
518+
519+ resp .Diagnostics .Append (r .patchOrgSyncMapping (ctx , orgID , claims , []string {})... )
520+ }
521+
459522 tflog .Trace (ctx , "deleting organization" , map [string ]any {
460523 "id" : orgID ,
461524 "name" : data .Name .ValueString (),
@@ -554,3 +617,37 @@ func (r *OrganizationResource) patchRoleSync(
554617
555618 return diags
556619}
620+
621+ func (r * OrganizationResource ) patchOrgSyncMapping (
622+ ctx context.Context ,
623+ orgID uuid.UUID ,
624+ currentClaims , plannedClaims []string ,
625+ ) diag.Diagnostics {
626+ var diags diag.Diagnostics
627+
628+ add , remove := slice .SymmetricDifference (currentClaims , plannedClaims )
629+ var addMappings []codersdk.IDPSyncMapping [uuid.UUID ]
630+ for _ , claim := range add {
631+ addMappings = append (addMappings , codersdk.IDPSyncMapping [uuid.UUID ]{
632+ Given : claim ,
633+ Gets : orgID ,
634+ })
635+ }
636+ var removeMappings []codersdk.IDPSyncMapping [uuid.UUID ]
637+ for _ , claim := range remove {
638+ removeMappings = append (removeMappings , codersdk.IDPSyncMapping [uuid.UUID ]{
639+ Given : claim ,
640+ Gets : orgID ,
641+ })
642+ }
643+
644+ _ , err := r .Client .PatchOrganizationIDPSyncMapping (ctx , codersdk.PatchOrganizationIDPSyncMappingRequest {
645+ Add : addMappings ,
646+ Remove : removeMappings ,
647+ })
648+ if err != nil {
649+ diags .AddError ("Org Sync Update error" , err .Error ())
650+ }
651+
652+ return diags
653+ }
0 commit comments