Skip to content

Commit 071b228

Browse files
authored
new datasource: sentry_all_organization_members (#496)
* introduce sentry_all_organization_members resource * docs update * member email is readonly
1 parent c1eee81 commit 071b228

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

Diff for: docs/data-sources/all_organization_members.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "sentry_all_organization_members Data Source - terraform-provider-sentry"
4+
subcategory: ""
5+
description: |-
6+
Retrieve all organization members.
7+
---
8+
9+
# sentry_all_organization_members (Data Source)
10+
11+
Retrieve all organization members.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `organization` (String) The slug of the organization.
21+
22+
### Read-Only
23+
24+
- `members` (Attributes Set) The list of members. (see [below for nested schema](#nestedatt--members))
25+
26+
<a id="nestedatt--members"></a>
27+
### Nested Schema for `members`
28+
29+
Read-Only:
30+
31+
- `email` (String) The email of the organization member.
32+
- `id` (String) The ID of of the organization member.
33+
- `role` (String) This is the role of the organization member.
+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
"github.com/jianyuan/go-sentry/v2/sentry"
11+
)
12+
13+
var _ datasource.DataSource = &AllOrganizationMembersDataSource{}
14+
var _ datasource.DataSourceWithConfigure = &OrganizationMemberDataSource{}
15+
16+
func NewAllOrganizationMembersDataSource() datasource.DataSource {
17+
return &AllOrganizationMembersDataSource{}
18+
}
19+
20+
type AllOrganizationMembersDataSource struct {
21+
baseDataSource
22+
}
23+
24+
type AllOrganizationMembersDataSourceMemberModel struct {
25+
Id types.String `tfsdk:"id"`
26+
Email types.String `tfsdk:"email"`
27+
Role types.String `tfsdk:"role"`
28+
}
29+
30+
func (m *AllOrganizationMembersDataSourceMemberModel) Fill(organization string, member sentry.OrganizationMember) error {
31+
m.Id = types.StringValue(member.ID)
32+
m.Email = types.StringValue(member.Email)
33+
m.Role = types.StringValue(member.OrgRole)
34+
35+
return nil
36+
}
37+
38+
type AllOrganizationMembersDataSourceModel struct {
39+
Organization types.String `tfsdk:"organization"`
40+
Members []AllOrganizationMembersDataSourceMemberModel `tfsdk:"members"`
41+
}
42+
43+
func (m *AllOrganizationMembersDataSourceModel) Fill(organization string, members []sentry.OrganizationMember) error {
44+
m.Organization = types.StringValue(organization)
45+
46+
for _, member := range members {
47+
mm := AllOrganizationMembersDataSourceMemberModel{}
48+
if err := mm.Fill(organization, member); err != nil {
49+
return err
50+
}
51+
m.Members = append(m.Members, mm)
52+
}
53+
54+
return nil
55+
}
56+
57+
func (d *AllOrganizationMembersDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
58+
resp.TypeName = req.ProviderTypeName + "_all_organization_members"
59+
}
60+
61+
func (d *AllOrganizationMembersDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
62+
resp.Schema = schema.Schema{
63+
MarkdownDescription: "Retrieve all organization members.",
64+
65+
Attributes: map[string]schema.Attribute{
66+
"organization": schema.StringAttribute{
67+
MarkdownDescription: "The slug of the organization.",
68+
Required: true,
69+
},
70+
"members": schema.SetNestedAttribute{
71+
MarkdownDescription: "The list of members.",
72+
Computed: true,
73+
NestedObject: schema.NestedAttributeObject{
74+
Attributes: map[string]schema.Attribute{
75+
"id": schema.StringAttribute{
76+
MarkdownDescription: "The ID of of the organization member.",
77+
Computed: true,
78+
},
79+
"email": schema.StringAttribute{
80+
MarkdownDescription: "The email of the organization member.",
81+
Computed: true,
82+
},
83+
"role": schema.StringAttribute{
84+
MarkdownDescription: "This is the role of the organization member.",
85+
Computed: true,
86+
},
87+
},
88+
},
89+
},
90+
},
91+
}
92+
}
93+
94+
func (d *AllOrganizationMembersDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
95+
var data AllOrganizationMembersDataSourceModel
96+
97+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
98+
if resp.Diagnostics.HasError() {
99+
return
100+
}
101+
102+
var allMembers []sentry.OrganizationMember
103+
params := &sentry.ListCursorParams{}
104+
105+
for {
106+
members, apiResp, err := d.client.OrganizationMembers.List(ctx, data.Organization.ValueString(), params)
107+
if err != nil {
108+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to list organization members, got error: %s", err))
109+
return
110+
}
111+
112+
for _, member := range members {
113+
allMembers = append(allMembers, *member)
114+
}
115+
116+
if apiResp.Cursor == "" {
117+
break
118+
}
119+
params.Cursor = apiResp.Cursor
120+
}
121+
122+
if err := data.Fill(data.Organization.ValueString(), allMembers); err != nil {
123+
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Fill error: %s", err))
124+
return
125+
}
126+
127+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
128+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package provider
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
10+
"github.com/hashicorp/terraform-plugin-testing/statecheck"
11+
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
12+
"github.com/jianyuan/terraform-provider-sentry/internal/acctest"
13+
)
14+
15+
func TestAccAllOrganizationMembersDataSource(t *testing.T) {
16+
rn := "data.sentry_all_organization_members.test"
17+
email := acctest.RandomWithPrefix("tf-member") + "@example.com"
18+
role := "member"
19+
20+
resource.Test(t, resource.TestCase{
21+
PreCheck: func() { acctest.PreCheck(t) },
22+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
23+
Steps: []resource.TestStep{
24+
{
25+
Config: testAccAllOrganizationMembersConfig(email, role),
26+
ConfigStateChecks: []statecheck.StateCheck{
27+
statecheck.ExpectKnownValue(rn, tfjsonpath.New("organization"), knownvalue.StringExact(acctest.TestOrganization)),
28+
statecheck.ExpectKnownValue(rn, tfjsonpath.New("members"), knownvalue.SetPartial([]knownvalue.Check{
29+
knownvalue.ObjectExact(map[string]knownvalue.Check{
30+
"id": knownvalue.StringRegexp(regexp.MustCompile(`^\d+$`)),
31+
"email": knownvalue.StringExact(email),
32+
"role": knownvalue.StringExact(role),
33+
}),
34+
})),
35+
},
36+
},
37+
},
38+
})
39+
}
40+
41+
func testAccAllOrganizationMembersConfig(email string, role string) string {
42+
return testAccOrganizationDataSourceConfig + fmt.Sprintf(`
43+
resource "sentry_organization_member" "test" {
44+
organization = data.sentry_organization.test.id
45+
email = "%[1]s"
46+
role = "%[2]s"
47+
}
48+
49+
data "sentry_all_organization_members" "test" {
50+
organization = data.sentry_organization.test.id
51+
52+
depends_on = [sentry_organization_member.test]
53+
}
54+
`, email, role)
55+
}

Diff for: internal/provider/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ func (p *SentryProvider) DataSources(ctx context.Context) []func() datasource.Da
112112
return []func() datasource.DataSource{
113113
NewAllClientKeysDataSource,
114114
NewAllProjectsDataSource,
115+
NewAllOrganizationMembersDataSource,
115116
NewClientKeyDataSource,
116117
NewIssueAlertDataSource,
117118
NewOrganizationDataSource,

0 commit comments

Comments
 (0)