Skip to content

Commit d613f20

Browse files
authored
Merge pull request #23 from roidelapluie/v4-user
new resource: gitlab_user
2 parents 7235477 + 14d912a commit d613f20

File tree

5 files changed

+397
-0
lines changed

5 files changed

+397
-0
lines changed

gitlab/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func Provider() terraform.ResourceProvider {
4646
"gitlab_label": resourceGitlabLabel(),
4747
"gitlab_project_hook": resourceGitlabProjectHook(),
4848
"gitlab_deploy_key": resourceGitlabDeployKey(),
49+
"gitlab_user": resourceGitlabUser(),
4950
},
5051

5152
ConfigureFunc: providerConfigure,

gitlab/resource_gitlab_user.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strconv"
7+
8+
"github.com/hashicorp/terraform/helper/schema"
9+
gitlab "github.com/xanzy/go-gitlab"
10+
)
11+
12+
func resourceGitlabUser() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceGitlabUserCreate,
15+
Read: resourceGitlabUserRead,
16+
Update: resourceGitlabUserUpdate,
17+
Delete: resourceGitlabUserDelete,
18+
19+
Schema: map[string]*schema.Schema{
20+
"username": {
21+
Type: schema.TypeString,
22+
Required: true,
23+
},
24+
"password": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
Sensitive: true,
28+
},
29+
"email": {
30+
Type: schema.TypeString,
31+
Required: true,
32+
ForceNew: true,
33+
},
34+
"name": {
35+
Type: schema.TypeString,
36+
Required: true,
37+
},
38+
"is_admin": {
39+
Type: schema.TypeBool,
40+
Optional: true,
41+
Default: false,
42+
},
43+
"can_create_group": {
44+
Type: schema.TypeBool,
45+
Optional: true,
46+
Default: false,
47+
},
48+
"skip_confirmation": {
49+
Type: schema.TypeBool,
50+
Optional: true,
51+
Default: true,
52+
},
53+
"projects_limit": {
54+
Type: schema.TypeInt,
55+
Optional: true,
56+
Default: 0,
57+
},
58+
},
59+
}
60+
}
61+
62+
func resourceGitlabUserSetToState(d *schema.ResourceData, user *gitlab.User) {
63+
d.Set("username", user.Username)
64+
d.Set("name", user.Name)
65+
d.Set("can_create_group", user.CanCreateGroup)
66+
d.Set("projects_limit", user.ProjectsLimit)
67+
}
68+
69+
func resourceGitlabUserCreate(d *schema.ResourceData, meta interface{}) error {
70+
client := meta.(*gitlab.Client)
71+
options := &gitlab.CreateUserOptions{
72+
Email: gitlab.String(d.Get("email").(string)),
73+
Password: gitlab.String(d.Get("password").(string)),
74+
Username: gitlab.String(d.Get("username").(string)),
75+
Name: gitlab.String(d.Get("name").(string)),
76+
ProjectsLimit: gitlab.Int(d.Get("projects_limit").(int)),
77+
Admin: gitlab.Bool(d.Get("is_admin").(bool)),
78+
CanCreateGroup: gitlab.Bool(d.Get("can_create_group").(bool)),
79+
SkipConfirmation: gitlab.Bool(d.Get("skip_confirmation").(bool)),
80+
}
81+
82+
log.Printf("[DEBUG] create gitlab user %q", options.Username)
83+
84+
user, _, err := client.Users.CreateUser(options)
85+
if err != nil {
86+
return err
87+
}
88+
89+
d.SetId(fmt.Sprintf("%d", user.ID))
90+
d.Set("is_admin", user.IsAdmin)
91+
92+
return resourceGitlabUserRead(d, meta)
93+
}
94+
95+
func resourceGitlabUserRead(d *schema.ResourceData, meta interface{}) error {
96+
client := meta.(*gitlab.Client)
97+
log.Printf("[DEBUG] read gitlab user %s", d.Id())
98+
99+
id, _ := strconv.Atoi(d.Id())
100+
101+
user, response, err := client.Users.GetUser(id)
102+
if err != nil {
103+
if response.StatusCode == 404 {
104+
log.Printf("[WARN] removing user %s from state because it no longer exists in gitlab", d.Id())
105+
d.SetId("")
106+
return nil
107+
}
108+
109+
return err
110+
}
111+
112+
resourceGitlabUserSetToState(d, user)
113+
return nil
114+
}
115+
116+
func resourceGitlabUserUpdate(d *schema.ResourceData, meta interface{}) error {
117+
client := meta.(*gitlab.Client)
118+
119+
options := &gitlab.ModifyUserOptions{}
120+
121+
if d.HasChange("name") {
122+
options.Name = gitlab.String(d.Get("name").(string))
123+
}
124+
125+
if d.HasChange("username") {
126+
options.Username = gitlab.String(d.Get("username").(string))
127+
}
128+
129+
if d.HasChange("is_admin") {
130+
options.Admin = gitlab.Bool(d.Get("is_admin").(bool))
131+
}
132+
133+
if d.HasChange("can_create_group") {
134+
options.CanCreateGroup = gitlab.Bool(d.Get("can_create_group").(bool))
135+
}
136+
137+
if d.HasChange("projects_limit") {
138+
options.ProjectsLimit = gitlab.Int(d.Get("projects_limit").(int))
139+
}
140+
141+
log.Printf("[DEBUG] update gitlab user %s", d.Id())
142+
143+
id, _ := strconv.Atoi(d.Id())
144+
145+
_, _, err := client.Users.ModifyUser(id, options)
146+
if err != nil {
147+
return err
148+
}
149+
150+
return resourceGitlabUserRead(d, meta)
151+
}
152+
153+
func resourceGitlabUserDelete(d *schema.ResourceData, meta interface{}) error {
154+
client := meta.(*gitlab.Client)
155+
log.Printf("[DEBUG] Delete gitlab user %s", d.Id())
156+
157+
id, _ := strconv.Atoi(d.Id())
158+
159+
_, err := client.Users.DeleteUser(id)
160+
// Ignoring error due to some bug in library
161+
log.Printf("[DEBUG] Delete gitlab user %s", err)
162+
return nil
163+
}

