Skip to content

Comments

fix: optimizing user deletion, improving error handling and logging#698

Open
rkcoder101 wants to merge 6 commits intogoharbor:mainfrom
rkcoder101:fix/user-delete
Open

fix: optimizing user deletion, improving error handling and logging#698
rkcoder101 wants to merge 6 commits intogoharbor:mainfrom
rkcoder101:fix/user-delete

Conversation

@rkcoder101
Copy link
Contributor

@rkcoder101 rkcoder101 commented Feb 11, 2026

Description

The PR solves some issues related to user deletion:-

  • Currently during user deletion, say n users were to be deleted, then the API for getting all the users is hit n times, which is inefficient. It also defeats the purpose of performing deletion concurrently as it reduces the overall speed.
  • Absence of clear success/error messages in stdout

Fixes #697

…etion; improved error and happy path logging

Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
Copilot AI review requested due to automatic review settings February 11, 2026 12:23
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the harbor user delete command to avoid repeated user-list API calls when deleting multiple users, and to provide clearer success/failure output via RunE.

Changes:

  • Switch user delete to RunE and return errors instead of only logging.
  • Resolve usernames to IDs via a single ListUsers call and delete resolved users concurrently.
  • Print summarized success/failure results for multi-delete, plus a success message for interactive delete.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 43 to 49
allUsers, err := api.ListUsers()
if err != nil {
return fmt.Errorf("failed to list users: %v", utils.ParseHarborErrorMsg(err))
}
userMap := make(map[string]int64)
for _, u := range allUsers.Payload {
userMap[u.Username] = u.UserID
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

api.ListUsers() is called once and only the returned Payload is used to build userMap. Since the Harbor API is paginated, this will only cover a single page and can incorrectly mark valid usernames as "user not found" when there are more users than the default page size. Consider using the same paging loop as user list (set Page=1, PageSize=100, iterate until a short page) to build the map, or add an API helper that fetches all users before resolving names.

Suggested change
allUsers, err := api.ListUsers()
if err != nil {
return fmt.Errorf("failed to list users: %v", utils.ParseHarborErrorMsg(err))
}
userMap := make(map[string]int64)
for _, u := range allUsers.Payload {
userMap[u.Username] = u.UserID
userMap := make(map[string]int64)
page := int64(1)
pageSize := int64(100)
for {
allUsers, err := api.ListUsers(page, pageSize)
if err != nil {
return fmt.Errorf("failed to list users: %v", utils.ParseHarborErrorMsg(err))
}
for _, u := range allUsers.Payload {
userMap[u.Username] = u.UserID
}
if len(allUsers.Payload) < int(pageSize) {
break
}
page++

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 👍

Comment on lines 30 to 36
Use: "delete [username...]",
Short: "delete user by name",
Args: cobra.MinimumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
// If there are command line arguments, process them concurrently.
if len(args) > 0 {
var wg sync.WaitGroup
errChan := make(chan error, len(args)) // Channel to collect errors
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
userID := prompt.GetUserIdFromUser()
if err := api.DeleteUser(userID); err != nil {
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command help text now says "delete user by name", but when no args are provided it deletes by an interactively-entered user ID (prompt.GetUserIdFromUser). Either update the Short/Use/Long help to reflect both modes (name args vs interactive ID), or switch the prompt to select/enter a username for consistency with the command description.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 37 to 46
return fmt.Errorf("failed to delete user: %v", utils.ParseHarborErrorMsg(err))
}
fmt.Println("User deleted successfully")
return nil
}

for _, arg := range args {
// Retrieve user ID by name.
userID, err := api.GetUsersIdByName(arg)
if err != nil {
log.Errorf("failed to get user id for '%s': %v", arg, err)
continue
}
wg.Add(1)
go func(userID int64) {
defer wg.Done()
if err := api.DeleteUser(userID); err != nil {
errChan <- err
}
}(userID)
allUsers, err := api.ListUsers()
if err != nil {
return fmt.Errorf("failed to list users: %v", utils.ParseHarborErrorMsg(err))
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the error wraps, utils.ParseHarborErrorMsg(err) returns a string, but the format uses %v. Using %s (or embedding the string directly) would avoid printing Go formatting artifacts and keep error messages consistent with other command implementations.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
@rkcoder101
Copy link
Contributor Author

@bupd @NucleoFusion @qcserestipy kindly review this whenever u guys r free. Thanks!

@bupd
Copy link
Collaborator

bupd commented Feb 18, 2026

please resolve copilot reviews.

…led the API to fetch the users

Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 0% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 7.21%. Comparing base (60ad0bd) to head (d45aa96).
⚠️ Report is 98 commits behind head on main.

Files with missing lines Patch % Lines
cmd/harbor/root/user/delete.go 0.00% 71 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             main    #698      +/-   ##
=========================================
- Coverage   10.99%   7.21%   -3.78%     
=========================================
  Files         173     260      +87     
  Lines        8671   12953    +4282     
=========================================
- Hits          953     935      -18     
- Misses       7612   11910    +4298     
- Partials      106     108       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
@rkcoder101
Copy link
Contributor Author

please resolve copilot reviews.

done 👍 kindly review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Redundant API calls for user deletion

2 participants