Skip to content

Commit 32ed585

Browse files
authored
Merge pull request #264 from ilpianista/feature/data-gitlab-group-membership
Add new data source gitlab_group_membership
2 parents f201ea2 + 1d3b41d commit 32ed585

File tree

5 files changed

+328
-5
lines changed

5 files changed

+328
-5
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
10+
"github.com/xanzy/go-gitlab"
11+
)
12+
13+
func dataSourceGitlabGroupMembership() *schema.Resource {
14+
acceptedAccessLevels := make([]string, 0, len(accessLevelID))
15+
for k := range accessLevelID {
16+
acceptedAccessLevels = append(acceptedAccessLevels, k)
17+
}
18+
return &schema.Resource{
19+
Read: dataSourceGitlabGroupMembershipRead,
20+
Schema: map[string]*schema.Schema{
21+
"group_id": {
22+
Type: schema.TypeInt,
23+
Computed: true,
24+
Optional: true,
25+
ConflictsWith: []string{
26+
"full_path",
27+
},
28+
},
29+
"full_path": {
30+
Type: schema.TypeString,
31+
Computed: true,
32+
Optional: true,
33+
ConflictsWith: []string{
34+
"group_id",
35+
},
36+
},
37+
"access_level": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
Optional: true,
41+
ValidateFunc: validateValueFunc(acceptedAccessLevels),
42+
},
43+
"members": {
44+
Type: schema.TypeList,
45+
Computed: true,
46+
Elem: &schema.Resource{
47+
Schema: map[string]*schema.Schema{
48+
"id": {
49+
Type: schema.TypeInt,
50+
Computed: true,
51+
},
52+
"username": {
53+
Type: schema.TypeString,
54+
Computed: true,
55+
},
56+
"name": {
57+
Type: schema.TypeString,
58+
Computed: true,
59+
},
60+
"state": {
61+
Type: schema.TypeString,
62+
Computed: true,
63+
},
64+
"avatar_url": {
65+
Type: schema.TypeString,
66+
Computed: true,
67+
},
68+
"web_url": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
},
72+
"access_level": {
73+
Type: schema.TypeString,
74+
Computed: true,
75+
},
76+
"expires_at": {
77+
Type: schema.TypeString,
78+
Computed: true,
79+
},
80+
},
81+
},
82+
},
83+
},
84+
}
85+
}
86+
87+
func dataSourceGitlabGroupMembershipRead(d *schema.ResourceData, meta interface{}) error {
88+
client := meta.(*gitlab.Client)
89+
90+
var gm []*gitlab.GroupMember
91+
var group *gitlab.Group
92+
var err error
93+
94+
log.Printf("[INFO] Reading Gitlab group")
95+
96+
groupIDData, groupIDOk := d.GetOk("group_id")
97+
fullPathData, fullPathOk := d.GetOk("full_path")
98+
99+
if groupIDOk {
100+
// Get group by id
101+
group, _, err = client.Groups.GetGroup(groupIDData.(int))
102+
if err != nil {
103+
return err
104+
}
105+
} else if fullPathOk {
106+
// Get group by full path
107+
group, _, err = client.Groups.GetGroup(fullPathData.(string))
108+
if err != nil {
109+
return err
110+
}
111+
} else {
112+
return fmt.Errorf("one and only one of group_id or full_path must be set")
113+
}
114+
115+
log.Printf("[INFO] Reading Gitlab group memberships")
116+
117+
// Get group memberships
118+
gm, _, err = client.Groups.ListGroupMembers(group.ID, &gitlab.ListGroupMembersOptions{})
119+
if err != nil {
120+
return err
121+
}
122+
123+
d.Set("group_id", group.ID)
124+
d.Set("full_path", group.FullPath)
125+
126+
d.Set("members", flattenGitlabMembers(d, gm))
127+
128+
var optionsHash strings.Builder
129+
optionsHash.WriteString(strconv.Itoa(group.ID))
130+
131+
if data, ok := d.GetOk("access_level"); ok {
132+
optionsHash.WriteString(data.(string))
133+
}
134+
135+
id := schema.HashString(optionsHash.String())
136+
d.SetId(fmt.Sprintf("%d", id))
137+
138+
return nil
139+
}
140+
141+
func flattenGitlabMembers(d *schema.ResourceData, members []*gitlab.GroupMember) []interface{} {
142+
membersList := []interface{}{}
143+
144+
var filterAccessLevel gitlab.AccessLevelValue = gitlab.NoPermissions
145+
if data, ok := d.GetOk("access_level"); ok {
146+
filterAccessLevel = accessLevelID[data.(string)]
147+
}
148+
149+
for _, member := range members {
150+
if filterAccessLevel != gitlab.NoPermissions && filterAccessLevel != member.AccessLevel {
151+
continue
152+
}
153+
154+
values := map[string]interface{}{
155+
"id": member.ID,
156+
"username": member.Username,
157+
"name": member.Name,
158+
"state": member.State,
159+
"avatar_url": member.AvatarURL,
160+
"web_url": member.WebURL,
161+
"access_level": accessLevel[gitlab.AccessLevelValue(member.AccessLevel)],
162+
}
163+
164+
if member.ExpiresAt != nil {
165+
values["expires_at"] = member.ExpiresAt.String()
166+
}
167+
168+
membersList = append(membersList, values)
169+
}
170+
171+
return membersList
172+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
9+
)
10+
11+
func TestAccDataSourceGitlabMembership_basic(t *testing.T) {
12+
rInt := acctest.RandInt()
13+
14+
resource.Test(t, resource.TestCase{
15+
PreCheck: func() { testAccPreCheck(t) },
16+
Providers: testAccProviders,
17+
Steps: []resource.TestStep{
18+
// Create the group and one member
19+
{
20+
Config: testAccDataSourceGitlabGroupMembershipConfig(rInt),
21+
Check: resource.ComposeTestCheckFunc(
22+
resource.TestCheckResourceAttr("gitlab_group.foo", "name", fmt.Sprintf("foo%d", rInt)),
23+
resource.TestCheckResourceAttr("gitlab_user.test", "name", fmt.Sprintf("foo%d", rInt)),
24+
resource.TestCheckResourceAttr("gitlab_group_membership.foo", "access_level", "developer"),
25+
),
26+
},
27+
{
28+
Config: testAccDataSourceGitlabGroupMembershipConfig_basic(rInt),
29+
Check: resource.ComposeTestCheckFunc(
30+
// Members is 2 because the user owning the token is always added to the group
31+
resource.TestCheckResourceAttr("data.gitlab_group_membership.foo", "members.#", "2"),
32+
resource.TestCheckResourceAttr("data.gitlab_group_membership.foo", "members.1.username", fmt.Sprintf("listest%d", rInt)),
33+
),
34+
},
35+
36+
// Get group using its ID, but return maintainers only
37+
{
38+
Config: testAccDataSourceGitlabGroupMembershipConfigFilterAccessLevel(rInt),
39+
Check: resource.ComposeTestCheckFunc(
40+
resource.TestCheckResourceAttr("data.gitlab_group_membership.foomaintainers", "members.#", "0"),
41+
),
42+
},
43+
},
44+
})
45+
}
46+
47+
func testAccDataSourceGitlabGroupMembershipConfig(rInt int) string {
48+
return fmt.Sprintf(`
49+
resource "gitlab_group" "foo" {
50+
name = "foo%d"
51+
path = "foo%d"
52+
}
53+
54+
resource "gitlab_user" "test" {
55+
name = "foo%d"
56+
username = "listest%d"
57+
password = "test%dtt"
58+
email = "listest%[email protected]"
59+
}
60+
61+
resource "gitlab_group_membership" "foo" {
62+
group_id = "${gitlab_group.foo.id}"
63+
user_id = "${gitlab_user.test.id}"
64+
access_level = "developer"
65+
}`, rInt, rInt, rInt, rInt, rInt, rInt)
66+
}
67+
68+
func testAccDataSourceGitlabGroupMembershipConfig_basic(rInt int) string {
69+
return fmt.Sprintf(`
70+
resource "gitlab_group" "foo" {
71+
name = "foo%d"
72+
path = "foo%d"
73+
}
74+
75+
data "gitlab_group_membership" "foo" {
76+
group_id = "${gitlab_group.foo.id}"
77+
}`, rInt, rInt)
78+
}
79+
80+
func testAccDataSourceGitlabGroupMembershipConfigFilterAccessLevel(rInt int) string {
81+
return fmt.Sprintf(`
82+
resource "gitlab_group" "foo" {
83+
name = "foo%d"
84+
path = "foo%d"
85+
}
86+
87+
data "gitlab_group_membership" "foomaintainers" {
88+
group_id = "${gitlab_group.foo.id}"
89+
access_level = "maintainer"
90+
}`, rInt, rInt)
91+
}

