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