这是indexloc提供的服务,不要输入任何密码
Skip to content

Create dsync groups data source #344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions client/dsync_groups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package client

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"
)

type DsyncGroup struct {
ID string `json:"id"`
Name string `json:"name"`
}

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, ResolvedTeamID)
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 GetDsyncGroupsResponse{}, err
}

allGroups = append(allGroups, response.Groups...)

if response.Pagination.After == nil {
break
}
after = response.Pagination.After
}

return GetDsyncGroupsResponse{
TeamID: ResolvedTeamID,
Groups: allGroups,
}, nil
}
64 changes: 64 additions & 0 deletions docs/data-sources/dsync_groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "vercel_dsync_groups Data Source - terraform-provider-vercel"
subcategory: ""
description: |-
Provides information about DSync groups for a team.
---

# vercel_dsync_groups (Data Source)

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 generated by tfplugindocs -->
## Schema

### Optional

- `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

- `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.

<a id="nestedatt--list"></a>
### Nested Schema for `list`

Read-Only:

- `id` (String) The ID of the group on Vercel.
- `name` (String) The name of the group on the Identity Provider.
28 changes: 28 additions & 0 deletions examples/data-sources/vercel_dsync_groups/data-source.tf
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}
138 changes: 138 additions & 0 deletions vercel/data_source_dsync_groups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
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_groups"
}

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{
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.",
},
"list": schema.ListNestedAttribute{
Description: "A list 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,
},
},
},
},
"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,
},
},
}
}

type DsyncGroup struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
}

type DsyncGroups struct {
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) {
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 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
}

var groupsList = make([]DsyncGroup, 0, len(out.Groups))
var groupsMap = make(map[string]types.String, len(out.Groups))
for _, g := range out.Groups {
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),
List: groupsList,
Map: groupsMap,
}

tflog.Info(ctx, "read dsync groups", map[string]any{
"team_id": result.TeamID.ValueString(),
})

diags = resp.State.Set(ctx, DsyncGroups(result))
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
37 changes: 37 additions & 0 deletions vercel/data_source_dsync_groups_test.go
Original file line number Diff line number Diff line change
@@ -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, "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"),
),
},
},
})
}

func testAccVercelDsyncGroupsDataSource(teamID string) string {
return fmt.Sprintf(`
data "vercel_dsync_groups" "test" {
team_id = "%s"
}
`, teamID)
}
1 change: 1 addition & 0 deletions vercel/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (p *vercelProvider) DataSources(_ context.Context) []func() datasource.Data
newTeamMemberDataSource,
newMicrofrontendGroupDataSource,
newMicrofrontendGroupMembershipDataSource,
newDsyncGroupsDataSource,
}
}

Expand Down