gitlab/provider.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@ func Provider() terraform.ResourceProvider {
5454
},
5555

5656
DataSourcesMap: map[string]*schema.Resource{
57-
"gitlab_group": dataSourceGitlabGroup(),
58-
"gitlab_project": dataSourceGitlabProject(),
59-
"gitlab_projects": dataSourceGitlabProjects(),
60-
"gitlab_user": dataSourceGitlabUser(),
61-
"gitlab_users": dataSourceGitlabUsers(),
57+
"gitlab_group": dataSourceGitlabGroup(),
58+
"gitlab_group_membership": dataSourceGitlabGroupMembership(),
59+
"gitlab_project": dataSourceGitlabProject(),
60+
"gitlab_projects": dataSourceGitlabProjects(),
61+
"gitlab_user": dataSourceGitlabUser(),
62+
"gitlab_users": dataSourceGitlabUsers(),
6263
},
6364

6465
ResourcesMap: map[string]*schema.Resource{
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
layout: "gitlab"
3+
page_title: "GitLab: gitlab_group_membership"
4+
sidebar_current: "docs-gitlab-data-source-group-membership"
5+
description: |-
6+
Looks up gitlab group membership
7+
---
8+
9+
# gitlab\_group\_membership
10+
11+
Provides details about a list of group members in the gitlab provider. The results include id, username, name and more about the requested members.
12+
13+
## Example Usage
14+
15+
**By group's ID**
16+
17+
```hcl
18+
data "gitlab_group_membership" "example" {
19+
group_id = 123
20+
}
21+
```
22+
23+
**By group's full path**
24+
25+
```hcl
26+
data "gitlab_group_membership" "example" {
27+
full_path = "foo/bar"
28+
}
29+
```
30+
31+
## Argument Reference
32+
33+
The following arguments are supported:
34+
35+
* `group_id` - (Optional) The ID of the group.
36+
37+
* `full_path` - (Optional) The full path of the group.
38+
39+
* `access_level` - (Optional) Only return members with the desidered access level. Acceptable values are: `guest`, `reporter`, `developer`, `maintainer`, `owner`.
40+
41+
**Note**: exactly one of group_id or full_path must be provided.
42+
43+
## Attributes Reference
44+
45+
The following attributes are exported:
46+
47+
* `members` - The list of group members.
48+
* `id` - The unique id assigned to the user by the gitlab server.
49+
* `username` - The username of the user.
50+
* `name` - The name of the user.
51+
* `state` - Whether the user is active or blocked.
52+
* `avatar_url` - The avatar URL of the user.
53+
* `web_url` - User's website URL.
54+
* `access_level` - One of five levels of access to the group.
55+
* `expires_at` - Expiration date for the group membership.
56+

website/gitlab.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
<li<%= sidebar_current("docs-gitlab-data-source-group") %>>
1717
<a href="/docs/providers/gitlab/d/group.html">gitlab_group</a>
1818
</li>
19+
<li<%= sidebar_current("docs-gitlab-data-source-group-membership") %>>
20+
<a href="/docs/providers/gitlab/d/group_membership.html">gitlab_group_membership</a>
21+
</li>
1922
<li<%= sidebar_current("docs-gitlab-data-source-project") %>>
2023
<a href="/docs/providers/gitlab/d/project.html">gitlab_project</a>
2124
</li>

0 commit comments

Comments
 (0)