diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 4c73f70727f7bc3378d2033f493c9078c8fe0b1f..42fb342b2b78360c564a63161dc8b110944a5e23 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -36,7 +36,6 @@ package gitlab */ import ( - "fmt" "net/http" "time" @@ -53,6 +52,16 @@ type Client struct { apiURL string } +// processError - helper +func processError(logPrefix string, err error) { + rlog.Warnf("%s error: %v", logPrefix, err) +} + +// processComplete - helper +func processComplete(logPrefix string, statusCode int) { + rlog.Debugf("Completed %s. Status Code: %d", logPrefix, statusCode) +} + // NewClient - create new gitlab api client func NewClient(apiURL string, token string, httpClient *http.Client) Client { // apiUrl https://code.il2.dso.mil/api/v4 @@ -76,21 +85,27 @@ func NewClient(apiURL string, token string, httpClient *http.Client) Client { // GetUser - func (r Client) GetUser(userID int) (*gogitlab.User, int, error) { + logPrefix := "GetUser" + getCustomeAttributes := true opts := gogitlab.GetUsersOptions{ WithCustomAttributes: &getCustomeAttributes, } + user, res, err := r.client.Users.GetUser(userID, opts) + if err != nil { + processError(logPrefix, err) return nil, 0, err } - rlog.Debugf("Completed call to GetUser userID: %d", user.ID) + processComplete(logPrefix, res.StatusCode) return user, res.StatusCode, nil } // GetUsers - func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { + logPrefix := "GetUsers" getCustomeAttributes := true listOptions := gogitlab.ListOptions{ @@ -105,8 +120,8 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { OrderBy: &orderBy, WithCustomAttributes: &getCustomeAttributes, } - // if search defined add it to opts + // if search defined add it to opts if search != nil { opts.Search = search } @@ -116,6 +131,7 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { for more { users, res, err := r.client.Users.ListUsers(&opts) if err != nil { + processError(logPrefix, err) return nil, err } for x := 0; x < len(users); x++ { @@ -129,35 +145,92 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { } } - rlog.Debug(fmt.Sprintf("Completed call to GetUsers. Records returned: %d", len(userList))) + processComplete(logPrefix, http.StatusOK) return userList, nil } +// GetUserByUsername - +func (r Client) GetUserByUsername(username *string) (*gogitlab.User, int, error) { + logPrefix := "GetUserByUsername" + getCustomeAttributes := true + var opts = gogitlab.ListUsersOptions{ + Username: username, + WithCustomAttributes: &getCustomeAttributes, + } + + users, _, err := r.client.Users.ListUsers(&opts) + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + if len(users) == 0 { + statusCode := http.StatusNotFound + rlog.Debugf("%s User Not Found. Status Code: %d", logPrefix, statusCode) + return nil, statusCode, nil + } + + statusCode := http.StatusFound + processComplete(logPrefix, statusCode) + return users[0], statusCode, nil +} + // AddUser - -func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, int, error) { +func (r Client) AddUser(createUserOptions *gogitlab.CreateUserOptions) (*gogitlab.User, int, error) { + logPrefix := "AddUser" var opts = gogitlab.CreateUserOptions{ - Username: &user.Username, - Email: &user.Email, - Name: &user.Name, - Password: &password, + Username: createUserOptions.Username, + Email: createUserOptions.Email, + Name: createUserOptions.Name, + Password: createUserOptions.Password, } + newUser, res, err := r.client.Users.CreateUser(&opts) + if err != nil { - return nil, res.StatusCode, err + processError(logPrefix, err) + return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to AddUser. Status Code: %d", res.StatusCode)) + + processComplete(logPrefix, res.StatusCode) return newUser, res.StatusCode, nil } +// UpdateUser - Update existing user. Only allow update of specific values +func (r Client) UpdateUser(userID int, modifyUserOptions *gogitlab.ModifyUserOptions) (*gogitlab.User, int, error) { + logPrefix := "UpdateUser" + + var opts = gogitlab.ModifyUserOptions{ + Email: modifyUserOptions.Email, + Name: modifyUserOptions.Name, + } + + user, res, err := r.client.Users.ModifyUser(userID, &opts) + + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + processComplete(logPrefix, res.StatusCode) + return user, res.StatusCode, nil +} + // DeleteUser - func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, error) { // waiting will be skilled if waitCount is 0 // setting wait will use a loop to wait until resource has completed deletion + logPrefix := "DeleteUser" + res, err := r.client.Users.DeleteUser(userID) + if err != nil { - return res.StatusCode, err + processError(logPrefix, err) + return 0, err } - rlog.Debugf("DeleteUser status: %d", res.StatusCode) + + returnStatusCode := res.StatusCode + // wait for resource to be deleted if waitCount > 0 { done := false @@ -169,19 +242,25 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er for !done && retryCount > 0 { _, res, err = r.client.Users.GetUser(userID, opts) if err != nil && res == nil { - rlog.Warnf("DeleteUser hard error: %v", err) + processError(logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { done = true } retryCount = retryCount - 1 - rlog.Debugf("DeleteUser wait status: %d", res.StatusCode) + rlog.Debugf("%s wait status: %d", logPrefix, res.StatusCode) time.Sleep((time.Duration(waitInterval) * time.Millisecond)) } + if done { + returnStatusCode = http.StatusOK + } else { + returnStatusCode = http.StatusRequestTimeout + } } - rlog.Debugf("Completed call to DeleteUser status: %d", res.StatusCode) - return res.StatusCode, nil + + processComplete(logPrefix, res.StatusCode) + return returnStatusCode, nil } // DeleteUserByUsername - convenience method @@ -190,46 +269,58 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun // setting wait will use a loop to wait until resource has completed deletion // expect return status code of http.StatusNoContent 204 or http.StatusNotFound 404 logPrefix := "Completed call to DeleteUserByUsername." + var opts = gogitlab.ListUsersOptions{Username: &username} - users, lres, err := r.client.Users.ListUsers(&opts) + + users, _, err := r.client.Users.ListUsers(&opts) + if err != nil { - return lres.StatusCode, err + processError(logPrefix, err) + return 0, err } + if len(users) == 0 { statusCode := http.StatusNotFound - rlog.Debug(fmt.Sprintf("%s User Not Found. Status Code: %d", logPrefix, statusCode)) + processComplete(logPrefix, statusCode) return statusCode, nil } statusCode, err := r.DeleteUser(users[0].ID, waitInterval, waitCount) + if err != nil { + processError(logPrefix, err) return 0, err } - rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, statusCode)) + + processComplete(logPrefix, statusCode) return statusCode, nil } // GetGroup - func (r Client) GetGroup(groupID int) (*gogitlab.Group, int, error) { + logPrefix := "GetGroup" + group, res, err := r.client.Groups.GetGroup(groupID) + if err != nil { + processError(logPrefix, err) return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to GetGroup. groupID: %d", group.ID)) + processComplete(logPrefix, res.StatusCode) return group, res.StatusCode, nil } // GetGroupByFullPath - func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, error) { // slow. get all groups and check for exact match to fullPath + logPrefix := "GetGroupByFullPath" + listOptions := gogitlab.ListOptions{ Page: 1, PerPage: itemsPerPage, } - // some valid values path, name - logPrefix := "Completed call to GetGroupByFullPath." orderBy := "path" opts := gogitlab.ListGroupsOptions{ ListOptions: listOptions, @@ -244,6 +335,7 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro for more && !found { groups, res, err := r.client.Groups.ListGroups(&opts) if err != nil { + processError(logPrefix, err) return nil, 0, err } for x := 0; x < len(groups) && !found; x++ { @@ -262,16 +354,20 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro } } + if !found { - rlog.Debug(fmt.Sprintf("%s NOT FOUND %s", logPrefix, *fullPath)) + processComplete(logPrefix, http.StatusNotFound) return nil, http.StatusNotFound, nil } - rlog.Debug(fmt.Sprintf("%s FOUND %s", logPrefix, group.FullPath)) + + processComplete(logPrefix, http.StatusFound) return group, http.StatusFound, nil } // GetGroups - func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { + logPrefix := "GetGroups" + listOptions := gogitlab.ListOptions{ Page: 1, PerPage: itemsPerPage, @@ -283,18 +379,23 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { ListOptions: listOptions, OrderBy: &orderBy, } - // if search defined add it to opts + // if search defined add it to opts if search != nil { opts.Search = search } + groupList := []*gogitlab.Group{} + var more = true for more { groups, res, err := r.client.Groups.ListGroups(&opts) + if err != nil { + processError(logPrefix, err) return nil, err } + for x := 0; x < len(groups); x++ { groupList = append(groupList, groups[x]) } @@ -304,42 +405,87 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { } else { more = false } - } - rlog.Debug(fmt.Sprintf("Completed call to GetGroups. Records returned: %d", len(groupList))) + + processComplete(logPrefix, http.StatusOK) return groupList, nil } // AddGroup - -func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, int, error) { +func (r Client) AddGroup(createGroupOptions gogitlab.CreateGroupOptions) (*gogitlab.Group, int, error) { // https://stackoverflow.com/questions/65081356/how-do-you-create-a-project-in-a-specific-group-via-gitlab-api // SubGroup will be created if a parentID is supplied + logPrefix := "AddGroup" + // force visibility to private var visibility = gogitlab.PrivateVisibility var opts = gogitlab.CreateGroupOptions{ - Name: &group.Name, - Path: &group.Path, - Description: &group.Description, - ParentID: parentID, + Name: createGroupOptions.Name, + Path: createGroupOptions.Path, + Description: createGroupOptions.Description, + ParentID: createGroupOptions.ParentID, Visibility: &visibility, } newGroup, res, err := r.client.Groups.CreateGroup(&opts) + if err != nil { - return nil, res.StatusCode, err + processError(logPrefix, err) + return nil, 0, err } + + processComplete(logPrefix, res.StatusCode) return newGroup, res.StatusCode, nil } +// AddGroupMember - +func (r Client) AddGroupMember(groupID *int, userID *int, accessLevel gogitlab.AccessLevelValue) (*gogitlab.GroupMember, int, error) { + logPrefix := "AddGroupMember" + + var opts = gogitlab.AddGroupMemberOptions{ + UserID: userID, + AccessLevel: &accessLevel, + } + + groupMember, res, err := r.client.GroupMembers.AddGroupMember(groupID, &opts) + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + processComplete(logPrefix, res.StatusCode) + return groupMember, res.StatusCode, nil +} + +// UpdateGroup - +func (r Client) UpdateGroup(groupID int, updateGroupOptions *gogitlab.UpdateGroupOptions) (*gogitlab.Group, int, error) { + logPrefix := "UpdateGroup" + + group, res, err := r.client.Groups.UpdateGroup(groupID, updateGroupOptions) + + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + processComplete(logPrefix, res.StatusCode) + return group, res.StatusCode, nil +} + // DeleteGroup - func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, error) { // waiting will be skilled if waitCount is 0 // setting wait will use a loop to wait until resource has completed deletion + logPrefix := "DeleteGroup" + res, err := r.client.Groups.DeleteGroup(groupID) + if err != nil { + processError(logPrefix, err) return 0, err } - rlog.Debugf("DeleteGroup status: %d", res.StatusCode) + + returnStatusCode := res.StatusCode // wait for resource to be deleted if waitCount > 0 { done := false @@ -347,7 +493,7 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, for !done && retryCount > 0 { _, res, err = r.client.Groups.GetGroup(groupID) if err != nil && res == nil { - rlog.Warnf("DeleteGroup hard error: %v", err) + processError(logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -357,25 +503,92 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, rlog.Debugf("DeleteGroup wait status: %d", res.StatusCode) time.Sleep((time.Duration(waitInterval) * time.Millisecond)) } + if done { + returnStatusCode = http.StatusOK + } else { + returnStatusCode = http.StatusRequestTimeout + } } - rlog.Debugf("Completed call to DeleteGroup status: %d", res.StatusCode) - return res.StatusCode, nil + processComplete(logPrefix, returnStatusCode) + return returnStatusCode, nil } // GetProject - -func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { +func (r Client) GetProject(projectID int) (*gogitlab.Project, int, error) { + logPrefix := "GetProject" opts := gogitlab.GetProjectOptions{} + project, res, err := r.client.Projects.GetProject(projectID, &opts) + if err != nil { - return nil, err + processError(logPrefix, err) + return nil, 0, err } - rlog.Debugf("Completed call to GetProject. status Code: %d", res.StatusCode) - return project, nil + processComplete(logPrefix, res.StatusCode) + return project, res.StatusCode, nil +} + +// GetProjectByFullPath - +func (r Client) GetProjectByFullPath(fullPath *string) (*gogitlab.Project, int, error) { + // slow. get all groups and check for exact match to fullPath + logPrefix := "GetProjectByFullPath" + + listOptions := gogitlab.ListOptions{ + Page: 1, + PerPage: itemsPerPage, + } + + // some valid values path, name + + orderBy := "path" + opts := gogitlab.ListProjectsOptions{ + ListOptions: listOptions, + OrderBy: &orderBy, + } + + project := &gogitlab.Project{} + var more = true + var found = false + + // while more and not found + for more && !found { + projects, res, err := r.client.Projects.ListProjects(&opts) + + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + for x := 0; x < len(projects) && !found; x++ { + rlog.Debugf("%s checking %s", logPrefix, projects[x].PathWithNamespace) + if projects[x].PathWithNamespace == *fullPath { + found = true + rlog.Debugf("%s FOUND %s", logPrefix, projects[x].PathWithNamespace) + project = projects[x] + } + } + + if res.NextPage > 0 { + opts.ListOptions.Page = opts.ListOptions.Page + 1 + } else { + more = false + } + } + + if !found { + processComplete(logPrefix, http.StatusNotFound) + return nil, http.StatusNotFound, nil + } + + processComplete(logPrefix, http.StatusFound) + return project, http.StatusFound, nil } // GetProjects - func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { + logPrefix := "GetProjects" + listOptions := gogitlab.ListOptions{ Page: 1, PerPage: itemsPerPage, @@ -398,6 +611,7 @@ func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { for more { projects, res, err := r.client.Projects.ListProjects(&opts) if err != nil { + processError(logPrefix, err) return nil, err } for x := 0; x < len(projects); x++ { @@ -410,36 +624,101 @@ func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { more = false } } - rlog.Debugf("Completed call to GetProjectss. Records returned: %d", len(projectList)) + + processComplete(logPrefix, http.StatusOK) return projectList, nil } // AddProject - -func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Project, int, error) { +func (r Client) AddProject(createProjectOptions gogitlab.CreateProjectOptions, groupID int) (*gogitlab.Project, int, error) { + logPrefix := "AddProject" // force visibility to private var visibility = gogitlab.PrivateVisibility // copy customizable settings from argument, hard code other options as desired var opts = gogitlab.CreateProjectOptions{ - Name: &project.Name, - Path: &project.Path, - Description: &project.Description, + Name: createProjectOptions.Name, + Path: createProjectOptions.Path, + Description: createProjectOptions.Description, NamespaceID: &groupID, // hard coded values Visibility: &visibility, } newProject, res, err := r.client.Projects.CreateProject(&opts) + if err != nil { - return nil, res.StatusCode, err + processError(logPrefix, err) + return nil, 0, err } + + processComplete(logPrefix, res.StatusCode) return newProject, res.StatusCode, nil } +// UpdateProject - +func (r Client) UpdateProject(projectID int, editProjectOptions gogitlab.EditProjectOptions) (*gogitlab.Project, int, error) { + logPrefix := "UpdateProject" + // copy customizable settings from argument, hard code other options as desired + var opts = gogitlab.EditProjectOptions{ + Name: editProjectOptions.Name, + Path: editProjectOptions.Path, + Description: editProjectOptions.Description, + } + + project, res, err := r.client.Projects.EditProject(projectID, &opts) + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + processComplete(logPrefix, res.StatusCode) + return project, res.StatusCode, nil +} + // DeleteProject - -func (r Client) DeleteProject(projectID int) (int, error) { +func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (int, error) { + logPrefix := "DeleteProject" + // waiting will be skipped if waitCount is 0 + // setting wait will use a loop to wait until resource has completed deletion res, err := r.client.Projects.DeleteProject(projectID) if err != nil { - return res.StatusCode, err + processError(logPrefix, err) + return 0, err + } + + returnStatusCode := res.StatusCode + + // wait for resource to be deleted + withCustomAttributes := false + opts := gogitlab.GetProjectOptions{ + WithCustomAttributes: &withCustomAttributes, + } + + if waitCount > 0 { + done := false + retryCount := waitCount + + for !done && retryCount > 0 { + _, res, err = r.client.Projects.GetProject(projectID, &opts) + if err != nil && res == nil { + processError(logPrefix, err) + return 0, err + } + if res.StatusCode == http.StatusNotFound { + done = true + } + retryCount = retryCount - 1 + rlog.Debugf("%s wait status: %d", logPrefix, res.StatusCode) + time.Sleep((time.Duration(waitInterval) * time.Millisecond)) + } + + if done { + returnStatusCode = http.StatusOK + } else { + returnStatusCode = http.StatusRequestTimeout + } } - return res.StatusCode, nil + + processComplete(logPrefix, returnStatusCode) + return returnStatusCode, nil } diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 4361ff22dc77a1a4e80eccbb9adee1dfce244be3..5c9e86d2345b67ca89e9946a60798f1acec9528c 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -214,7 +214,10 @@ func TestClient_AddUser(t *testing.T) { httpmock.ActivateNonDefault(testHTTPClient) defer httpmock.DeactivateAndReset() - testUser1 := gogitlab.User{ID: 1, Username: "joedirt"} + testName := "test Joe Dirt" + testUsername := "testjoedirt" + testPassword := "password" + testUser1 := gogitlab.User{ID: 1, Username: testUsername, Name: testName} httpmock.RegisterResponder("POST", "https://test/api/v4/users", @@ -233,8 +236,7 @@ func TestClient_AddUser(t *testing.T) { apiURL string } type args struct { - user *gogitlab.User - password string + createUserOptions *gogitlab.CreateUserOptions } tests := []struct { name string @@ -247,7 +249,7 @@ func TestClient_AddUser(t *testing.T) { { name: "AddUser 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, - args: args{user: &testUser1, password: "test"}, + args: args{createUserOptions: &gogitlab.CreateUserOptions{Name: &testName, Username: &testUsername, Password: &testPassword}}, want: &testUser1, wantErr: false, }, @@ -259,7 +261,7 @@ func TestClient_AddUser(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, _, err := r.AddUser(tt.args.user, tt.args.password) + got, _, err := r.AddUser(tt.args.createUserOptions) if (err != nil) != tt.wantErr { t.Errorf("Client.AddUser() error = %v, wantErr %v", err, tt.wantErr) return @@ -273,6 +275,72 @@ func TestClient_AddUser(t *testing.T) { } } +func TestClient_UpdateUser(t *testing.T) { + // setup a http client for use in mocking + testHTTPClient := &http.Client{} + httpmock.ActivateNonDefault(testHTTPClient) + defer httpmock.DeactivateAndReset() + + testUser1 := gogitlab.User{ID: 1, Username: "joedirt"} + + httpmock.RegisterResponder("PUT", + `=~^https://test/api/v4/users.*`, + httpmock.NewJsonResponderOrPanic(200, testUser1), + ) + + // test objects + testAPIUrl := "https://test/api/v4/" + testToken := "token" + // create a gitlab Client object, inject http client to allow for mocking using httpmock + testGitlabClient, _ := gogitlab.NewClient(testToken, gogitlab.WithBaseURL(testAPIUrl), gogitlab.WithHTTPClient(testHTTPClient)) + updatedName := "Updated Name" + + type fields struct { + client *gogitlab.Client + token string + apiURL string + } + type args struct { + user *gogitlab.User + modifyUserOptions gogitlab.ModifyUserOptions + } + tests := []struct { + name string + fields fields + args args + want *gogitlab.User + want1 int + wantErr bool + }{ + { + name: "UpdateUser 1", + fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, + args: args{user: &testUser1, modifyUserOptions: gogitlab.ModifyUserOptions{Name: &updatedName}}, + want: &testUser1, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := Client{ + client: tt.fields.client, + token: tt.fields.token, + apiURL: tt.fields.apiURL, + } + got, _, err := r.UpdateUser(tt.args.user.ID, &tt.args.modifyUserOptions) + if (err != nil) != tt.wantErr { + t.Errorf("Client.UpdateUser() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got.ID != tt.want.ID { + t.Errorf("Client.UpdateUser() got = %d, want %d", got.ID, tt.want.ID) + return + } + t.Logf("Client.UpdateUser() got = %d, want %d", got.ID, tt.want.ID) + }) + } +} + func TestClient_DeleteUser(t *testing.T) { // setup a http client for use in mocking testHTTPClient := &http.Client{} @@ -283,20 +351,14 @@ func TestClient_DeleteUser(t *testing.T) { testUsername := "testusername" testUser := gogitlab.User{ID: testUserID, Username: testUsername} - // httpmock.RegisterResponder("DELETE", - // `=~^https://test/api/v4/users.*`, - // httpmock.NewJsonResponderOrPanic(202, testUser), - // ) - - // mock to list out the articles counter := 0 - httpmock.RegisterResponder("DELETE", `=~^https://test/api/v4/users.*`, func(req *http.Request) (*http.Response, error) { return httpmock.NewJsonResponse(201, testUser) }, ) + // setup a mock that will change response on every 4th call httpmock.RegisterResponder("GET", `=~^https://test/api/v4/users.*`, func(req *http.Request) (*http.Response, error) { @@ -333,7 +395,7 @@ func TestClient_DeleteUser(t *testing.T) { name: "DeleteUser 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, args: args{userID: testUserID}, - want: 404, + want: 200, wantErr: false, }, } @@ -580,7 +642,8 @@ func TestClient_AddGroup(t *testing.T) { defer httpmock.DeactivateAndReset() // empty gitlab User array - testGroup := gogitlab.Group{ID: 1, Name: "joedirt"} + testGroupName := "test group name" + testGroup := gogitlab.Group{ID: 1, Name: testGroupName} httpmock.RegisterResponder("POST", "https://test/api/v4/groups", @@ -599,7 +662,7 @@ func TestClient_AddGroup(t *testing.T) { apiURL string } type args struct { - group *gogitlab.Group + createGroupOptions gogitlab.CreateGroupOptions } tests := []struct { name string @@ -612,7 +675,7 @@ func TestClient_AddGroup(t *testing.T) { { name: "AddGroup 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, - args: args{group: &testGroup}, + args: args{createGroupOptions: gogitlab.CreateGroupOptions{Name: &testGroupName}}, want: &testGroup, wantErr: false, }, @@ -624,7 +687,7 @@ func TestClient_AddGroup(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, _, err := r.AddGroup(tt.args.group, nil) + got, _, err := r.AddGroup(tt.args.createGroupOptions) if (err != nil) != tt.wantErr { t.Errorf("Client.AddGroup() error = %v, wantErr %v", err, tt.wantErr) return @@ -644,28 +707,12 @@ func TestClient_DeleteGroup(t *testing.T) { testHTTPClient := &http.Client{} httpmock.ActivateNonDefault(testHTTPClient) defer httpmock.DeactivateAndReset() - // empty gitlab User array - testGroupArray := []*gogitlab.Group{} testGroup1 := gogitlab.Group{ID: 1, Name: "group joedirt"} - testGroup2 := gogitlab.Group{ID: 2, Name: "group spongebob"} - testGroupArray = append(testGroupArray, &testGroup1, &testGroup2) - // httpmock.RegisterResponder("DELETE", - // `=~^https://test/api/v4/groups.*`, - // httpmock.NewJsonResponderOrPanic(202, testGroup1), - // ) - // httpmock.RegisterResponder("GET", - // `=~^https://test/api/v4/groups.*`, - // httpmock.NewJsonResponderOrPanic(200, testGroupArray), - // ) var counter = 0 httpmock.RegisterResponder("DELETE", `=~^https://test/api/v4/groups.*`, func(req *http.Request) (*http.Response, error) { - // counter = counter + 1 - // if counter%4 == 0 { - // return httpmock.NewJsonResponse(404, testGroup1) - // } return httpmock.NewJsonResponse(201, testGroup1) }, ) @@ -706,7 +753,7 @@ func TestClient_DeleteGroup(t *testing.T) { name: "DeleteGroup 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, args: args{groupID: testGroupID}, - want: 404, + want: 200, wantErr: false, }, } @@ -784,7 +831,7 @@ func TestClient_GetProject(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.GetProject(tt.args.projectID) + got, _, err := r.GetProject(tt.args.projectID) if (err != nil) != tt.wantErr { t.Errorf("Client.GetProject() error = %v, wantErr %v", err, tt.wantErr) return @@ -880,6 +927,7 @@ func TestClient_AddProject(t *testing.T) { testProjectID := 1 testProjectName := "testProjectName" testProject := gogitlab.Project{ID: testProjectID, Name: testProjectName} + createTestProjetOptions := gogitlab.CreateProjectOptions{Name: &testProjectName} httpmock.RegisterResponder("POST", "https://test/api/v4/projects", @@ -898,7 +946,7 @@ func TestClient_AddProject(t *testing.T) { apiURL string } type args struct { - project *gogitlab.Project + createProjectOptions *gogitlab.CreateProjectOptions groupID int } tests := []struct { @@ -912,7 +960,7 @@ func TestClient_AddProject(t *testing.T) { { name: "AddGroup 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, - args: args{project: &testProject}, + args: args{createProjectOptions: &createTestProjetOptions}, want1: 200, want: &testProject, wantErr: false, @@ -925,7 +973,7 @@ func TestClient_AddProject(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, got1, err := r.AddProject(tt.args.project, tt.args.groupID) + got, got1, err := r.AddProject(*tt.args.createProjectOptions, tt.args.groupID) if (err != nil) != tt.wantErr { t.Errorf("Client.AddProject() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go index 04cff12cdfa0d05bf3c7f4ed888501974ba7ee86..b07cf688a036694616b83a9f1d50dabc6fd9ce9e 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -195,8 +195,8 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { for i := 1; i <= 125; i++ { projectName := "test project " + fmt.Sprintf("%d", i) - projectObj := gogitlab.Project{Name: projectName} - got, statusCode, err := c.AddProject(&projectObj, group.ID) + projectObj := gogitlab.CreateProjectOptions{Name: &projectName} + got, statusCode, err := c.AddProject(projectObj, group.ID) if err != nil { t.Errorf("Client.AddProject() error = %v %d", err, statusCode) @@ -207,8 +207,8 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { for i := 1; i <= 125; i++ { projectName := "test project " + fmt.Sprintf("%d", i) - projectObj := gogitlab.Project{Name: projectName} - got, statusCode, err := c.AddProject(&projectObj, subgroup1.ID) + projectObj := gogitlab.CreateProjectOptions{Name: &projectName} + got, statusCode, err := c.AddProject(projectObj, subgroup1.ID) if err != nil { t.Errorf("Client.AddProject() error = %v %d", err, statusCode) diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go new file mode 100644 index 0000000000000000000000000000000000000000..229ca5be10057d869a46e75838bae677da33eb50 --- /dev/null +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -0,0 +1,112 @@ +// +build integration + +package integration + +import ( + "errors" + "fmt" + "os" + "testing" + + gogitlab "github.com/xanzy/go-gitlab" + gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" +) + +const groupsTestItemCount = 65 + +// getClient_Groups - +func getClient_Groups() (gitlab.Client, error) { + gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") + if !ok { + return gitlab.Client{}, errors.New("env variable GITLAB_API_URL undefinded") + } + gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") + if !ok { + return gitlab.Client{}, errors.New("env variable GITLAB_API_TOKEN undefinded") + } + var client = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) + return client, nil +} + + +func TestClient_GetGroups(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Groups() + if err != nil { + t.Errorf("Client.getClient() error = %v", err) + return + } + got, err := c.GetGroups(nil) + if err != nil { + t.Errorf("Client.GetGroups() error = %v", err) + return + } + t.Logf("GetGroups - number of groups %d", len(got)) + }) +} + +func TestClient_AddGroups(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Groups() + if err != nil { + t.Errorf("Client.getClient() error = %v", err) + return + } + + for i := 1; i <= groupsTestItemCount; i++ { + path := "test-group-" + fmt.Sprintf("%d", i) + name := "test group " + fmt.Sprintf("%d", i) + + groupObj := gogitlab.Group{Name: name, Path: path} + got, statusCode, err := c.AddGroup(&groupObj, nil) + + if err != nil { + t.Errorf("Client.AddGroup() error = %v %d", err, statusCode) + } else { + t.Logf("AddGroup %s %s %s %s %d", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) + } + } + + }) +} + +func TestClient_GetGroups2(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Groups() + if err != nil { + t.Errorf("Client.getClient() error = %v", err) + return + } + got, err := c.GetGroups(nil) + if err != nil { + t.Errorf("Client.GetGroups() error = %v", err) + return + } + t.Logf("GetGroups2 - number of groups %d", len(got)) + }) +} + +func TestClient_deleteGroups(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Groups() + if err != nil { + t.Errorf("Client.getClient() error = %v", err) + return + } + + search := "test-group" + groupList, err := c.GetGroups(&search) + + for x := 0; x < len(groupList); x++ { + group := groupList[x] + statusCode, err := c.DeleteGroup(group.ID, 100, 1200) + + if err != nil { + t.Errorf("Client.DeleteGroup() error = %v %d", err, statusCode) + } else { + t.Logf("DeleteGroup %s %d", group.Name, statusCode) + } + } + + }) +} diff --git a/integration-tests/gitlab/api/gitlab_api_test.go b/integration-tests/gitlab/api/gitlab_api_test.go deleted file mode 100644 index 9b0c6f1bf04d6d92340b7a3db9112aa7045dfe47..0000000000000000000000000000000000000000 --- a/integration-tests/gitlab/api/gitlab_api_test.go +++ /dev/null @@ -1,319 +0,0 @@ -// +build integration - -package integration - -import ( - "errors" - "fmt" - "os" - "testing" - - gogitlab "github.com/xanzy/go-gitlab" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" -) - -const testItemCount = 65 - -// getClient - -func getClient() (gitlab.Client, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.Client{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.Client{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - var client = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, nil -} - -//TestClient_getUsers - -func TestClient_getUsers(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - got, err := c.GetUsers(nil) - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - t.Logf("GetUsers %d", len(got)) - }) -} - -// TestClient_addUsers - -func TestClient_addUsers(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - - for i := 1; i <= testItemCount; i++ { - username := "testuser" + fmt.Sprintf("%d", i) - name := "test user name " + fmt.Sprintf("%d", i) - email := username + "@email.com" - userObj := gogitlab.User{Username: username, Email: email, Name: name} - got, statusCode, err := c.AddUser(&userObj, "password") - - if err != nil { - t.Errorf("Client.AddUser() error = %v %d", err, statusCode) - } else { - t.Logf("AddUser %s %d", got.Username, statusCode) - } - } - - }) -} - -func TestClient_getUsersCount(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - got, err := c.GetUsers(nil) - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - t.Logf("GetUsers - user count: %d", len(got)) - }) -} -func TestClient_deleteUsers(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - - for i := 1; i <= testItemCount; i++ { - username := "testuser" + fmt.Sprintf("%d", i) - statusCode, err := c.DeleteUserByUsername(username, 100, 200) - - if err != nil { - t.Errorf("Client.DeleteUser() error = %v %d", err, statusCode) - } else { - t.Logf("Deleted user %s %d", username, statusCode) - } - } - - }) -} - -func TestClient_getGroupsCount(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - got, err := c.GetGroups(nil) - if err != nil { - t.Errorf("Client.GetGroups() error = %v", err) - return - } - t.Logf("GetGroups - number of groups %d", len(got)) - }) -} - -func TestClient_addGroups(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - - for i := 1; i <= testItemCount; i++ { - path := "test-group-" + fmt.Sprintf("%d", i) - name := "test group " + fmt.Sprintf("%d", i) - - groupObj := gogitlab.Group{Name: name, Path: path} - got, statusCode, err := c.AddGroup(&groupObj, nil) - - if err != nil { - t.Errorf("Client.AddGroup() error = %v %d", err, statusCode) - } else { - t.Logf("AddGroup %s %s %s %s %d", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) - } - } - - }) -} - -func TestClient_getGroupsCount2(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - got, err := c.GetGroups(nil) - if err != nil { - t.Errorf("Client.GetGroups() error = %v", err) - return - } - t.Logf("GetGroups - number of groups %d", len(got)) - }) -} - -func TestClient_deleteGroups(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - - search := "test-group" - groupList, err := c.GetGroups(&search) - - for x := 0; x < len(groupList); x++ { - group := groupList[x] - statusCode, err := c.DeleteGroup(group.ID, 100, 1200) - - if err != nil { - t.Errorf("Client.DeleteGroup() error = %v %d", err, statusCode) - } else { - t.Logf("DeleteGroup %s %d", group.Name, statusCode) - } - } - - }) -} - -func TestClient_getProjectsCount(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - got, err := c.GetProjects(nil) - if err != nil { - t.Errorf("Client.GetProjects() error = %v", err) - return - } - t.Logf("Projects - number of projects %d", len(got)) - }) -} - -func TestClient_addProjects1(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - var group *gogitlab.Group - var statusCode int - - // find or create the group to hold projects - groupPath := "test-group-adam1" - groupName := "test group adam1" - groupList, err := c.GetGroups(&groupPath) - if err != nil { - t.Errorf("AddGroup error = %v", err) - return - } - - if len(groupList) == 0 { - groupObj := gogitlab.Group{Name: groupName, Path: groupPath} - group, statusCode, err = c.AddGroup(&groupObj, nil) - if err != nil { - t.Errorf("AddGroup error = %v", err) - return - } - t.Logf("AddGroup: %s %d", group.FullPath, statusCode) - } else { - group = groupList[0] - t.Logf("GetGroups: %s", group.FullPath) - } - - for i := 1; i <= testItemCount; i++ { - projectName := "test project " + fmt.Sprintf("%d", i) - - projectObj := gogitlab.Project{Name: projectName} - got, statusCode, err := c.AddProject(&projectObj, group.ID) - - if err != nil { - t.Errorf("Client.AddProject() error = %v %d", err, statusCode) - } else { - t.Logf("AddProject: [%s, %s, %d]", got.NameWithNamespace, got.HTTPURLToRepo, statusCode) - } - } - - }) -} - -func TestClient_addProjects2(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.GetUsers() error = %v", err) - return - } - - var group *gogitlab.Group - var statusCode int - // find or create the group to hold projects - groupPath := "testX-group-adam2" - groupName := "testX group adam2" - groupList, err := c.GetGroups(&groupPath) - if err != nil { - t.Errorf("AddGroup error = %v", err) - return - } - - if len(groupList) == 0 { - groupObj := gogitlab.Group{Name: groupName, Path: groupPath} - group, statusCode, err = c.AddGroup(&groupObj, nil) - if err != nil { - t.Errorf("AddGroup error = %v", err) - return - } - t.Logf("AddGroup: %s %d", group.FullPath, statusCode) - } else { - group = groupList[0] - t.Logf("GetGroups: %s", group.FullPath) - } - - for i := 1; i <= testItemCount; i++ { - projectName := "test project " + fmt.Sprintf("%d", i) - - projectObj := gogitlab.Project{Name: projectName} - got, statusCode, err := c.AddProject(&projectObj, group.ID) - - if err != nil { - t.Errorf("Client.AddProject() error = %v %d", err, statusCode) - } else { - t.Logf("AddProject: [%s, %s, %d]", got.NameWithNamespace, got.HTTPURLToRepo, statusCode) - } - } - - }) -} - -func TestClient_getProjectsCount2(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getClient() - if err != nil { - t.Errorf("Client.getClient() error = %v", err) - return - } - got, err := c.GetProjects(nil) - if err != nil { - t.Errorf("Client.GetProjects() error = %v", err) - return - } - t.Logf("Projects - number of projects %d", len(got)) - }) -} diff --git a/integration-tests/gitlab/api/gitlab_api_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go new file mode 100644 index 0000000000000000000000000000000000000000..28f3f7461d148432f41b1c747f25540c15b6ca12 --- /dev/null +++ b/integration-tests/gitlab/api/gitlab_api_users_test.go @@ -0,0 +1,156 @@ +// +build integration + +package integration + +import ( + "errors" + "fmt" + "os" + "testing" + + gogitlab "github.com/xanzy/go-gitlab" + gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" +) + +const testItemCount = 65 + +// getClient - +func getClient_Users() (gitlab.Client, error) { + gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") + if !ok { + return gitlab.Client{}, errors.New("env variable GITLAB_API_URL undefinded") + } + gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") + if !ok { + return gitlab.Client{}, errors.New("env variable GITLAB_API_TOKEN undefinded") + } + var client = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) + return client, nil +} + +//TestClient_getUsers - +func TestClient_getUsers(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Users() + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + got, err := c.GetUsers(nil) + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + t.Logf("GetUsers %d", len(got)) + }) +} + +// TestClient_addUsers - +func TestClient_addUsers(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Users() + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + + for i := 1; i <= testItemCount; i++ { + username := "testuser" + fmt.Sprintf("%d", i) + name := "test user name " + fmt.Sprintf("%d", i) + email := username + "@email.com" + userObj := gogitlab.User{Username: username, Email: email, Name: name} + got, statusCode, err := c.AddUser(&userObj, "password") + + if err != nil { + t.Errorf("Client.AddUser() error = %v %d", err, statusCode) + } else { + t.Logf("AddUser %s %d", got.Username, statusCode) + } + } + + }) +} + +func TestClient_UpdateUser(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Users() + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + // create a user + username := "testupdateuser01" + name := "test update user name 01" + email := username + "@email.com" + userObj := gogitlab.User{Username: username, Email: email, Name: name} + user, statusCode, err := c.AddUser(&userObj, "password") + t.Logf(" created user %s status code %d", username, statusCode) + + // get user + user, statusCode, err = c.GetUserByUsername(&username) + if err != nil { + t.Errorf("Client.GetUserByUsername() error = %v", err) + return + } + t.Logf("GetUserByUsername: %s", user.Username) + + // update user + testName := "Updated Username 01" + modifyUserOptions := gogitlab.ModifyUserOptions{Name: &testName} + _, statusCode, err = c.UpdateUser(user.ID, &modifyUserOptions) + + // get user + user, statusCode, err = c.GetUserByUsername(&username) + if err != nil { + t.Errorf("Client.GetUserByUsername() error = %v", err) + return + } + t.Logf("GetUserByUsername success: %s", user.Username) + if ( user.Name != testName) { + t.Errorf("TestClient_UpdateUser expected %s got %s", testName, user.Name) + } else { + t.Logf("TestClient_UpdateUser success. updated Name: %s for username: %s", user.Username, user.Name) + } + + // cleanup + c.DeleteUser(user.ID,0,0) + + }) +} +func TestClient_getUsersCount(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Users() + if err != nil { + t.Errorf("Client.getClient() error = %v", err) + return + } + got, err := c.GetUsers(nil) + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + t.Logf("GetUsers - user count: %d", len(got)) + }) +} +func TestClient_deleteUsers(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClient_Users() + if err != nil { + t.Errorf("Client.GetUsers() error = %v", err) + return + } + + for i := 1; i <= testItemCount; i++ { + username := "testuser" + fmt.Sprintf("%d", i) + statusCode, err := c.DeleteUserByUsername(username, 100, 200) + + if err != nil { + t.Errorf("Client.DeleteUser() error = %v %d", err, statusCode) + } else { + t.Logf("Deleted user %s %d", username, statusCode) + } + } + + }) +} +