From 9c0ac96b7ed0462b76122326383a4d79ee86e8ac Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 21 Jun 2021 13:57:58 -0600 Subject: [PATCH 01/12] fix sonarqube findings --- clients/gitlab/client.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 94827ff..48c5c19 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -160,7 +160,7 @@ func (r Client) DeleteUser(userID int) (int, error) { // DeleteUserByUsername - convenience method func (r Client) DeleteUserByUsername(username string) (int, error) { // 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) if err != nil { @@ -168,15 +168,15 @@ func (r Client) DeleteUserByUsername(username string) (int, error) { } if len(users) == 0 { statusCode := http.StatusNotFound - rlog.Debug(fmt.Sprintf("Completed call to DeleteUser. Status Code: %d", statusCode)) + rlog.Debug(fmt.Sprintf("%s User Not Found. Status Code: %d", logPrefix, statusCode)) return statusCode, nil } - + res, err := r.client.Users.DeleteUser(users[0].ID) if err != nil { return res.StatusCode, err } - rlog.Debug(fmt.Sprintf("Completed call to DeleteUser. Status Code: %d", res.StatusCode)) + rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, res.StatusCode)) return res.StatusCode, nil } -- GitLab From 7afa512c5b2d794f1a78426bff336ba9eb0936c5 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 21 Jun 2021 15:44:43 -0600 Subject: [PATCH 02/12] add wait to delete group in order to insure resouce has been deleted before returning --- clients/gitlab/client.go | 95 +++++++++++++++++-- .../gitlab/api/gitlab_api_adhoc_test.go | 49 +++++----- rlog.conf | 2 +- 3 files changed, 117 insertions(+), 29 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 48c5c19..5103208 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -37,9 +37,11 @@ package gitlab import ( "fmt" + "net/http" + "time" + "github.com/romana/rlog" gogitlab "github.com/xanzy/go-gitlab" - "net/http" ) const itemsPerPage = 50 @@ -83,7 +85,7 @@ func (r Client) GetUser(userID int) (*gogitlab.User, int, error) { return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to GetUser userID: %d", user.ID)) + rlog.Debugf("Completed call to GetUser userID: %d", user.ID) return user, res.StatusCode, nil } @@ -191,6 +193,56 @@ func (r Client) GetGroup(groupID int) (*gogitlab.Group, int, error) { 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 + listOptions := gogitlab.ListOptions{ + Page: 1, + PerPage: itemsPerPage, + } + + // some valid values path, name + logPrefix := "Completed call to GetGroupByFullPath." + orderBy := "path" + opts := gogitlab.ListGroupsOptions{ + ListOptions: listOptions, + OrderBy: &orderBy, + } + + group := &gogitlab.Group{} + var more = true + var found = false + + // while more and not found + for more && !found { + groups, res, err := r.client.Groups.ListGroups(&opts) + if err != nil { + return nil, 0, err + } + for x := 0; x < len(groups) && !found; x++ { + rlog.Debugf(">>>>>>>> group %s", groups[x].FullPath) + if groups[x].FullPath == *fullPath { + found = true + rlog.Debugf(">>>>>>>> FOUND group %s", groups[x].FullPath) + group = groups[x] + } + } + + if res.NextPage > 0 { + opts.ListOptions.Page = opts.ListOptions.Page + 1 + } else { + more = false + } + + } + if !found { + rlog.Debug(fmt.Sprintf("%s NOT FOUND %s", logPrefix, *fullPath)) + return nil, http.StatusNotFound, nil + } + rlog.Debug(fmt.Sprintf("%s FOUND %s", logPrefix, group.FullPath)) + return group, http.StatusFound, nil +} + // GetGroups - func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { listOptions := gogitlab.ListOptions{ @@ -253,11 +305,33 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, } // DeleteGroup - -func (r Client) DeleteGroup(groupID int) (int, error) { +func (r Client) DeleteGroup(groupID int, wait bool) (int, error) { + // recommended to use wait = true + // setting wait will use a loop to wait until resource has completed deletion res, err := r.client.Groups.DeleteGroup(groupID) if err != nil { - return res.StatusCode, err + return 0, err + } + rlog.Debugf("DeleteGroup status: %d", res.StatusCode) + // wait for resource to be deleted + if wait { + gone := false + retryCount := 50 + for !gone && retryCount >= 0 { + _, res, err = r.client.Groups.GetGroup(groupID) + if err != nil && res == nil { + rlog.Debugf("DeleteGroup hard error: %v", err) + return 0, err + } + if res.StatusCode == http.StatusNotFound { + gone = true + } + retryCount = retryCount -1 + rlog.Debugf("DeleteGroup wait status: %d", res.StatusCode) + time.Sleep((10 * time.Millisecond)) + } } + rlog.Debugf("Completed call to DeleteGroup status: %d", res.StatusCode) return res.StatusCode, nil } @@ -269,7 +343,7 @@ func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { return nil, err } - rlog.Debug(fmt.Sprintf("Completed call to GetProject. status Code: %d", res.StatusCode)) + rlog.Debugf("Completed call to GetProject. status Code: %d", res.StatusCode) return project, nil } @@ -309,7 +383,7 @@ func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { more = false } } - rlog.Debug(fmt.Sprintf("Completed call to GetProjectss. Records returned: %d", len(projectList))) + rlog.Debugf("Completed call to GetProjectss. Records returned: %d", len(projectList)) return projectList, nil } @@ -333,3 +407,12 @@ func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Pr } return newProject, res.StatusCode, nil } + +// DeleteProject - +func (r Client) DeleteProject(projectID int) (int, error) { + res, err := r.client.Projects.DeleteProject(projectID) + if err != nil { + return res.StatusCode, err + } + return res.StatusCode, nil +} diff --git a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go index 0f27134..57f3cc3 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -3,15 +3,19 @@ package integration import ( - "testing" "errors" + "net/http" "os" + "testing" + + gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" + "github.com/romana/rlog" gogitlab "github.com/xanzy/go-gitlab" ) -// getClient_AdHoc - +// getClient_AdHoc - func getClient_AdHoc() (gitlab.Client, error) { gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") if !ok { @@ -21,7 +25,7 @@ func getClient_AdHoc() (gitlab.Client, error) { if !ok { return gitlab.Client{}, errors.New("env variable GITLAB_API_TOKEN undefinded") } - var client = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken,nil) + var client = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) return client, nil } func TestClient_AdHoc_getUsers_All(t *testing.T) { @@ -37,7 +41,7 @@ func TestClient_AdHoc_getUsers_All(t *testing.T) { return } t.Logf("GetUsers %d", len(got)) - for x:=0;x>>>>>>> delete group %d", statusCode) + + } - groupName := "adam root" - groupPath := "adam-root" groupObj := gogitlab.Group{Name: groupName, Path: groupPath} - group, statusCode, err := c.AddGroup(&groupObj, nil) + group, statusCode, err = c.AddGroup(&groupObj, nil) if err != nil { t.Errorf("AddGroup error = %v", err) return @@ -173,12 +180,10 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { return } t.Logf("AddGroup: %s %d", subgroup.FullPath, statusCode) - } }) } - func TestClient_AdHoc_getProjects_ALL(t *testing.T) { t.Run("test", func(t *testing.T) { c, err := getClient_AdHoc() @@ -192,7 +197,7 @@ func TestClient_AdHoc_getProjects_ALL(t *testing.T) { return } t.Logf("GetProjects %d", len(got)) - for x:=0;x Date: Mon, 21 Jun 2021 17:31:19 -0600 Subject: [PATCH 03/12] add wait for delete user and delete group --- clients/gitlab/client.go | 61 +++++++++++++------ clients/gitlab/client_test.go | 8 +-- .../gitlab/api/gitlab_api_adhoc_test.go | 49 ++++++++++++--- 3 files changed, 87 insertions(+), 31 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 5103208..620bf0a 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -150,17 +150,40 @@ func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, i } // DeleteUser - -func (r Client) DeleteUser(userID int) (int, error) { +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 res, err := r.client.Users.DeleteUser(userID) if err != nil { return res.StatusCode, err } - rlog.Debug(fmt.Sprintf("Completed call to DeleteUser. Status Code: %d", res.StatusCode)) + rlog.Debugf("DeleteUser status: %d", res.StatusCode) + // wait for resource to be deleted + if waitCount > 0 { + done := false + retryCount := waitCount + for !done && retryCount > 0 { + _, res, err = r.client.Groups.GetGroup(userID) + if err != nil && res == nil { + rlog.Warnf("DeleteUser hard error: %v", err) + return 0, err + } + if res.StatusCode == http.StatusNotFound { + done = true + } + retryCount = retryCount - 1 + rlog.Debugf("DeleteUser wait status: %d", res.StatusCode) + time.Sleep((time.Duration(waitInterval) * time.Millisecond)) + } + } + rlog.Debugf("Completed call to DeleteUser status: %d", res.StatusCode) return res.StatusCode, nil } // DeleteUserByUsername - convenience method -func (r Client) DeleteUserByUsername(username string) (int, error) { +func (r Client) DeleteUserByUsername(username string, 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 // expect return status code of http.StatusNoContent 204 or http.StatusNotFound 404 logPrefix := "Completed call to DeleteUserByUsername." var opts = gogitlab.ListUsersOptions{Username: &username} @@ -174,12 +197,12 @@ func (r Client) DeleteUserByUsername(username string) (int, error) { return statusCode, nil } - res, err := r.client.Users.DeleteUser(users[0].ID) + statusCode, err := r.DeleteUser(users[0].ID, waitInterval, waitCount) if err != nil { - return res.StatusCode, err + return 0, err } - rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, res.StatusCode)) - return res.StatusCode, nil + rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, statusCode)) + return statusCode, nil } // GetGroup - @@ -220,10 +243,10 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro return nil, 0, err } for x := 0; x < len(groups) && !found; x++ { - rlog.Debugf(">>>>>>>> group %s", groups[x].FullPath) + rlog.Debugf("GetGroupByFullPath checking group %s", groups[x].FullPath) if groups[x].FullPath == *fullPath { found = true - rlog.Debugf(">>>>>>>> FOUND group %s", groups[x].FullPath) + rlog.Debugf("GetGroupByFullPath FOUND group %s", groups[x].FullPath) group = groups[x] } } @@ -305,8 +328,8 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, } // DeleteGroup - -func (r Client) DeleteGroup(groupID int, wait bool) (int, error) { - // recommended to use wait = true +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 res, err := r.client.Groups.DeleteGroup(groupID) if err != nil { @@ -314,21 +337,21 @@ func (r Client) DeleteGroup(groupID int, wait bool) (int, error) { } rlog.Debugf("DeleteGroup status: %d", res.StatusCode) // wait for resource to be deleted - if wait { - gone := false - retryCount := 50 - for !gone && retryCount >= 0 { + if waitCount > 0 { + done := false + retryCount := waitCount + for !done && retryCount > 0 { _, res, err = r.client.Groups.GetGroup(groupID) if err != nil && res == nil { - rlog.Debugf("DeleteGroup hard error: %v", err) + rlog.Warnf("DeleteGroup hard error: %v", err) return 0, err } if res.StatusCode == http.StatusNotFound { - gone = true + done = true } - retryCount = retryCount -1 + retryCount = retryCount - 1 rlog.Debugf("DeleteGroup wait status: %d", res.StatusCode) - time.Sleep((10 * time.Millisecond)) + time.Sleep((time.Duration(waitInterval) * time.Millisecond)) } } rlog.Debugf("Completed call to DeleteGroup status: %d", res.StatusCode) diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 5927ed3..9e890b6 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -282,8 +282,6 @@ func TestClient_DeleteUser(t *testing.T) { testUserID := 1 testUsername := "testusername" testUser := gogitlab.User{ID: testUserID, Username: testUsername} - testUserArray := []*gogitlab.User{} - testUserArray = append(testUserArray, &testUser) httpmock.RegisterResponder("DELETE", `=~^https://test/api/v4/users.*`, @@ -326,7 +324,7 @@ func TestClient_DeleteUser(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteUser(tt.args.userID) + got, err := r.DeleteUser(tt.args.userID, 0, 0) if (err != nil) != tt.wantErr { t.Errorf("Client.DeleteUser() error = %v, wantErr %v", err, tt.wantErr) return @@ -396,7 +394,7 @@ func TestClient_DeleteUserByUsername(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteUserByUsername(tt.args.username) + got, err := r.DeleteUserByUsername(tt.args.username, 0, 0) if (err != nil) != tt.wantErr { t.Errorf("Client.DeleteUserByUsername() error = %v, wantErr %v", err, tt.wantErr) return @@ -678,7 +676,7 @@ func TestClient_DeleteGroup(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteGroup(tt.args.groupID) + got, err := r.DeleteGroup(tt.args.groupID, 0, 0) if (err != nil) != tt.wantErr { t.Errorf("Client.DeleteGroup() 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 57f3cc3..f826ae0 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -4,11 +4,11 @@ package integration import ( "errors" + "fmt" "net/http" "os" "testing" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" "github.com/romana/rlog" @@ -93,7 +93,7 @@ func TestClient_AdHoc_deleteUser_None(t *testing.T) { return } username := "notfound" - statusCode, err := c.DeleteUserByUsername(username) + statusCode, err := c.DeleteUserByUsername(username, 1000, 20) if err != nil { t.Errorf("Client.DeleteUser() error = %v", err) return @@ -158,7 +158,8 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { if (err == nil) && (statusCode == http.StatusFound) { - statusCode, err = c.DeleteGroup(group.ID, true) + // delete and wait for resource to clear.. up to 120 seconds + statusCode, err = c.DeleteGroup(group.ID, 1000, 120) rlog.Debugf(">>>>>>>> delete group %d", statusCode) } @@ -171,16 +172,50 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { } t.Logf("AddGroup: %s %d", group.FullPath, statusCode) - groupName = "adam subgroup" - groupPath = "adam-subgroup" + groupName = "adam subgroup1" + groupPath = "adam-subgroup1" + groupObj = gogitlab.Group{Name: groupName, Path: groupPath} + subgroup1, statusCode, err := c.AddGroup(&groupObj, &group.ID) + if err != nil { + t.Errorf("AddGroup error = %v", err) + return + } + t.Logf("AddGroup: %s %d", subgroup1.FullPath, statusCode) + + groupName = "adam subgroup2" + groupPath = "adam-subgroup2" groupObj = gogitlab.Group{Name: groupName, Path: groupPath} - subgroup, statusCode, err := c.AddGroup(&groupObj, &group.ID) + subgroup2, statusCode, err := c.AddGroup(&groupObj, &group.ID) if err != nil { t.Errorf("AddGroup error = %v", err) return } - t.Logf("AddGroup: %s %d", subgroup.FullPath, statusCode) + t.Logf("AddGroup: %s %d", subgroup2.FullPath, statusCode) + for i := 1; i <= 250; 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) + } + } + for i := 1; i <= 250; i++ { + projectName := "test project " + fmt.Sprintf("%d", i) + + projectObj := gogitlab.Project{Name: projectName} + got, statusCode, err := c.AddProject(&projectObj, subgroup1.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) + } + } }) } -- GitLab From 15aa4645e41d829e27a93e0316f92193b06d9bcd Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 21 Jun 2021 18:48:04 -0600 Subject: [PATCH 04/12] update tests to wait for delte resources --- clients/gitlab/client.go | 6 +- clients/gitlab/client_test.go | 55 ++++++++++++++++--- .../gitlab/api/gitlab_api_adhoc_test.go | 10 ++-- .../gitlab/api/gitlab_api_test.go | 4 +- rlog.conf | 2 +- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 620bf0a..4c73f70 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -162,8 +162,12 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er if waitCount > 0 { done := false retryCount := waitCount + getCustomeAttributes := true + opts := gogitlab.GetUsersOptions{ + WithCustomAttributes: &getCustomeAttributes, + } for !done && retryCount > 0 { - _, res, err = r.client.Groups.GetGroup(userID) + _, res, err = r.client.Users.GetUser(userID, opts) if err != nil && res == nil { rlog.Warnf("DeleteUser hard error: %v", err) return 0, err diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 9e890b6..d8b8bda 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -283,9 +283,29 @@ 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.*`, - httpmock.NewJsonResponderOrPanic(202, testUser), + func(req *http.Request) (*http.Response, error) { + return httpmock.NewJsonResponse(201, testUser) + }, + ) + httpmock.RegisterResponder("GET", + `=~^https://test/api/v4/users.*`, + func(req *http.Request) (*http.Response, error) { + counter = counter + 1 + if counter%4 == 0 { + return httpmock.NewJsonResponse(404, testUser) + } + return httpmock.NewJsonResponse(202, testUser) + }, ) // test objects @@ -313,7 +333,7 @@ func TestClient_DeleteUser(t *testing.T) { name: "DeleteUser 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, args: args{userID: testUserID}, - want: 202, + want: 404, wantErr: false, }, } @@ -324,7 +344,7 @@ func TestClient_DeleteUser(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteUser(tt.args.userID, 0, 0) + got, err := r.DeleteUser(tt.args.userID, 1000, 10) if (err != nil) != tt.wantErr { t.Errorf("Client.DeleteUser() error = %v, wantErr %v", err, tt.wantErr) return @@ -630,13 +650,34 @@ func TestClient_DeleteGroup(t *testing.T) { 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.*`, - httpmock.NewJsonResponderOrPanic(202, testGroup1), + func(req *http.Request) (*http.Response, error) { + // counter = counter + 1 + // if counter%4 == 0 { + // return httpmock.NewJsonResponse(404, testGroup1) + // } + return httpmock.NewJsonResponse(201, testGroup1) + }, ) httpmock.RegisterResponder("GET", `=~^https://test/api/v4/groups.*`, - httpmock.NewJsonResponderOrPanic(200, testGroupArray), + func(req *http.Request) (*http.Response, error) { + counter = counter + 1 + if counter%4 == 0 { + return httpmock.NewJsonResponse(404, testGroup1) + } + return httpmock.NewJsonResponse(202, testGroup1) + }, ) // test objects @@ -665,7 +706,7 @@ func TestClient_DeleteGroup(t *testing.T) { name: "DeleteGroup 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, args: args{groupID: testGroupID}, - want: 202, + want: 404, wantErr: false, }, } @@ -676,7 +717,7 @@ func TestClient_DeleteGroup(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteGroup(tt.args.groupID, 0, 0) + got, err := r.DeleteGroup(tt.args.groupID, 1000, 10) if (err != nil) != tt.wantErr { t.Errorf("Client.DeleteGroup() 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 f826ae0..04cff12 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -93,7 +93,7 @@ func TestClient_AdHoc_deleteUser_None(t *testing.T) { return } username := "notfound" - statusCode, err := c.DeleteUserByUsername(username, 1000, 20) + statusCode, err := c.DeleteUserByUsername(username, 100, 200) if err != nil { t.Errorf("Client.DeleteUser() error = %v", err) return @@ -157,9 +157,9 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { group, statusCode, err := c.GetGroupByFullPath(&groupFullPath) if (err == nil) && (statusCode == http.StatusFound) { - + t.Logf("DeleteGroup %s. This can take minutes, set log level to DEBUG to see detailed progress.", groupFullPath) // delete and wait for resource to clear.. up to 120 seconds - statusCode, err = c.DeleteGroup(group.ID, 1000, 120) + statusCode, err = c.DeleteGroup(group.ID, 100, 1200) rlog.Debugf(">>>>>>>> delete group %d", statusCode) } @@ -192,7 +192,7 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { } t.Logf("AddGroup: %s %d", subgroup2.FullPath, statusCode) - for i := 1; i <= 250; i++ { + for i := 1; i <= 125; i++ { projectName := "test project " + fmt.Sprintf("%d", i) projectObj := gogitlab.Project{Name: projectName} @@ -204,7 +204,7 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { t.Logf("AddProject: [%s, %s, %d]", got.NameWithNamespace, got.HTTPURLToRepo, statusCode) } } - for i := 1; i <= 250; i++ { + for i := 1; i <= 125; i++ { projectName := "test project " + fmt.Sprintf("%d", i) projectObj := gogitlab.Project{Name: projectName} diff --git a/integration-tests/gitlab/api/gitlab_api_test.go b/integration-tests/gitlab/api/gitlab_api_test.go index a0a3cfd..9b0c6f1 100644 --- a/integration-tests/gitlab/api/gitlab_api_test.go +++ b/integration-tests/gitlab/api/gitlab_api_test.go @@ -96,7 +96,7 @@ func TestClient_deleteUsers(t *testing.T) { for i := 1; i <= testItemCount; i++ { username := "testuser" + fmt.Sprintf("%d", i) - statusCode, err := c.DeleteUserByUsername(username) + statusCode, err := c.DeleteUserByUsername(username, 100, 200) if err != nil { t.Errorf("Client.DeleteUser() error = %v %d", err, statusCode) @@ -178,7 +178,7 @@ func TestClient_deleteGroups(t *testing.T) { for x := 0; x < len(groupList); x++ { group := groupList[x] - statusCode, err := c.DeleteGroup(group.ID) + statusCode, err := c.DeleteGroup(group.ID, 100, 1200) if err != nil { t.Errorf("Client.DeleteGroup() error = %v %d", err, statusCode) diff --git a/rlog.conf b/rlog.conf index 23fd5be..d50c2ce 100644 --- a/rlog.conf +++ b/rlog.conf @@ -1,6 +1,6 @@ # Comment lines start with a '#' # export RLOG_CONF_FILE= -RLOG_LOG_LEVEL = DEBUG +RLOG_LOG_LEVEL = WARN RLOG_LOG_STREAM = stdout # time format - use ! to prevent override by environment variable RLOG_TIME_FORMAT="2006/01/06 15:04:05.00" -- GitLab From 5c49f6f2a9dbe913714360fd93d28fa3fa59aed3 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 22 Jun 2021 18:26:08 -0600 Subject: [PATCH 05/12] format --- clients/gitlab/client_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index d8b8bda..4361ff2 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -290,7 +290,7 @@ func TestClient_DeleteUser(t *testing.T) { // mock to list out the articles counter := 0 - + httpmock.RegisterResponder("DELETE", `=~^https://test/api/v4/users.*`, func(req *http.Request) (*http.Response, error) { @@ -658,7 +658,7 @@ func TestClient_DeleteGroup(t *testing.T) { // `=~^https://test/api/v4/groups.*`, // httpmock.NewJsonResponderOrPanic(200, testGroupArray), // ) -var counter = 0; + var counter = 0 httpmock.RegisterResponder("DELETE", `=~^https://test/api/v4/groups.*`, func(req *http.Request) (*http.Response, error) { -- GitLab From 3183d4ceebd009dd3bd89f45bd4798ce8717d53b Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 22 Jun 2021 18:46:49 -0600 Subject: [PATCH 06/12] update docker image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b3cd263..bedb426 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # NOTE: USING THIS IMAGE UNTIL registry1 credentials are added to IL2 runners # Build the manager binary -FROM registry.il2.dso.mil/platform-one/devops/pipeline-templates/pipeline-job/golang-builder-1.6:1.0 as builder +FROM registry.il2.dso.mil/platform-one/devops/pipeline-templates/valkyrie/golang-builder-1.6:1.0 as builder WORKDIR /workspace # Copy the Go Modules manifests -- GitLab From 3ff0aa0f28967802268da8de3b539215c29df9b0 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 11:15:29 -0600 Subject: [PATCH 07/12] add updates --- clients/gitlab/client.go | 122 +++++++++++++++++++++++++++++++++- clients/gitlab/client_test.go | 76 +++++++++++++++++---- 2 files changed, 183 insertions(+), 15 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 4c73f70..c834939 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -149,6 +149,22 @@ func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, i return newUser, res.StatusCode, nil } +// UpdateUser - create a User object and update specific values +func (r Client) UpdateUser(user *gogitlab.User) (*gogitlab.User, int, error) { + var userID = user.ID + var opts = gogitlab.ModifyUserOptions{ + Username: &user.Username, + Email: &user.Email, + Name: &user.Name, + } + user, res, err := r.client.Users.ModifyUser(userID, &opts) + if err != nil { + return nil, 0, err + } + rlog.Debug(fmt.Sprintf("Completed call to UpdateUser. Status Code: %d", 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 @@ -374,6 +390,56 @@ func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { return project, nil } +// GetProjectByFullPath - +func (r Client) GetProjectByFullPath(fullPath *string) (*gogitlab.Project, int, error) { + // slow. get all groups and check for exact match to fullPath + listOptions := gogitlab.ListOptions{ + Page: 1, + PerPage: itemsPerPage, + } + + // some valid values path, name + logPrefix := "Completed call to GetProjectByFullPath." + 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 { + return nil, 0, err + } + for x := 0; x < len(projects) && !found; x++ { + rlog.Debugf("GetProjectByFullPath checking project %s", projects[x].PathWithNamespace) + if projects[x].PathWithNamespace == *fullPath { + found = true + rlog.Debugf("GetProjectByFullPath FOUND project %s", projects[x].PathWithNamespace) + project = projects[x] + } + } + + if res.NextPage > 0 { + opts.ListOptions.Page = opts.ListOptions.Page + 1 + } else { + more = false + } + + } + if !found { + rlog.Debug(fmt.Sprintf("%s NOT FOUND %s", logPrefix, *fullPath)) + return nil, http.StatusNotFound, nil + } + rlog.Debug(fmt.Sprintf("%s FOUND %s", logPrefix, project.PathWithNamespace)) + return project, http.StatusFound, nil +} + // GetProjects - func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { listOptions := gogitlab.ListOptions{ @@ -435,11 +501,61 @@ func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Pr return newProject, res.StatusCode, nil } +// AddProject - +func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Project, int, error) { + // 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, + NamespaceID: &groupID, + // hard coded values + Visibility: &visibility, + } + + newProject, res, err := r.client.Projects.CreateProject(&opts) + if err != nil { + return nil, res.StatusCode, err + } + return newProject, 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 + return 0, err + } + rlog.Debugf("% status: %d", logPrefix, 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 { + rlog.Warnf("%s hard error: %v", 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)) + } } + rlog.Debugf("Completed %s, status: %d", logPrefix, res.StatusCode) return res.StatusCode, nil -} +} \ No newline at end of file diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 4361ff2..276e800 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -273,6 +273,70 @@ 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)) + + type fields struct { + client *gogitlab.Client + token string + apiURL string + } + type args struct { + user *gogitlab.User + } + 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}, + 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) + 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{} @@ -644,20 +708,8 @@ 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.*`, -- GitLab From 342c79e359489209bdaf6a3a8b324f73775d4bd6 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 13:14:33 -0600 Subject: [PATCH 08/12] snapshot work --- clients/gitlab/client.go | 161 +++++++++++++----- .../gitlab/api/gitlab_api_groups_test.go | 112 ++++++++++++ .../gitlab/api/gitlab_api_users_test.go | 156 +++++++++++++++++ 3 files changed, 385 insertions(+), 44 deletions(-) create mode 100644 integration-tests/gitlab/api/gitlab_api_groups_test.go create mode 100644 integration-tests/gitlab/api/gitlab_api_users_test.go diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index c834939..cd2adce 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -76,21 +76,24 @@ 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 { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, 0, err } - rlog.Debugf("Completed call to GetUser userID: %d", user.ID) + rlog.Debugf("Completed %s userID: %d", logPrefix, user.ID) return user, res.StatusCode, nil } // GetUsers - func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { + logPrefix := "GetUsers" getCustomeAttributes := true listOptions := gogitlab.ListOptions{ @@ -105,8 +108,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 +119,7 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { for more { users, res, err := r.client.Users.ListUsers(&opts) if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, err } for x := 0; x < len(users); x++ { @@ -129,12 +133,39 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { } } - rlog.Debug(fmt.Sprintf("Completed call to GetUsers. Records returned: %d", len(userList))) + rlog.Debug(fmt.Sprintf("Completed %s. Records returned: %d", logPrefix, len(userList))) return userList, nil } +// GetUsers - +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 { + rlog.Warnf("%s error: %v", 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 + rlog.Debugf("Completed %s. statusCode: %d", logPrefix, statusCode) + return users[0], statusCode, nil +} + // AddUser - func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, int, error) { + logPrefix := "AddUser" var opts = gogitlab.CreateUserOptions{ Username: &user.Username, Email: &user.Email, @@ -143,14 +174,16 @@ func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, i } newUser, res, err := r.client.Users.CreateUser(&opts) if err != nil { - return nil, res.StatusCode, err + rlog.Warnf("%s error: %v", logPrefix, err) + return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to AddUser. Status Code: %d", res.StatusCode)) + rlog.Debug(fmt.Sprintf("Completed %s. Status Code: %d", logPrefix, res.StatusCode)) return newUser, res.StatusCode, nil } // UpdateUser - create a User object and update specific values func (r Client) UpdateUser(user *gogitlab.User) (*gogitlab.User, int, error) { + logPrefix := "UpdateUser" var userID = user.ID var opts = gogitlab.ModifyUserOptions{ Username: &user.Username, @@ -159,9 +192,10 @@ func (r Client) UpdateUser(user *gogitlab.User) (*gogitlab.User, int, error) { } user, res, err := r.client.Users.ModifyUser(userID, &opts) if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to UpdateUser. Status Code: %d", res.StatusCode)) + rlog.Debug(fmt.Sprintf("Completed %s. Status Code: %d", logPrefix, res.StatusCode)) return user, res.StatusCode, nil } @@ -169,11 +203,13 @@ func (r Client) UpdateUser(user *gogitlab.User) (*gogitlab.User, int, error) { 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 + rlog.Warnf("%s error: %v", logPrefix, err) + return 0, err } - rlog.Debugf("DeleteUser status: %d", res.StatusCode) + rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) // wait for resource to be deleted if waitCount > 0 { done := false @@ -185,18 +221,18 @@ 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) + rlog.Warnf("%s error: %v", 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)) } } - rlog.Debugf("Completed call to DeleteUser status: %d", res.StatusCode) + rlog.Debugf("Completed %s status: %d", logPrefix, res.StatusCode) return res.StatusCode, nil } @@ -207,9 +243,10 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun // 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 + rlog.Warnf("%s error: %v", logPrefix, err) + return 0, err } if len(users) == 0 { statusCode := http.StatusNotFound @@ -219,6 +256,7 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun statusCode, err := r.DeleteUser(users[0].ID, waitInterval, waitCount) if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) return 0, err } rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, statusCode)) @@ -227,25 +265,26 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun // GetGroup - func (r Client) GetGroup(groupID int) (*gogitlab.Group, int, error) { + logPrefix := "GetGroup" group, res, err := r.client.Groups.GetGroup(groupID) if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed call to GetGroup. groupID: %d", group.ID)) + rlog.Debug(fmt.Sprintf("Completed %s. groupID: %d", logPrefix, group.ID)) 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, @@ -260,6 +299,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 { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, 0, err } for x := 0; x < len(groups) && !found; x++ { @@ -288,6 +328,7 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro // GetGroups - func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { + logPrefix := "GetGroups" listOptions := gogitlab.ListOptions{ Page: 1, PerPage: itemsPerPage, @@ -309,6 +350,7 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { for more { groups, res, err := r.client.Groups.ListGroups(&opts) if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) return nil, err } for x := 0; x < len(groups); x++ { @@ -322,12 +364,36 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { } } - rlog.Debug(fmt.Sprintf("Completed call to GetGroups. Records returned: %d", len(groupList))) + rlog.Debugf("Completed %s. Records returned: %d", logPrefix, len(groupList)) return groupList, nil } // AddGroup - func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*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, + Visibility: &visibility, + } + + newGroup, res, err := r.client.Groups.CreateGroup(&opts) + if err != nil { + rlog.Warnf("%s error: %v", logPrefix, err) + return nil, 0, err + } + rlog.Debugf("Completed %s. statusCode: %d", logPrefix, res.StatusCode) + return newGroup, res.StatusCode, nil +} + +// AddGroup - +func (r Client) UpdateGroup(group *gogitlab.Group, parentID *int) (*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 // force visibility to private @@ -342,7 +408,7 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, newGroup, res, err := r.client.Groups.CreateGroup(&opts) if err != nil { - return nil, res.StatusCode, err + return nil, 0, err } return newGroup, res.StatusCode, nil } @@ -351,11 +417,14 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, 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 { + rlog.Warnf("%s error: %v", logPrefix, err) return 0, err } - rlog.Debugf("DeleteGroup status: %d", res.StatusCode) + rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) + returnStatusCode := res.StatusCode // wait for resource to be deleted if waitCount > 0 { done := false @@ -363,7 +432,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) + rlog.Warnf("%s error: %v", logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -373,33 +442,42 @@ 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 + rlog.Debugf("Completed %s statusCode: %d", logPrefix, returnStatusCode) + return returnStatusCode, nil } // GetProject - func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { + logPrefix := "GetProject" opts := gogitlab.GetProjectOptions{} project, res, err := r.client.Projects.GetProject(projectID, &opts) if err != nil { + rlog.Warnf("%s hard error: %v", logPrefix, err) return nil, err } - rlog.Debugf("Completed call to GetProject. status Code: %d", res.StatusCode) + rlog.Debugf("Completed %s. status Code: %d", logPrefix, res.StatusCode) return project, 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 - logPrefix := "Completed call to GetProjectByFullPath." + orderBy := "path" opts := gogitlab.ListProjectsOptions{ ListOptions: listOptions, @@ -417,10 +495,10 @@ func (r Client) GetProjectByFullPath(fullPath *string) (*gogitlab.Project, int, return nil, 0, err } for x := 0; x < len(projects) && !found; x++ { - rlog.Debugf("GetProjectByFullPath checking project %s", projects[x].PathWithNamespace) + rlog.Debugf("%s checking %s", logPrefix, projects[x].PathWithNamespace) if projects[x].PathWithNamespace == *fullPath { found = true - rlog.Debugf("GetProjectByFullPath FOUND project %s", projects[x].PathWithNamespace) + rlog.Debugf("%s FOUND %s", logPrefix, projects[x].PathWithNamespace) project = projects[x] } } @@ -476,7 +554,7 @@ func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { more = false } } - rlog.Debugf("Completed call to GetProjectss. Records returned: %d", len(projectList)) + rlog.Debugf("Completed call to GetProjects. Records returned: %d", len(projectList)) return projectList, nil } @@ -496,30 +574,25 @@ func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Pr newProject, res, err := r.client.Projects.CreateProject(&opts) if err != nil { - return nil, res.StatusCode, err + return nil, 0, err } return newProject, res.StatusCode, nil } -// AddProject - -func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Project, int, error) { - // force visibility to private - var visibility = gogitlab.PrivateVisibility +// UpdateProject - +func (r Client) UpdateProject(project *gogitlab.Project) (*gogitlab.Project, int, error) { // copy customizable settings from argument, hard code other options as desired - var opts = gogitlab.CreateProjectOptions{ + var opts = gogitlab.EditProjectOptions{ Name: &project.Name, Path: &project.Path, Description: &project.Description, - NamespaceID: &groupID, - // hard coded values - Visibility: &visibility, } - newProject, res, err := r.client.Projects.CreateProject(&opts) + project, res, err := r.client.Projects.EditProject(project.ID, &opts) if err != nil { - return nil, res.StatusCode, err + return nil, 0, err } - return newProject, res.StatusCode, nil + return project, res.StatusCode, nil } // DeleteProject - @@ -535,17 +608,17 @@ func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (i // wait for resource to be deleted withCustomAttributes := false - opts := gogitlab.GetProjectOptions { - WithCustomAttributes: &withCustomAttributes, + opts := gogitlab.GetProjectOptions{ + WithCustomAttributes: &withCustomAttributes, } if waitCount > 0 { done := false retryCount := waitCount for !done && retryCount > 0 { - _, res, err = r.client.Projects.GetProject(projectID,&opts) + _, res, err = r.client.Projects.GetProject(projectID, &opts) if err != nil && res == nil { - rlog.Warnf("%s hard error: %v", logPrefix, err) + rlog.Warnf("%s error: %v", logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -558,4 +631,4 @@ func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (i } rlog.Debugf("Completed %s, status: %d", logPrefix, res.StatusCode) return res.StatusCode, nil -} \ No newline at end of file +} 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 0000000..229ca5b --- /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_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go new file mode 100644 index 0000000..3cf5c2c --- /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" + user.Name=testName + _, statusCode, err = c.UpdateUser(user) + + // 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) + } + } + + }) +} + -- GitLab From 15b02de4dcddf293f79541a7080328422d835c0d Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 14:25:18 -0600 Subject: [PATCH 09/12] group update --- clients/gitlab/client.go | 53 ++- clients/gitlab/client_test.go | 8 +- .../gitlab/api/gitlab_api_projects_test.go | 319 ++++++++++++++++++ 3 files changed, 362 insertions(+), 18 deletions(-) create mode 100644 integration-tests/gitlab/api/gitlab_api_projects_test.go diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index cd2adce..eed1b27 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -137,7 +137,7 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { return userList, nil } -// GetUsers - +// GetUserByUsername - func (r Client) GetUserByUsername(username *string) (*gogitlab.User, int, error) { logPrefix := "GetUserByUsername" getCustomeAttributes := true @@ -181,14 +181,13 @@ func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, i return newUser, res.StatusCode, nil } -// UpdateUser - create a User object and update specific values -func (r Client) UpdateUser(user *gogitlab.User) (*gogitlab.User, int, error) { +// 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 userID = user.ID + var opts = gogitlab.ModifyUserOptions{ - Username: &user.Username, - Email: &user.Email, - Name: &user.Name, + Email: modifyUserOptions.Email, + Name: modifyUserOptions.Name, } user, res, err := r.client.Users.ModifyUser(userID, &opts) if err != nil { @@ -210,6 +209,7 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er return 0, err } rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) + returnStatusCode := res.StatusCode // wait for resource to be deleted if waitCount > 0 { done := false @@ -231,9 +231,15 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er 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 %s status: %d", logPrefix, res.StatusCode) - return res.StatusCode, nil + return returnStatusCode, nil } // DeleteUserByUsername - convenience method @@ -392,25 +398,42 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, return newGroup, res.StatusCode, nil } -// AddGroup - -func (r Client) UpdateGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, int, error) { +// 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 { + rlog.Warnf("%s error: %v", logPrefix, err) + return nil, 0, err + } + rlog.Debugf("Completed %s. statusCode: %d", logPrefix, res.StatusCode) + return groupMember, res.StatusCode, nil +} + +// UpdateGroup - +func (r Client) UpdateGroup(group *gogitlab.Group) (*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 // force visibility to private var visibility = gogitlab.PrivateVisibility - var opts = gogitlab.CreateGroupOptions{ + var opts = gogitlab.UpdateGroupOptions{ Name: &group.Name, Path: &group.Path, Description: &group.Description, - ParentID: parentID, Visibility: &visibility, } - newGroup, res, err := r.client.Groups.CreateGroup(&opts) + group, res, err := r.client.Groups.UpdateGroup(group.ID, &opts) + if err != nil { return nil, 0, err } - return newGroup, res.StatusCode, nil + return group, res.StatusCode, nil } // DeleteGroup - diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 276e800..d86a2c9 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -291,6 +291,7 @@ func TestClient_UpdateUser(t *testing.T) { 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 @@ -298,7 +299,8 @@ func TestClient_UpdateUser(t *testing.T) { apiURL string } type args struct { - user *gogitlab.User + user *gogitlab.User + modifyUserOptions gogitlab.ModifyUserOptions } tests := []struct { name string @@ -311,7 +313,7 @@ func TestClient_UpdateUser(t *testing.T) { { name: "UpdateUser 1", fields: fields{client: testGitlabClient, token: testToken, apiURL: testAPIUrl}, - args: args{user: &testUser1}, + args: args{user: &testUser1, modifyUserOptions: gogitlab.ModifyUserOptions{Name: &updatedName}}, want: &testUser1, wantErr: false, }, @@ -323,7 +325,7 @@ func TestClient_UpdateUser(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, _, err := r.UpdateUser(tt.args.user) + 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 diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go new file mode 100644 index 0000000..9b0c6f1 --- /dev/null +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -0,0 +1,319 @@ +// +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)) + }) +} -- GitLab From f11b28f0aa552f69b465fd8ce88854bcb77d6366 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 15:28:41 -0600 Subject: [PATCH 10/12] standardize all calls. --- clients/gitlab/client.go | 172 ++++++---- clients/gitlab/client_test.go | 23 +- .../gitlab/api/gitlab_api_adhoc_test.go | 6 +- .../gitlab/api/gitlab_api_projects_test.go | 319 ------------------ .../gitlab/api/gitlab_api_test.go | 319 ------------------ 5 files changed, 117 insertions(+), 722 deletions(-) delete mode 100644 integration-tests/gitlab/api/gitlab_api_projects_test.go delete mode 100644 integration-tests/gitlab/api/gitlab_api_test.go diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index eed1b27..c1294a7 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,14 @@ type Client struct { apiURL string } +func processError(logPrefix string, err error) { + rlog.Warnf("%s error: %v", logPrefix, err) +} + +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 @@ -83,11 +90,11 @@ func (r Client) GetUser(userID int) (*gogitlab.User, int, error) { } user, res, err := r.client.Users.GetUser(userID, opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } - rlog.Debugf("Completed %s userID: %d", logPrefix, user.ID) + processComplete(logPrefix, res.StatusCode) return user, res.StatusCode, nil } @@ -119,7 +126,7 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { for more { users, res, err := r.client.Users.ListUsers(&opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, err } for x := 0; x < len(users); x++ { @@ -133,7 +140,7 @@ func (r Client) GetUsers(search *string) ([]*gogitlab.User, error) { } } - rlog.Debug(fmt.Sprintf("Completed %s. Records returned: %d", logPrefix, len(userList))) + processComplete(logPrefix, http.StatusOK) return userList, nil } @@ -148,7 +155,7 @@ func (r Client) GetUserByUsername(username *string) (*gogitlab.User, int, error) users, _, err := r.client.Users.ListUsers(&opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } @@ -159,7 +166,7 @@ func (r Client) GetUserByUsername(username *string) (*gogitlab.User, int, error) } statusCode := http.StatusFound - rlog.Debugf("Completed %s. statusCode: %d", logPrefix, statusCode) + processComplete(logPrefix, statusCode) return users[0], statusCode, nil } @@ -174,10 +181,11 @@ func (r Client) AddUser(user *gogitlab.User, password string) (*gogitlab.User, i } newUser, res, err := r.client.Users.CreateUser(&opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) + return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed %s. Status Code: %d", logPrefix, res.StatusCode)) + processComplete(logPrefix, res.StatusCode) return newUser, res.StatusCode, nil } @@ -191,10 +199,10 @@ func (r Client) UpdateUser(userID int, modifyUserOptions *gogitlab.ModifyUserOpt } user, res, err := r.client.Users.ModifyUser(userID, &opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed %s. Status Code: %d", logPrefix, res.StatusCode)) + processComplete(logPrefix, res.StatusCode) return user, res.StatusCode, nil } @@ -205,7 +213,7 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er logPrefix := "DeleteUser" res, err := r.client.Users.DeleteUser(userID) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) @@ -221,7 +229,7 @@ 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("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -238,7 +246,7 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er } } - rlog.Debugf("Completed %s status: %d", logPrefix, res.StatusCode) + processComplete(logPrefix, res.StatusCode) return returnStatusCode, nil } @@ -251,21 +259,24 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun var opts = gogitlab.ListUsersOptions{Username: &username} users, _, err := r.client.Users.ListUsers(&opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, 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 { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } - rlog.Debug(fmt.Sprintf("%s Status Code: %d", logPrefix, statusCode)) + + processComplete(logPrefix, statusCode) return statusCode, nil } @@ -274,11 +285,11 @@ func (r Client) GetGroup(groupID int) (*gogitlab.Group, int, error) { logPrefix := "GetGroup" group, res, err := r.client.Groups.GetGroup(groupID) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } - rlog.Debug(fmt.Sprintf("Completed %s. groupID: %d", logPrefix, group.ID)) + processComplete(logPrefix, res.StatusCode) return group, res.StatusCode, nil } @@ -305,7 +316,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 { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } for x := 0; x < len(groups) && !found; x++ { @@ -325,10 +336,11 @@ 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 } @@ -346,19 +358,22 @@ 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 { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, err } + for x := 0; x < len(groups); x++ { groupList = append(groupList, groups[x]) } @@ -368,9 +383,9 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { } else { more = false } - } - rlog.Debugf("Completed %s. Records returned: %d", logPrefix, len(groupList)) + + processComplete(logPrefix, http.StatusOK) return groupList, nil } @@ -391,10 +406,11 @@ func (r Client) AddGroup(group *gogitlab.Group, parentID *int) (*gogitlab.Group, newGroup, res, err := r.client.Groups.CreateGroup(&opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } - rlog.Debugf("Completed %s. statusCode: %d", logPrefix, res.StatusCode) + + processComplete(logPrefix, res.StatusCode) return newGroup, res.StatusCode, nil } @@ -409,30 +425,26 @@ func (r Client) AddGroupMember(groupID *int, userID *int, accessLevel gogitlab.A groupMember, res, err := r.client.GroupMembers.AddGroupMember(groupID, &opts) if err != nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return nil, 0, err } - rlog.Debugf("Completed %s. statusCode: %d", logPrefix, res.StatusCode) + + processComplete(logPrefix, res.StatusCode) return groupMember, res.StatusCode, nil } // UpdateGroup - -func (r Client) UpdateGroup(group *gogitlab.Group) (*gogitlab.Group, int, error) { - // https://stackoverflow.com/questions/65081356/how-do-you-create-a-project-in-a-specific-group-via-gitlab-api - // force visibility to private - var visibility = gogitlab.PrivateVisibility - var opts = gogitlab.UpdateGroupOptions{ - Name: &group.Name, - Path: &group.Path, - Description: &group.Description, - Visibility: &visibility, - } +func (r Client) UpdateGroup(groupID int, updateGroupOptions *gogitlab.UpdateGroupOptions) (*gogitlab.Group, int, error) { + logPrefix := "UpdateGroup" - group, res, err := r.client.Groups.UpdateGroup(group.ID, &opts) + 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 } @@ -441,12 +453,14 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, // 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 { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } - rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) + returnStatusCode := res.StatusCode // wait for resource to be deleted if waitCount > 0 { @@ -455,7 +469,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("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -471,7 +485,7 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, returnStatusCode = http.StatusRequestTimeout } } - rlog.Debugf("Completed %s statusCode: %d", logPrefix, returnStatusCode) + processComplete(logPrefix, returnStatusCode) return returnStatusCode, nil } @@ -479,13 +493,15 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { logPrefix := "GetProject" opts := gogitlab.GetProjectOptions{} + project, res, err := r.client.Projects.GetProject(projectID, &opts) + if err != nil { - rlog.Warnf("%s hard error: %v", logPrefix, err) + processError(logPrefix, err) return nil, err } - rlog.Debugf("Completed %s. status Code: %d", logPrefix, res.StatusCode) + processComplete(logPrefix, res.StatusCode) return project, nil } @@ -514,9 +530,12 @@ func (r Client) GetProjectByFullPath(fullPath *string) (*gogitlab.Project, int, // 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 { @@ -531,18 +550,21 @@ func (r Client) GetProjectByFullPath(fullPath *string) (*gogitlab.Project, int, } else { more = false } - } + 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, project.PathWithNamespace)) + + 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, @@ -565,6 +587,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++ { @@ -577,19 +600,21 @@ func (r Client) GetProjects(search *string) ([]*gogitlab.Project, error) { more = false } } - rlog.Debugf("Completed call to GetProjects. 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, @@ -597,24 +622,31 @@ func (r Client) AddProject(project *gogitlab.Project, groupID int) (*gogitlab.Pr newProject, res, err := r.client.Projects.CreateProject(&opts) if err != nil { + processError(logPrefix, err) return nil, 0, err } + + processComplete(logPrefix, res.StatusCode) return newProject, res.StatusCode, nil } // UpdateProject - -func (r Client) UpdateProject(project *gogitlab.Project) (*gogitlab.Project, int, error) { +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: &project.Name, - Path: &project.Path, - Description: &project.Description, + Name: editProjectOptions.Name, + Path: editProjectOptions.Path, + Description: editProjectOptions.Description, } - project, res, err := r.client.Projects.EditProject(project.ID, &opts) + 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 } @@ -625,9 +657,11 @@ func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (i // setting wait will use a loop to wait until resource has completed deletion res, err := r.client.Projects.DeleteProject(projectID) if err != nil { + processError(logPrefix, err) return 0, err } - rlog.Debugf("% status: %d", logPrefix, res.StatusCode) + + returnStatusCode := res.StatusCode // wait for resource to be deleted withCustomAttributes := false @@ -638,10 +672,11 @@ func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (i if waitCount > 0 { done := false retryCount := waitCount + for !done && retryCount > 0 { _, res, err = r.client.Projects.GetProject(projectID, &opts) if err != nil && res == nil { - rlog.Warnf("%s error: %v", logPrefix, err) + processError(logPrefix, err) return 0, err } if res.StatusCode == http.StatusNotFound { @@ -651,7 +686,14 @@ func (r Client) DeleteProject(projectID int, waitInterval int, waitCount int) (i 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 %s, status: %d", logPrefix, res.StatusCode) - 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 d86a2c9..337ced3 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -349,20 +349,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) { @@ -399,7 +393,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, }, } @@ -716,10 +710,6 @@ func TestClient_DeleteGroup(t *testing.T) { 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) }, ) @@ -760,7 +750,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, }, } @@ -934,6 +924,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", @@ -952,7 +943,7 @@ func TestClient_AddProject(t *testing.T) { apiURL string } type args struct { - project *gogitlab.Project + createProjectOptions *gogitlab.CreateProjectOptions groupID int } tests := []struct { @@ -966,7 +957,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, @@ -979,7 +970,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 04cff12..c1c340d 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -195,7 +195,7 @@ 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} + projectObj := gogitlab.CreateProjectOptions{Name: &projectName} got, statusCode, err := c.AddProject(&projectObj, group.ID) if err != nil { @@ -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_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go deleted file mode 100644 index 9b0c6f1..0000000 --- a/integration-tests/gitlab/api/gitlab_api_projects_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_test.go b/integration-tests/gitlab/api/gitlab_api_test.go deleted file mode 100644 index 9b0c6f1..0000000 --- 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)) - }) -} -- GitLab From a793814976118d1cbc82df168434389da3ada45f Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 15:59:20 -0600 Subject: [PATCH 11/12] fix integration tests --- integration-tests/gitlab/api/gitlab_api_adhoc_test.go | 2 +- integration-tests/gitlab/api/gitlab_api_users_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go index c1c340d..b07cf68 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -196,7 +196,7 @@ func TestClient_AdHoc_addGroups_SubGroup(t *testing.T) { projectName := "test project " + fmt.Sprintf("%d", i) projectObj := gogitlab.CreateProjectOptions{Name: &projectName} - got, statusCode, err := c.AddProject(&projectObj, group.ID) + got, statusCode, err := c.AddProject(projectObj, group.ID) if err != nil { t.Errorf("Client.AddProject() error = %v %d", err, statusCode) diff --git a/integration-tests/gitlab/api/gitlab_api_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go index 3cf5c2c..28f3f74 100644 --- a/integration-tests/gitlab/api/gitlab_api_users_test.go +++ b/integration-tests/gitlab/api/gitlab_api_users_test.go @@ -96,8 +96,8 @@ func TestClient_UpdateUser(t *testing.T) { // update user testName := "Updated Username 01" - user.Name=testName - _, statusCode, err = c.UpdateUser(user) + modifyUserOptions := gogitlab.ModifyUserOptions{Name: &testName} + _, statusCode, err = c.UpdateUser(user.ID, &modifyUserOptions) // get user user, statusCode, err = c.GetUserByUsername(&username) -- GitLab From 9ff0eed5672328301fe8a6d31dad43f7e831d6b4 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 23 Jun 2021 16:33:56 -0600 Subject: [PATCH 12/12] use gogitlab objects for create and update calls --- clients/gitlab/client.go | 55 +++++++++++++++++++++++++---------- clients/gitlab/client_test.go | 23 ++++++++------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index c1294a7..42fb342 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -52,10 +52,12 @@ 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) } @@ -84,11 +86,14 @@ 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 @@ -171,20 +176,22 @@ func (r Client) GetUserByUsername(username *string) (*gogitlab.User, int, error) } // 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 { processError(logPrefix, err) - return nil, 0, err } + processComplete(logPrefix, res.StatusCode) return newUser, res.StatusCode, nil } @@ -197,11 +204,14 @@ func (r Client) UpdateUser(userID int, modifyUserOptions *gogitlab.ModifyUserOpt 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 } @@ -211,13 +221,16 @@ func (r Client) DeleteUser(userID int, waitInterval int, waitCount int) (int, er // 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 { processError(logPrefix, err) return 0, err } - rlog.Debugf("%s status: %d", logPrefix, res.StatusCode) + returnStatusCode := res.StatusCode + // wait for resource to be deleted if waitCount > 0 { done := false @@ -256,8 +269,11 @@ 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, _, err := r.client.Users.ListUsers(&opts) + if err != nil { processError(logPrefix, err) return 0, err @@ -283,7 +299,9 @@ func (r Client) DeleteUserByUsername(username string, waitInterval int, waitCoun // 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 @@ -297,6 +315,7 @@ func (r Client) GetGroup(groupID int) (*gogitlab.Group, int, error) { 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, @@ -335,6 +354,7 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro } } + if !found { processComplete(logPrefix, http.StatusNotFound) return nil, http.StatusNotFound, nil @@ -347,6 +367,7 @@ func (r Client) GetGroupByFullPath(fullPath *string) (*gogitlab.Group, int, erro // GetGroups - func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { logPrefix := "GetGroups" + listOptions := gogitlab.ListOptions{ Page: 1, PerPage: itemsPerPage, @@ -365,6 +386,7 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { } groupList := []*gogitlab.Group{} + var more = true for more { groups, res, err := r.client.Groups.ListGroups(&opts) @@ -390,21 +412,23 @@ func (r Client) GetGroups(search *string) ([]*gogitlab.Group, error) { } // 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 { processError(logPrefix, err) return nil, 0, err @@ -490,7 +514,7 @@ func (r Client) DeleteGroup(groupID int, waitInterval int, waitCount int) (int, } // 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{} @@ -498,11 +522,11 @@ func (r Client) GetProject(projectID int) (*gogitlab.Project, error) { if err != nil { processError(logPrefix, err) - return nil, err + return nil, 0, err } processComplete(logPrefix, res.StatusCode) - return project, nil + return project, res.StatusCode, nil } // GetProjectByFullPath - @@ -621,6 +645,7 @@ func (r Client) AddProject(createProjectOptions gogitlab.CreateProjectOptions, g } newProject, res, err := r.client.Projects.CreateProject(&opts) + if err != nil { processError(logPrefix, err) return nil, 0, err diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 337ced3..5c9e86d 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 @@ -640,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", @@ -659,7 +662,7 @@ func TestClient_AddGroup(t *testing.T) { apiURL string } type args struct { - group *gogitlab.Group + createGroupOptions gogitlab.CreateGroupOptions } tests := []struct { name string @@ -672,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, }, @@ -684,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 @@ -828,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 -- GitLab