Skip to content

Commit 19242fe

Browse files
committed
add: quota update command
Signed-off-by: bupd <bupdprasanth@gmail.com>
1 parent 4ad7725 commit 19242fe

4 files changed

Lines changed: 208 additions & 2 deletions

File tree

cmd/harbor/root/quota/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func Quota() *cobra.Command {
1414
cmd.AddCommand(
1515
ListQuotaCommand(),
1616
ViewQuotaCommand(),
17+
UpdateQuotaCommand(),
1718
)
1819

1920
return cmd

cmd/harbor/root/quota/update.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package quota
2+
3+
import (
4+
"errors"
5+
"os"
6+
"regexp"
7+
"strconv"
8+
9+
"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
10+
"github.com/goharbor/harbor-cli/pkg/api"
11+
"github.com/goharbor/harbor-cli/pkg/prompt"
12+
"github.com/goharbor/harbor-cli/pkg/views/quota/update"
13+
log "github.com/sirupsen/logrus"
14+
"github.com/spf13/cobra"
15+
)
16+
17+
type QuotaUpdateReq struct {
18+
// The new hard limits for the quota
19+
Hard ResourceList `json:"hard,omitempty"`
20+
}
21+
22+
type ResourceList map[string]int64
23+
24+
// UpdateQuotaCommand updates the quota
25+
func UpdateQuotaCommand() *cobra.Command {
26+
var (
27+
quotaID int64
28+
storage string
29+
)
30+
31+
cmd := &cobra.Command{
32+
Use: "update [QuotaID]",
33+
Short: "update project quotas for projects",
34+
Args: cobra.MaximumNArgs(1),
35+
Run: func(cmd *cobra.Command, args []string) {
36+
var err error
37+
var storageValue int64
38+
39+
if len(args) > 0 {
40+
quotaID, err = strconv.ParseInt(args[0], 10, 64)
41+
} else {
42+
quotaID = prompt.GetQuotaIDFromUser()
43+
}
44+
45+
if err != nil {
46+
log.Errorf("failed to parse registry id: %v", err)
47+
}
48+
49+
if storage != "" {
50+
if storage == "-1" {
51+
storageValue = -1
52+
} else {
53+
storageValue, err = storageStringToBytes(storage)
54+
if err != nil {
55+
log.Errorf("failed to parse storage: %v", err)
56+
os.Exit(1)
57+
}
58+
}
59+
} else {
60+
storage = update.UpdateQuotaView()
61+
storageValue, err = storageStringToBytes(storage)
62+
}
63+
64+
hardlimit := &models.QuotaUpdateReq{
65+
Hard: models.ResourceList{"storage": storageValue},
66+
}
67+
68+
err = api.UpdateQuota(quotaID, hardlimit)
69+
if err != nil {
70+
log.Errorf("failed to update quota: %v", err)
71+
os.Exit(1)
72+
}
73+
74+
log.Infof("quota updated successfully!")
75+
},
76+
}
77+
78+
flags := cmd.Flags()
79+
flags.StringVarP(&storage, "storage", "", "", "Enter storage size (e.g., 50GiB, 200MiB, 4TiB)")
80+
81+
return cmd
82+
}
83+
84+
func storageStringToBytes(storage string) (int64, error) {
85+
// Define the conversion multipliers
86+
multipliers := map[string]int64{
87+
"MiB": 1024 * 1024,
88+
"GiB": 1024 * 1024 * 1024,
89+
"TiB": 1024 * 1024 * 1024 * 1024,
90+
}
91+
92+
// Define the regex to parse the input string
93+
re := regexp.MustCompile(`^(\d+)(MiB|GiB|TiB)$`)
94+
matches := re.FindStringSubmatch(storage)
95+
if matches == nil {
96+
return 0, errors.New("invalid storage format")
97+
}
98+
99+
// Extract the value and unit from the matches
100+
valueStr, unit := matches[1], matches[2]
101+
value, err := strconv.ParseInt(valueStr, 10, 64)
102+
if err != nil {
103+
return 0, err
104+
}
105+
106+
// Calculate the value in bytes
107+
bytes := value * multipliers[unit]
108+
109+
// Check if the value exceeds 1024 TB
110+
maxBytes := 1024 * 1024 * 1024 * 1024 * 1024
111+
if bytes > int64(maxBytes) {
112+
return 0, errors.New("value exceeds 1024 TB")
113+
}
114+
115+
return bytes, nil
116+
}

pkg/api/quota_handler.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package api
22

33
import (
44
"github.com/goharbor/go-client/pkg/sdk/v2.0/client/quota"
5+
"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
56
"github.com/goharbor/harbor-cli/pkg/utils"
67
)
78

@@ -27,16 +28,33 @@ func ListQuota(opts ListQuotaFlags) (*quota.ListQuotasOK, error) {
2728
return response, nil
2829
}
2930

30-
func GetQuota(QuotaID int64) (*quota.GetQuotaOK, error) {
31+
func GetQuota(quotaID int64) (*quota.GetQuotaOK, error) {
3132
ctx, client, err := utils.ContextWithClient()
3233
if err != nil {
3334
return nil, err
3435
}
3536

36-
response, err := client.Quota.GetQuota(ctx, &quota.GetQuotaParams{ID: QuotaID})
37+
response, err := client.Quota.GetQuota(ctx, &quota.GetQuotaParams{ID: quotaID})
3738
if err != nil {
3839
return nil, err
3940
}
4041

4142
return response, nil
4243
}
44+
45+
func UpdateQuota(quotaID int64, hardlimit *models.QuotaUpdateReq) error {
46+
ctx, client, err := utils.ContextWithClient()
47+
if err != nil {
48+
return err
49+
}
50+
51+
_, err = client.Quota.UpdateQuota(
52+
ctx,
53+
&quota.UpdateQuotaParams{ID: quotaID, Hard: hardlimit},
54+
)
55+
if err != nil {
56+
return err
57+
}
58+
59+
return nil
60+
}

pkg/views/quota/update/view.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package update
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/charmbracelet/huh"
9+
log "github.com/sirupsen/logrus"
10+
)
11+
12+
type CreateView struct {
13+
StorageUnit string
14+
Value int64
15+
}
16+
17+
func UpdateQuotaView() string {
18+
var (
19+
value string
20+
createView CreateView
21+
)
22+
23+
storageUnits := []string{"MiB", "GiB", "TiB"}
24+
25+
// Initialize a slice to hold select options
26+
var storageUnitSelectOptions []huh.Option[string]
27+
28+
// Iterate over registryOptions to populate registrySelectOptions
29+
for _, option := range storageUnits {
30+
storageUnitSelectOptions = append(
31+
storageUnitSelectOptions,
32+
huh.NewOption(option, option),
33+
)
34+
}
35+
36+
theme := huh.ThemeCharm()
37+
err := huh.NewForm(
38+
huh.NewGroup(
39+
huh.NewSelect[string]().
40+
Title("Select a Storage Unit").
41+
Value(&createView.StorageUnit).
42+
Options(storageUnitSelectOptions...).
43+
Validate(func(str string) error {
44+
if str == "" {
45+
return errors.New("Storage Type cannot be empty.")
46+
}
47+
return nil
48+
}),
49+
50+
huh.NewInput().
51+
Title("Quota Limit").
52+
Value(&value).
53+
Validate(func(str string) error {
54+
if str == "" {
55+
return errors.New("Quota Limits cannot be empty")
56+
}
57+
_, err := strconv.ParseInt(str, 10, 64)
58+
if err != nil {
59+
return errors.New("Quota limit must be a valid integer")
60+
}
61+
createView.Value, _ = strconv.ParseInt(value, 10, 64)
62+
return nil
63+
}),
64+
),
65+
).WithTheme(theme).Run()
66+
if err != nil {
67+
log.Fatal(err)
68+
}
69+
70+
return fmt.Sprintf("%v%v", createView.Value, createView.StorageUnit)
71+
}

0 commit comments

Comments
 (0)