Skip to content

Commit 72b480a

Browse files
committed
add: quota list command
Signed-off-by: bupd <bupdprasanth@gmail.com>
1 parent ec6b9f4 commit 72b480a

6 files changed

Lines changed: 208 additions & 0 deletions

File tree

cmd/harbor/root/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/goharbor/harbor-cli/cmd/harbor/root/artifact"
99
"github.com/goharbor/harbor-cli/cmd/harbor/root/project"
10+
"github.com/goharbor/harbor-cli/cmd/harbor/root/quota"
1011
"github.com/goharbor/harbor-cli/cmd/harbor/root/registry"
1112
repositry "github.com/goharbor/harbor-cli/cmd/harbor/root/repository"
1213
"github.com/goharbor/harbor-cli/cmd/harbor/root/user"
@@ -106,6 +107,7 @@ harbor help
106107
repositry.Repository(),
107108
user.User(),
108109
artifact.Artifact(),
110+
quota.Quota(),
109111
)
110112

111113
return root

cmd/harbor/root/quota/cmd.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package quota
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
func Quota() *cobra.Command {
8+
cmd := &cobra.Command{
9+
Use: "quota",
10+
Short: "Manage quotas",
11+
Long: `Manage quotas`,
12+
Example: ` harbor quota list`,
13+
}
14+
cmd.AddCommand(
15+
ListQuotaCommand(),
16+
)
17+
18+
return cmd
19+
}

cmd/harbor/root/quota/list.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package quota
2+
3+
import (
4+
"github.com/goharbor/harbor-cli/pkg/api"
5+
"github.com/goharbor/harbor-cli/pkg/utils"
6+
"github.com/goharbor/harbor-cli/pkg/views/quota/list"
7+
log "github.com/sirupsen/logrus"
8+
"github.com/spf13/cobra"
9+
"github.com/spf13/viper"
10+
)
11+
12+
// Lists the Quotas specified for each project
13+
func ListQuotaCommand() *cobra.Command {
14+
var opts api.ListQuotaFlags
15+
16+
cmd := &cobra.Command{
17+
Use: "list",
18+
Short: "list quota",
19+
Run: func(cmd *cobra.Command, args []string) {
20+
quota, err := api.ListQuota(opts)
21+
if err != nil {
22+
log.Fatalf("failed to get projects list: %v", err)
23+
}
24+
FormatFlag := viper.GetString("output-format")
25+
if FormatFlag != "" {
26+
utils.PrintPayloadInJSONFormat(quota)
27+
return
28+
}
29+
30+
list.ListQuotas(quota.Payload)
31+
},
32+
}
33+
34+
flags := cmd.Flags()
35+
flags.Int64VarP(&opts.Page, "page", "", 1, "Page number")
36+
flags.Int64VarP(&opts.PageSize, "page-size", "", 10, "Size of per page")
37+
flags.StringVarP(&opts.Reference, "ref", "", "", "Reference type of quota")
38+
flags.StringVarP(&opts.ReferenceID, "refid", "", "", "Reference ID of quota")
39+
flags.StringVarP(
40+
&opts.Sort,
41+
"sort",
42+
"",
43+
"",
44+
"Sort the resource list in ascending or descending order",
45+
)
46+
47+
return cmd
48+
}

pkg/api/quota_handler.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package api
2+
3+
import (
4+
"github.com/goharbor/go-client/pkg/sdk/v2.0/client/quota"
5+
"github.com/goharbor/harbor-cli/pkg/utils"
6+
)
7+
8+
func ListQuota(opts ListQuotaFlags) (quota.ListQuotasOK, error) {
9+
ctx, client, err := utils.ContextWithClient()
10+
if err != nil {
11+
return quota.ListQuotasOK{}, err
12+
}
13+
14+
response, err := client.Quota.ListQuotas(
15+
ctx,
16+
&quota.ListQuotasParams{
17+
Page: &opts.Page,
18+
PageSize: &opts.PageSize,
19+
Reference: &opts.Reference,
20+
ReferenceID: &opts.ReferenceID,
21+
Sort: &opts.Sort,
22+
},
23+
)
24+
if err != nil {
25+
return quota.ListQuotasOK{}, err
26+
}
27+
return *response, nil
28+
}

