From 20dfecc4e981be2c8a802c23986b8217f9cf4d1a Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 10:42:42 +0200 Subject: [PATCH 01/15] Create dsync groups data source --- client/dsync_groups.go | 58 +++++++++++++ docs/data-sources/dsync_group.md | 32 ++++++++ vercel/data_source_dsync_groups.go | 126 +++++++++++++++++++++++++++++ vercel/provider.go | 1 + 4 files changed, 217 insertions(+) create mode 100644 client/dsync_groups.go create mode 100644 docs/data-sources/dsync_group.md create mode 100644 vercel/data_source_dsync_groups.go diff --git a/client/dsync_groups.go b/client/dsync_groups.go new file mode 100644 index 00000000..919aae37 --- /dev/null +++ b/client/dsync_groups.go @@ -0,0 +1,58 @@ +package client + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +type DsyncGroup struct { + ID string `json:"id"` + Name string `json:"name"` +} + +type DsyncGroups struct { + Groups []DsyncGroup `json:"groups"` +} + +func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) (DsyncGroups, error) { + var allGroups []DsyncGroup + var after *string + + for { + url := fmt.Sprintf("%s/teams/%s/dsync/groups", c.baseURL, TeamID) + if after != nil { + url = fmt.Sprintf("%s?after=%s", url, *after) + } + tflog.Info(ctx, "getting dsync groups", map[string]any{ + "url": url, + }) + + var response struct { + Groups []DsyncGroup `json:"groups"` + Pagination struct { + Before *string `json:"before"` + After *string `json:"after"` + } `json:"pagination"` + } + err := c.doRequest(clientRequest{ + ctx: ctx, + method: "GET", + url: url, + body: "", + }, &response) + if err != nil { + return DsyncGroups{}, err + } + + allGroups = append(allGroups, response.Groups...) + + if response.Pagination.After == nil { + break + } + after = response.Pagination.After + } + + return DsyncGroups{Groups: allGroups}, nil +} diff --git a/docs/data-sources/dsync_group.md b/docs/data-sources/dsync_group.md new file mode 100644 index 00000000..6c43f363 --- /dev/null +++ b/docs/data-sources/dsync_group.md @@ -0,0 +1,32 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "vercel_dsync_group Data Source - terraform-provider-vercel" +subcategory: "" +description: |- + Provides information about DSync groups for a team. +--- + +# vercel_dsync_group (Data Source) + +Provides information about DSync groups for a team. + + + + +## Schema + +### Required + +- `team_id` (String) The ID of the team to retrieve DSync groups for. + +### Read-Only + +- `groups` (Attributes Map) A map of DSync groups for the team. (see [below for nested schema](#nestedatt--groups)) + + +### Nested Schema for `groups` + +Read-Only: + +- `id` (String) The ID of the group on Vercel. +- `name` (String) The name of the group on the Identity Provider. diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go new file mode 100644 index 00000000..5ac4f4bc --- /dev/null +++ b/vercel/data_source_dsync_groups.go @@ -0,0 +1,126 @@ +package vercel + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/vercel/terraform-provider-vercel/v3/client" +) + +var ( + _ datasource.DataSource = &dsyncGroupsDataSource{} + _ datasource.DataSourceWithConfigure = &dsyncGroupsDataSource{} +) + +func newDsyncGroupsDataSource() datasource.DataSource { + return &dsyncGroupsDataSource{} +} + +type dsyncGroupsDataSource struct { + client *client.Client +} + +func (d *dsyncGroupsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_dsync_group" +} + +func (d *dsyncGroupsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*client.Client) + if !ok { + resp.Diagnostics.AddError( + "Unexpected DataSource Configure Type", + fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + d.client = client +} + +func (d *dsyncGroupsDataSource) Schema(_ context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Provides information about DSync groups for a team.", + Attributes: map[string]schema.Attribute{ + "team_id": schema.StringAttribute{ + Description: "The ID of the team to retrieve DSync groups for.", + Required: true, + }, + "groups": schema.MapNestedAttribute{ + Description: "A map of DSync groups for the team.", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "The ID of the group on Vercel.", + Computed: true, + }, + "name": schema.StringAttribute{ + Description: "The name of the group on the Identity Provider.", + Computed: true, + }, + }, + }, + }, + }, + } +} + +type DsyncGroup struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` +} + +type DsyncGroups struct { + TeamID types.String `tfsdk:"team_id"` + Groups map[string]DsyncGroup `tfsdk:"groups"` +} + +func responseToDsyncGroups(out client.DsyncGroups) DsyncGroups { + return DsyncGroups{ + Groups: make(map[string]DsyncGroup, len(out.Groups)), + } +} + +func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var config DsyncGroups + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + out, err := d.client.GetDsyncGroups(ctx, config.TeamID.ValueString()) + if client.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + "Error reading DSync Groups", + fmt.Sprintf("Could not get DSync Groups for team %s, unexpected error: %s", + config.TeamID.ValueString(), + err, + ), + ) + return + } + + result := responseToDsyncGroups(out) + tflog.Info(ctx, "read dsync groups", map[string]any{ + "team_id": result.TeamID.ValueString(), + }) + + diags = resp.State.Set(ctx, result) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} diff --git a/vercel/provider.go b/vercel/provider.go index a7cc8637..da2bf870 100644 --- a/vercel/provider.go +++ b/vercel/provider.go @@ -109,6 +109,7 @@ func (p *vercelProvider) DataSources(_ context.Context) []func() datasource.Data newTeamMemberDataSource, newMicrofrontendGroupDataSource, newMicrofrontendGroupMembershipDataSource, + newDsyncGroupsDataSource, } } From 7d75811813cc28185cbf39ac72c997faebaec496 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 15:16:24 +0200 Subject: [PATCH 02/15] add test --- vercel/data_source_dsync_groups_test.go | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 vercel/data_source_dsync_groups_test.go diff --git a/vercel/data_source_dsync_groups_test.go b/vercel/data_source_dsync_groups_test.go new file mode 100644 index 00000000..2bd4fcc2 --- /dev/null +++ b/vercel/data_source_dsync_groups_test.go @@ -0,0 +1,37 @@ +package vercel_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAcc_DsyncGroupsDataSource(t *testing.T) { + resourceName := "data.vercel_dsync_groups.test" + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccVercelDsyncGroupsDataSource(testTeam(t)), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "team_id", testTeam(t)), + resource.TestCheckResourceAttrSet(resourceName, "groups.#"), + resource.TestCheckResourceAttrSet(resourceName, "groups.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "groups.0.name"), + resource.TestCheckResourceAttrSet(resourceName, "groups.1.id"), + resource.TestCheckResourceAttrSet(resourceName, "groups.1.name"), + ), + }, + }, + }) +} + +func testAccVercelDsyncGroupsDataSource(teamID string) string { + return fmt.Sprintf(` +data "vercel_dsync_groups" "test" { + team_id = "%s" +} +`, teamID) +} From 0086b51b88a07f10820fe5054092d114a2f575c8 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 15:34:32 +0200 Subject: [PATCH 03/15] fix plurality --- vercel/data_source_dsync_groups.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index 5ac4f4bc..47462b9f 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -25,7 +25,7 @@ type dsyncGroupsDataSource struct { } func (d *dsyncGroupsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_dsync_group" + resp.TypeName = req.ProviderTypeName + "_dsync_groups" } func (d *dsyncGroupsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { From e4c50d2f3d209d1c9e8d1338d85723dfd6bbcaa2 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 15:55:13 +0200 Subject: [PATCH 04/15] update docs --- docs/data-sources/{dsync_group.md => dsync_groups.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename docs/data-sources/{dsync_group.md => dsync_groups.md} (85%) diff --git a/docs/data-sources/dsync_group.md b/docs/data-sources/dsync_groups.md similarity index 85% rename from docs/data-sources/dsync_group.md rename to docs/data-sources/dsync_groups.md index 6c43f363..ab64e426 100644 --- a/docs/data-sources/dsync_group.md +++ b/docs/data-sources/dsync_groups.md @@ -1,12 +1,12 @@ --- # generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "vercel_dsync_group Data Source - terraform-provider-vercel" +page_title: "vercel_dsync_groups Data Source - terraform-provider-vercel" subcategory: "" description: |- Provides information about DSync groups for a team. --- -# vercel_dsync_group (Data Source) +# vercel_dsync_groups (Data Source) Provides information about DSync groups for a team. From 47b371ba969a61203160b69a958400f4fd91db1d Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 16:51:44 +0200 Subject: [PATCH 05/15] use ListNestedAttribute --- vercel/data_source_dsync_groups.go | 2 +- vercel/data_source_dsync_groups_test.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index 47462b9f..3d0a3d54 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -53,7 +53,7 @@ func (d *dsyncGroupsDataSource) Schema(_ context.Context, req datasource.SchemaR Description: "The ID of the team to retrieve DSync groups for.", Required: true, }, - "groups": schema.MapNestedAttribute{ + "groups": schema.ListNestedAttribute{ Description: "A map of DSync groups for the team.", Computed: true, NestedObject: schema.NestedAttributeObject{ diff --git a/vercel/data_source_dsync_groups_test.go b/vercel/data_source_dsync_groups_test.go index 2bd4fcc2..724b416a 100644 --- a/vercel/data_source_dsync_groups_test.go +++ b/vercel/data_source_dsync_groups_test.go @@ -16,7 +16,6 @@ func TestAcc_DsyncGroupsDataSource(t *testing.T) { { Config: testAccVercelDsyncGroupsDataSource(testTeam(t)), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "team_id", testTeam(t)), resource.TestCheckResourceAttrSet(resourceName, "groups.#"), resource.TestCheckResourceAttrSet(resourceName, "groups.0.id"), resource.TestCheckResourceAttrSet(resourceName, "groups.0.name"), @@ -31,7 +30,7 @@ func TestAcc_DsyncGroupsDataSource(t *testing.T) { func testAccVercelDsyncGroupsDataSource(teamID string) string { return fmt.Sprintf(` data "vercel_dsync_groups" "test" { - team_id = "%s" + team_id = "%s" } `, teamID) } From 98087dddc712cf316d70b6600f04584423174fff Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 16:55:09 +0200 Subject: [PATCH 06/15] update docs --- docs/data-sources/dsync_groups.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-sources/dsync_groups.md b/docs/data-sources/dsync_groups.md index ab64e426..1cc1b34c 100644 --- a/docs/data-sources/dsync_groups.md +++ b/docs/data-sources/dsync_groups.md @@ -21,7 +21,7 @@ Provides information about DSync groups for a team. ### Read-Only -- `groups` (Attributes Map) A map of DSync groups for the team. (see [below for nested schema](#nestedatt--groups)) +- `groups` (Attributes List) A map of DSync groups for the team. (see [below for nested schema](#nestedatt--groups)) ### Nested Schema for `groups` From f41ccdefe78c21f1f52269318cbf90795909c037 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Wed, 11 Jun 2025 17:40:56 +0200 Subject: [PATCH 07/15] fix result --- client/dsync_groups.go | 10 +++------- vercel/data_source_dsync_groups.go | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/client/dsync_groups.go b/client/dsync_groups.go index 919aae37..19054a7f 100644 --- a/client/dsync_groups.go +++ b/client/dsync_groups.go @@ -12,11 +12,7 @@ type DsyncGroup struct { Name string `json:"name"` } -type DsyncGroups struct { - Groups []DsyncGroup `json:"groups"` -} - -func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) (DsyncGroups, error) { +func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) ([]DsyncGroup, error) { var allGroups []DsyncGroup var after *string @@ -43,7 +39,7 @@ func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) (DsyncGroups body: "", }, &response) if err != nil { - return DsyncGroups{}, err + return nil, err } allGroups = append(allGroups, response.Groups...) @@ -54,5 +50,5 @@ func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) (DsyncGroups after = response.Pagination.After } - return DsyncGroups{Groups: allGroups}, nil + return allGroups, nil } diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index 3d0a3d54..a6092511 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -79,14 +79,8 @@ type DsyncGroup struct { } type DsyncGroups struct { - TeamID types.String `tfsdk:"team_id"` - Groups map[string]DsyncGroup `tfsdk:"groups"` -} - -func responseToDsyncGroups(out client.DsyncGroups) DsyncGroups { - return DsyncGroups{ - Groups: make(map[string]DsyncGroup, len(out.Groups)), - } + TeamID types.String `tfsdk:"team_id"` + Groups []DsyncGroup `tfsdk:"groups"` } func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -113,12 +107,24 @@ func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadReq return } - result := responseToDsyncGroups(out) + var groups = make([]DsyncGroup, 0, len(out)) + for _, g := range out { + groups = append(groups, DsyncGroup{ + ID: types.StringValue(g.ID), + Name: types.StringValue(g.Name), + }) + } + + result := DsyncGroups{ + TeamID: config.TeamID, + Groups: groups, + } + tflog.Info(ctx, "read dsync groups", map[string]any{ "team_id": result.TeamID.ValueString(), }) - diags = resp.State.Set(ctx, result) + diags = resp.State.Set(ctx, DsyncGroups(result)) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return From c91a5bd3721de0cc3811ab7ad48a63b5e5e1a3a4 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:02:05 +0200 Subject: [PATCH 08/15] make TeamID optional --- client/dsync_groups.go | 18 ++++++++++++++---- vercel/data_source_dsync_groups.go | 13 +++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/client/dsync_groups.go b/client/dsync_groups.go index 19054a7f..a0c7e53e 100644 --- a/client/dsync_groups.go +++ b/client/dsync_groups.go @@ -12,12 +12,19 @@ type DsyncGroup struct { Name string `json:"name"` } -func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) ([]DsyncGroup, error) { +type GetDsyncGroupsResponse struct { + TeamID string `json:"teamId"` + Groups []DsyncGroup `json:"groups"` +} + +func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) (GetDsyncGroupsResponse, error) { var allGroups []DsyncGroup var after *string + var ResolvedTeamID = c.TeamID(TeamID) + for { - url := fmt.Sprintf("%s/teams/%s/dsync/groups", c.baseURL, TeamID) + url := fmt.Sprintf("%s/teams/%s/dsync/groups", c.baseURL, ResolvedTeamID) if after != nil { url = fmt.Sprintf("%s?after=%s", url, *after) } @@ -39,7 +46,7 @@ func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) ([]DsyncGrou body: "", }, &response) if err != nil { - return nil, err + return GetDsyncGroupsResponse{}, err } allGroups = append(allGroups, response.Groups...) @@ -50,5 +57,8 @@ func (c *Client) GetDsyncGroups(ctx context.Context, TeamID string) ([]DsyncGrou after = response.Pagination.After } - return allGroups, nil + return GetDsyncGroupsResponse{ + TeamID: ResolvedTeamID, + Groups: allGroups, + }, nil } diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index a6092511..8321fd64 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -50,11 +50,12 @@ func (d *dsyncGroupsDataSource) Schema(_ context.Context, req datasource.SchemaR Description: "Provides information about DSync groups for a team.", Attributes: map[string]schema.Attribute{ "team_id": schema.StringAttribute{ - Description: "The ID of the team to retrieve DSync groups for.", - Required: true, + Optional: true, + Computed: true, + Description: "The ID of the team the Dsync Groups are associated to. Required when configuring a team resource if a default team has not been set in the provider.", }, "groups": schema.ListNestedAttribute{ - Description: "A map of DSync groups for the team.", + Description: "A list of DSync groups for the team.", Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ @@ -107,8 +108,8 @@ func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadReq return } - var groups = make([]DsyncGroup, 0, len(out)) - for _, g := range out { + var groups = make([]DsyncGroup, 0, len(out.Groups)) + for _, g := range out.Groups { groups = append(groups, DsyncGroup{ ID: types.StringValue(g.ID), Name: types.StringValue(g.Name), @@ -116,7 +117,7 @@ func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadReq } result := DsyncGroups{ - TeamID: config.TeamID, + TeamID: types.StringValue(out.TeamID), Groups: groups, } From c7fe8741e9d14f6c2bffafd6d44d1bfce260c127 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:06:29 +0200 Subject: [PATCH 09/15] remove notfound check --- vercel/data_source_dsync_groups.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index 8321fd64..41afd616 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -93,10 +93,6 @@ func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadReq } out, err := d.client.GetDsyncGroups(ctx, config.TeamID.ValueString()) - if client.NotFound(err) { - resp.State.RemoveResource(ctx) - return - } if err != nil { resp.Diagnostics.AddError( "Error reading DSync Groups", From 42dad783bf632be26866c211f7aea613f9a2b3bc Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:28:12 +0200 Subject: [PATCH 10/15] add map attribute --- vercel/data_source_dsync_groups.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/vercel/data_source_dsync_groups.go b/vercel/data_source_dsync_groups.go index 41afd616..53550ec9 100644 --- a/vercel/data_source_dsync_groups.go +++ b/vercel/data_source_dsync_groups.go @@ -54,7 +54,7 @@ func (d *dsyncGroupsDataSource) Schema(_ context.Context, req datasource.SchemaR Computed: true, Description: "The ID of the team the Dsync Groups are associated to. Required when configuring a team resource if a default team has not been set in the provider.", }, - "groups": schema.ListNestedAttribute{ + "list": schema.ListNestedAttribute{ Description: "A list of DSync groups for the team.", Computed: true, NestedObject: schema.NestedAttributeObject{ @@ -70,6 +70,11 @@ func (d *dsyncGroupsDataSource) Schema(_ context.Context, req datasource.SchemaR }, }, }, + "map": schema.MapAttribute{ + Description: "A map of Identity Provider group names to their Vercel IDs. This can be used to look up the ID of a group by its name using the [lookup](https://developer.hashicorp.com/terraform/language/functions/lookup) function.", + Computed: true, + ElementType: types.StringType, + }, }, } } @@ -80,8 +85,9 @@ type DsyncGroup struct { } type DsyncGroups struct { - TeamID types.String `tfsdk:"team_id"` - Groups []DsyncGroup `tfsdk:"groups"` + TeamID types.String `tfsdk:"team_id"` + List []DsyncGroup `tfsdk:"list"` + Map map[string]types.String `tfsdk:"map"` } func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -104,17 +110,20 @@ func (d *dsyncGroupsDataSource) Read(ctx context.Context, req datasource.ReadReq return } - var groups = make([]DsyncGroup, 0, len(out.Groups)) + var groupsList = make([]DsyncGroup, 0, len(out.Groups)) + var groupsMap = make(map[string]types.String, len(out.Groups)) for _, g := range out.Groups { - groups = append(groups, DsyncGroup{ + groupsList = append(groupsList, DsyncGroup{ ID: types.StringValue(g.ID), Name: types.StringValue(g.Name), }) + groupsMap[g.Name] = types.StringValue(g.ID) } result := DsyncGroups{ TeamID: types.StringValue(out.TeamID), - Groups: groups, + List: groupsList, + Map: groupsMap, } tflog.Info(ctx, "read dsync groups", map[string]any{ From 921be336a4092477951e7225c0a7890d53874c97 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:28:18 +0200 Subject: [PATCH 11/15] create example --- .../vercel_dsync_groups/data-source.tf | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 examples/data-sources/vercel_dsync_groups/data-source.tf diff --git a/examples/data-sources/vercel_dsync_groups/data-source.tf b/examples/data-sources/vercel_dsync_groups/data-source.tf new file mode 100644 index 00000000..aa15da30 --- /dev/null +++ b/examples/data-sources/vercel_dsync_groups/data-source.tf @@ -0,0 +1,28 @@ +data "vercel_dsync_groups" "example" { + team_id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" +} + +resource "vercel_access_group" "contractor" { + team_id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" + name = "contractor" + description = "Access group for contractors" +} + +resource "vercel_team_config" "example" { + id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" + saml = { + enforced = true + roles = { + lookup(vercel_dsync_groups.example.map, "admin") = { + role = "OWNER" + } + lookup(vercel_dsync_groups.example.map, "finance") = { + role = "BILLING" + } + lookup(vercel_dsync_groups.example.map, "contractor") = { + role = "CONTRIBUTOR" + access_group_id = vercel_access_group.contractor.id + } + } + } +} \ No newline at end of file From 42bee638aeb414156f033fedc3b4ac2419b37f57 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:28:42 +0200 Subject: [PATCH 12/15] update docs --- docs/data-sources/dsync_groups.md | 42 +++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/data-sources/dsync_groups.md b/docs/data-sources/dsync_groups.md index 1cc1b34c..5b0b36d0 100644 --- a/docs/data-sources/dsync_groups.md +++ b/docs/data-sources/dsync_groups.md @@ -10,21 +10,53 @@ description: |- Provides information about DSync groups for a team. +## Example Usage +```terraform +data "vercel_dsync_groups" "example" { + team_id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" +} + +resource "vercel_access_group" "contractor" { + team_id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" + name = "contractor" + description = "Access group for contractors" +} + +resource "vercel_team_config" "example" { + id = "team_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" + saml = { + enforced = true + roles = { + lookup(vercel_dsync_groups.example.map, "admin") = { + role = "OWNER" + } + lookup(vercel_dsync_groups.example.map, "finance") = { + role = "BILLING" + } + lookup(vercel_dsync_groups.example.map, "contractor") = { + role = "CONTRIBUTOR" + access_group_id = vercel_access_group.contractor.id + } + } + } +} +``` ## Schema -### Required +### Optional -- `team_id` (String) The ID of the team to retrieve DSync groups for. +- `team_id` (String) The ID of the team the Dsync Groups are associated to. Required when configuring a team resource if a default team has not been set in the provider. ### Read-Only -- `groups` (Attributes List) A map of DSync groups for the team. (see [below for nested schema](#nestedatt--groups)) +- `list` (Attributes List) A list of DSync groups for the team. (see [below for nested schema](#nestedatt--list)) +- `map` (Map of String) A map of Identity Provider group names to their Vercel IDs. This can be used to look up the ID of a group by its name using the [lookup](https://developer.hashicorp.com/terraform/language/functions/lookup) function. - -### Nested Schema for `groups` + +### Nested Schema for `list` Read-Only: From 084bb3947ca8fc354deedba8ba51434f0a3903cc Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 11:29:57 +0200 Subject: [PATCH 13/15] line-break --- examples/data-sources/vercel_dsync_groups/data-source.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data-sources/vercel_dsync_groups/data-source.tf b/examples/data-sources/vercel_dsync_groups/data-source.tf index aa15da30..4fd1de63 100644 --- a/examples/data-sources/vercel_dsync_groups/data-source.tf +++ b/examples/data-sources/vercel_dsync_groups/data-source.tf @@ -25,4 +25,4 @@ resource "vercel_team_config" "example" { } } } -} \ No newline at end of file +} From 5c8f05e0cb2337cc8b89aeb3593fb77e9122847c Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 13:10:25 +0200 Subject: [PATCH 14/15] fix tests --- vercel/data_source_dsync_groups_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vercel/data_source_dsync_groups_test.go b/vercel/data_source_dsync_groups_test.go index 724b416a..323dc511 100644 --- a/vercel/data_source_dsync_groups_test.go +++ b/vercel/data_source_dsync_groups_test.go @@ -16,11 +16,11 @@ func TestAcc_DsyncGroupsDataSource(t *testing.T) { { Config: testAccVercelDsyncGroupsDataSource(testTeam(t)), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "groups.#"), - resource.TestCheckResourceAttrSet(resourceName, "groups.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "groups.0.name"), - resource.TestCheckResourceAttrSet(resourceName, "groups.1.id"), - resource.TestCheckResourceAttrSet(resourceName, "groups.1.name"), + resource.TestCheckResourceAttrSet(resourceName, "list.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "list.0.name"), + resource.TestCheckResourceAttrSet(resourceName, "list.1.id"), + resource.TestCheckResourceAttrSet(resourceName, "list.1.name"), + resource.TestCheckResourceAttrSet(resourceName, "map"), ), }, }, From 389501e584e4872ba21539065ea213f447387c74 Mon Sep 17 00:00:00 2001 From: Marc Greenstock Date: Thu, 12 Jun 2025 13:25:54 +0200 Subject: [PATCH 15/15] check length of map and list --- vercel/data_source_dsync_groups_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vercel/data_source_dsync_groups_test.go b/vercel/data_source_dsync_groups_test.go index 323dc511..5574039f 100644 --- a/vercel/data_source_dsync_groups_test.go +++ b/vercel/data_source_dsync_groups_test.go @@ -16,11 +16,12 @@ func TestAcc_DsyncGroupsDataSource(t *testing.T) { { Config: testAccVercelDsyncGroupsDataSource(testTeam(t)), Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "list.#", "2"), + resource.TestCheckResourceAttr(resourceName, "map.%", "2"), resource.TestCheckResourceAttrSet(resourceName, "list.0.id"), resource.TestCheckResourceAttrSet(resourceName, "list.0.name"), resource.TestCheckResourceAttrSet(resourceName, "list.1.id"), resource.TestCheckResourceAttrSet(resourceName, "list.1.name"), - resource.TestCheckResourceAttrSet(resourceName, "map"), ), }, },