gitlab/resource_gitlab_user_test.go

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform/helper/acctest"
9+
"github.com/hashicorp/terraform/helper/resource"
10+
"github.com/hashicorp/terraform/terraform"
11+
"github.com/xanzy/go-gitlab"
12+
)
13+
14+
func TestAccGitlabUser_basic(t *testing.T) {
15+
var user gitlab.User
16+
rInt := acctest.RandInt()
17+
18+
resource.Test(t, resource.TestCase{
19+
PreCheck: func() { testAccPreCheck(t) },
20+
Providers: testAccProviders,
21+
CheckDestroy: testAccCheckGitlabGroupDestroy,
22+
Steps: []resource.TestStep{
23+
// Create a user
24+
{
25+
Config: testAccGitlabUserConfig(rInt),
26+
Check: resource.ComposeTestCheckFunc(
27+
testAccCheckGitlabUserExists("gitlab_user.foo", &user),
28+
testAccCheckGitlabUserAttributes(&user, &testAccGitlabUserExpectedAttributes{
29+
Email: "listest%[email protected]",
30+
Password: fmt.Sprintf("test%dtt", rInt),
31+
Username: fmt.Sprintf("listest%d", rInt),
32+
Name: fmt.Sprintf("foo %d", rInt),
33+
ProjectsLimit: 0,
34+
Admin: false,
35+
CanCreateGroup: false,
36+
SkipConfirmation: true,
37+
}),
38+
),
39+
},
40+
// Update the user to change the name
41+
{
42+
Config: testAccGitlabUserUpdateConfig(rInt),
43+
Check: resource.ComposeTestCheckFunc(
44+
testAccCheckGitlabUserExists("gitlab_user.foo", &user),
45+
testAccCheckGitlabUserAttributes(&user, &testAccGitlabUserExpectedAttributes{
46+
Email: "listest%[email protected]",
47+
Password: fmt.Sprintf("test%dtt", rInt),
48+
Username: fmt.Sprintf("listest%d", rInt),
49+
Name: fmt.Sprintf("bar %d", rInt),
50+
ProjectsLimit: 10,
51+
Admin: true,
52+
CanCreateGroup: true,
53+
SkipConfirmation: false,
54+
}),
55+
),
56+
},
57+
// Update the user to put the name back
58+
{
59+
Config: testAccGitlabUserConfig(rInt),
60+
Check: resource.ComposeTestCheckFunc(
61+
testAccCheckGitlabUserExists("gitlab_user.foo", &user),
62+
testAccCheckGitlabUserAttributes(&user, &testAccGitlabUserExpectedAttributes{
63+
Email: "listest%[email protected]",
64+
Password: fmt.Sprintf("test%dtt", rInt),
65+
Username: fmt.Sprintf("listest%d", rInt),
66+
Name: fmt.Sprintf("foo %d", rInt),
67+
ProjectsLimit: 0,
68+
Admin: false,
69+
CanCreateGroup: false,
70+
SkipConfirmation: false,
71+
}),
72+
),
73+
},
74+
},
75+
})
76+
}
77+
78+
func testAccCheckGitlabUserExists(n string, user *gitlab.User) resource.TestCheckFunc {
79+
return func(s *terraform.State) error {
80+
rs, ok := s.RootModule().Resources[n]
81+
if !ok {
82+
return fmt.Errorf("Not Found: %s", n)
83+
}
84+
85+
userID := rs.Primary.ID
86+
if userID == "" {
87+
return fmt.Errorf("No user ID is set")
88+
}
89+
conn := testAccProvider.Meta().(*gitlab.Client)
90+
91+
id, _ := strconv.Atoi(userID)
92+
93+
gotUser, _, err := conn.Users.GetUser(id)
94+
if err != nil {
95+
return err
96+
}
97+
*user = *gotUser
98+
return nil
99+
}
100+
}
101+
102+
type testAccGitlabUserExpectedAttributes struct {
103+
Email string
104+
Password string
105+
Username string
106+
Name string
107+
ProjectsLimit int
108+
Admin bool
109+
CanCreateGroup bool
110+
SkipConfirmation bool
111+
}
112+
113+
func testAccCheckGitlabUserAttributes(user *gitlab.User, want *testAccGitlabUserExpectedAttributes) resource.TestCheckFunc {
114+
return func(s *terraform.State) error {
115+
if user.Name != want.Name {
116+
return fmt.Errorf("got name %q; want %q", user.Name, want.Name)
117+
}
118+
119+
if user.Username != want.Username {
120+
return fmt.Errorf("got username %q; want %q", user.Username, want.Username)
121+
}
122+
123+
return nil
124+
}
125+
}
126+
127+
func testAccCheckGitlabUserDestroy(s *terraform.State) error {
128+
conn := testAccProvider.Meta().(*gitlab.Client)
129+
130+
for _, rs := range s.RootModule().Resources {
131+
if rs.Type != "gitlab_user" {
132+
continue
133+
}
134+
135+
id, _ := strconv.Atoi(rs.Primary.ID)
136+
137+
user, resp, err := conn.Users.GetUser(id)
138+
if err == nil {
139+
if user != nil && fmt.Sprintf("%d", user.ID) == rs.Primary.ID {
140+
return fmt.Errorf("User still exists")
141+
}
142+
}
143+
if resp.StatusCode != 404 {
144+
return err
145+
}
146+
return nil
147+
}
148+
return nil
149+
}
150+
151+
func testAccGitlabUserConfig(rInt int) string {
152+
return fmt.Sprintf(`
153+
resource "gitlab_user" "foo" {
154+
name = "foo %d"
155+
username = "listest%d"
156+
password = "test%dtt"
157+
email = "listest%[email protected]"
158+
is_admin = false
159+
projects_limit = 0
160+
can_create_group = false
161+
}
162+
`, rInt, rInt, rInt, rInt)
163+
}
164+
165+
func testAccGitlabUserUpdateConfig(rInt int) string {
166+
return fmt.Sprintf(`
167+
resource "gitlab_user" "foo" {
168+
name = "bar %d"
169+
username = "listest%d"
170+
password = "test%dtt"
171+
email = "listest%[email protected]"
172+
is_admin = true
173+
projects_limit = 10
174+
can_create_group = true
175+
}
176+
`, rInt, rInt, rInt, rInt)
177+
}

0 commit comments

Comments
 (0)