pkg/api/types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ type ListFlags struct {
88
Sort string
99
Public bool
1010
}
11+
12+
type ListQuotaFlags struct {
13+
PageSize int64
14+
Page int64
15+
Sort string
16+
Reference string
17+
ReferenceID string
18+
}

pkg/views/quota/list/view.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package list
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strconv"
7+
8+
"github.com/charmbracelet/bubbles/table"
9+
tea "github.com/charmbracelet/bubbletea"
10+
"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
11+
"github.com/goharbor/harbor-cli/pkg/utils"
12+
"github.com/goharbor/harbor-cli/pkg/views/base/tablelist"
13+
)
14+
15+
var columns = []table.Column{
16+
{Title: "ID", Width: 4},
17+
{Title: "Project", Width: 12},
18+
{Title: "Owner Name", Width: 12},
19+
{Title: "Storage", Width: 32},
20+
{Title: "Creation Time", Width: 20},
21+
}
22+
23+
// Function to get project details
24+
func GetProjectDetails(ref models.QuotaRefObject) (string, string, error) {
25+
if refMap, ok := ref.(map[string]interface{}); ok {
26+
projectName, _ := refMap["name"].(string)
27+
ownerName, _ := refMap["owner_name"].(string)
28+
return projectName, ownerName, nil
29+
}
30+
return "", "", fmt.Errorf("Error: Ref is not of expected type")
31+
}
32+
33+
// Function to convert bytes to human-readable storage
34+
func BytesToStorageString(bytes int64) string {
35+
const (
36+
mebibyte = 1024 * 1024
37+
gibibyte = 1024 * mebibyte
38+
)
39+
40+
mib := float64(bytes) / float64(mebibyte)
41+
42+
if mib >= 1024 {
43+
gib := mib / 1024
44+
return fmt.Sprintf("%.1f GiB", gib)
45+
}
46+
47+
return fmt.Sprintf("%.2f MiB", mib)
48+
}
49+
50+
// Function to calculate storage
51+
func CalculateStorage(hard models.ResourceList, used models.ResourceList) (string, string) {
52+
var storageUsed, storageGiven string
53+
54+
if hard["storage"] == -1 {
55+
storageGiven = "Unlimited"
56+
} else {
57+
storageGiven = BytesToStorageString(hard["storage"])
58+
}
59+
60+
if used["storage"] == 0 {
61+
storageUsed = "0 MiB"
62+
} else {
63+
storageUsed = BytesToStorageString(used["storage"])
64+
}
65+
66+
return storageUsed, storageGiven
67+
}
68+
69+
// Function to format storage
70+
func FormatStorage(hard models.ResourceList, used models.ResourceList) string {
71+
storageUsed, storageGiven := CalculateStorage(hard, used)
72+
return fmt.Sprintf("%v of %v", storageUsed, storageGiven)
73+
}
74+
75+
// ListQuotas in table format
76+
func ListQuotas(quotas []*models.Quota) {
77+
var rows []table.Row
78+
for _, quota := range quotas {
79+
projectName, ownerName, err := GetProjectDetails(quota.Ref)
80+
if err != nil {
81+
fmt.Println(err)
82+
continue
83+
}
84+
85+
storage := FormatStorage(quota.Hard, quota.Used)
86+
87+
createdTime, _ := utils.FormatCreatedTime(quota.CreationTime.String())
88+
rows = append(rows, table.Row{
89+
strconv.FormatInt(quota.ID, 10),
90+
projectName,
91+
ownerName,
92+
storage,
93+
createdTime,
94+
})
95+
}
96+
97+
m := tablelist.NewModel(columns, rows, len(rows))
98+
99+
if _, err := tea.NewProgram(m).Run(); err != nil {
100+
fmt.Println("Error running program:", err)
101+
os.Exit(1)
102+
}
103+
}

0 commit comments

Comments
 (0)