Skip to content

Commit be21559

Browse files
authored
Add: Quota Command to Manage Quotas (#97)
* add: quota `list` command Signed-off-by: bupd <bupdprasanth@gmail.com> * add: quota `view` command Signed-off-by: bupd <bupdprasanth@gmail.com> * add: quota `update` command Signed-off-by: bupd <bupdprasanth@gmail.com> * add: unit test for quota update Signed-off-by: bupd <bupdprasanth@gmail.com> * fix lint Signed-off-by: bupd <bupdprasanth@gmail.com> * fix quota list cmd Signed-off-by: bupd <bupdprasanth@gmail.com> * fix quota view cmd Signed-off-by: bupd <bupdprasanth@gmail.com> * update quota view Signed-off-by: bupd <bupdprasanth@gmail.com> * fix quota cmd Signed-off-by: bupd <bupdprasanth@gmail.com> * add docs Signed-off-by: bupd <bupdprasanth@gmail.com> * fix lint issues Signed-off-by: bupd <bupdprasanth@gmail.com> --------- Signed-off-by: bupd <bupdprasanth@gmail.com>
1 parent 99b1020 commit be21559

21 files changed

Lines changed: 1192 additions & 1 deletion

cmd/harbor/root/cmd.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/goharbor/harbor-cli/cmd/harbor/root/instance"
2525
"github.com/goharbor/harbor-cli/cmd/harbor/root/labels"
2626
"github.com/goharbor/harbor-cli/cmd/harbor/root/project"
27+
"github.com/goharbor/harbor-cli/cmd/harbor/root/quota"
2728
"github.com/goharbor/harbor-cli/cmd/harbor/root/registry"
2829
"github.com/goharbor/harbor-cli/cmd/harbor/root/repository"
2930
"github.com/goharbor/harbor-cli/cmd/harbor/root/schedule"
@@ -95,19 +96,20 @@ harbor help
9596
versionCommand(),
9697
LoginCommand(),
9798
config.Config(),
99+
HealthCommand(),
98100
project.Project(),
99101
registry.Registry(),
100102
repository.Repository(),
101103
user.User(),
102104
artifact.Artifact(),
103105
tag.TagCommand(),
104-
HealthCommand(),
105106
cve.CVEAllowlist(),
106107
schedule.Schedule(),
107108
labels.Labels(),
108109
InfoCommand(),
109110
webhook.Webhook(),
110111
instance.Instance(),
112+
quota.Quota(),
111113
)
112114

113115
return root

cmd/harbor/root/quota/cmd.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright Project Harbor Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package quota
15+
16+
import (
17+
"github.com/spf13/cobra"
18+
)
19+
20+
func Quota() *cobra.Command {
21+
cmd := &cobra.Command{
22+
Use: "quota",
23+
Short: "Manage quotas",
24+
Long: `Manage quotas of projects`,
25+
Example: ` harbor quota list`,
26+
}
27+
cmd.AddCommand(
28+
ListQuotaCommand(),
29+
ViewQuotaCommand(),
30+
UpdateQuotaCommand(),
31+
)
32+
33+
return cmd
34+
}

cmd/harbor/root/quota/list.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright Project Harbor Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package quota
15+
16+
import (
17+
"github.com/goharbor/harbor-cli/pkg/api"
18+
"github.com/goharbor/harbor-cli/pkg/utils"
19+
"github.com/goharbor/harbor-cli/pkg/views/quota/list"
20+
log "github.com/sirupsen/logrus"
21+
"github.com/spf13/cobra"
22+
"github.com/spf13/viper"
23+
)
24+
25+
// Lists the Quotas specified for each project
26+
func ListQuotaCommand() *cobra.Command {
27+
var opts api.ListQuotaFlags
28+
29+
cmd := &cobra.Command{
30+
Use: "list",
31+
Short: "list quotas",
32+
Long: "list quotas specified for each project",
33+
Run: func(cmd *cobra.Command, args []string) {
34+
if opts.PageSize > 100 {
35+
log.Errorf("page size should be less than or equal to 100")
36+
return
37+
}
38+
39+
quota, err := api.ListQuota(opts)
40+
if err != nil {
41+
log.Errorf("failed to get quota list: %v", err)
42+
return
43+
}
44+
45+
FormatFlag := viper.GetString("output-format")
46+
if FormatFlag != "" {
47+
err = utils.PrintFormat(quota, FormatFlag)
48+
if err != nil {
49+
log.Errorf("failed to get quota list: %v", err)
50+
return
51+
}
52+
} else {
53+
list.ListQuotas(quota.Payload)
54+
}
55+
},
56+
}
57+
58+
flags := cmd.Flags()
59+
flags.Int64VarP(&opts.Page, "page", "", 1, "Page number")
60+
flags.Int64VarP(&opts.PageSize, "page-size", "", 0, "Size of per page (use 0 to fetch all)")
61+
flags.StringVarP(&opts.Reference, "ref", "", "", "Reference type of quota")
62+
flags.StringVarP(&opts.ReferenceID, "refid", "", "", "Reference ID of quota")
63+
flags.StringVarP(
64+
&opts.Sort,
65+
"sort",
66+
"",
67+
"",
68+
"Sort the resource list in ascending or descending order",
69+
)
70+
71+
return cmd
72+
}

cmd/harbor/root/quota/update.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright Project Harbor Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package quota
15+
16+
import (
17+
"fmt"
18+
"os"
19+
"strconv"
20+
21+
"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
22+
"github.com/goharbor/harbor-cli/pkg/api"
23+
"github.com/goharbor/harbor-cli/pkg/prompt"
24+
"github.com/goharbor/harbor-cli/pkg/utils"
25+
"github.com/goharbor/harbor-cli/pkg/views/quota/update"
26+
log "github.com/sirupsen/logrus"
27+
"github.com/spf13/cobra"
28+
)
29+
30+
type QuotaUpdateReq struct {
31+
// The new hard limits for the quota
32+
Hard ResourceList `json:"hard,omitempty"`
33+
}
34+
35+
type ResourceList map[string]int64
36+
37+
// UpdateQuotaCommand updates the quota
38+
func UpdateQuotaCommand() *cobra.Command {
39+
var (
40+
storage string
41+
)
42+
43+
var opts api.ListQuotaFlags
44+
cmd := &cobra.Command{
45+
Use: "update [QuotaID]",
46+
Short: "update quotas for projects",
47+
Args: cobra.MaximumNArgs(1),
48+
Run: func(cmd *cobra.Command, args []string) {
49+
var err error
50+
var storageValue int64
51+
52+
// get quota id with quota
53+
quota, err := GetQuotaFromUser(args, opts)
54+
if err != nil {
55+
log.Errorf("error: %v", err)
56+
return
57+
}
58+
59+
if storage != "" {
60+
if storage == "-1" {
61+
storageValue = -1
62+
} else {
63+
storageValue, err = utils.StorageStringToBytes(storage)
64+
if err != nil {
65+
log.Errorf("failed to parse storage: %v", err)
66+
os.Exit(1)
67+
}
68+
}
69+
} else {
70+
storage = update.UpdateQuotaView(quota)
71+
storageValue, err = utils.StorageStringToBytes(storage)
72+
if err != nil {
73+
log.Errorf("failed to parse storage: %v", err)
74+
os.Exit(1)
75+
}
76+
}
77+
78+
hardlimit := &models.QuotaUpdateReq{
79+
Hard: models.ResourceList{"storage": storageValue},
80+
}
81+
82+
err = api.UpdateQuota(quota.ID, hardlimit)
83+
if err != nil {
84+
log.Errorf("failed to update quota: %v", err)
85+
os.Exit(1)
86+
}
87+
88+
log.Infof("quota updated successfully!")
89+
},
90+
}
91+
92+
flags := cmd.Flags()
93+
flags.StringVarP(&storage, "storage", "", "", "Enter storage size (e.g., 50GiB, 20MiB, 4TiB)")
94+
flags.StringVarP(&opts.Reference, "project-name", "", "", "Get quota by project-name")
95+
flags.StringVarP(&opts.ReferenceID, "project-id", "", "", "Get quota by project ID")
96+
97+
return cmd
98+
}
99+
100+
func GetQuotaFromUser(args []string, opts api.ListQuotaFlags) (*models.Quota, error) {
101+
var err error
102+
var quota *models.Quota
103+
104+
if len(args) > 0 {
105+
quotaID, err := strconv.ParseInt(args[0], 10, 64)
106+
if err != nil {
107+
err := fmt.Errorf("failed to parse quotaID: %v", err)
108+
return nil, err
109+
}
110+
quota, err = api.GetQuota(int64(quotaID))
111+
if err != nil {
112+
err := fmt.Errorf("failed to get Quota: %v", err)
113+
return nil, err
114+
}
115+
} else if opts.Reference != "" {
116+
project, err := api.GetProject(opts.Reference, false)
117+
if err != nil {
118+
err := fmt.Errorf("failed to get project: %v", err)
119+
return nil, err
120+
}
121+
projectID := project.Payload.ProjectID
122+
quota, err = api.GetQuotaByRef(int64(projectID))
123+
if err != nil {
124+
err := fmt.Errorf("failed to get quota: %v", err)
125+
return nil, err
126+
}
127+
} else if opts.ReferenceID != "" {
128+
projectID, err := strconv.ParseInt(opts.ReferenceID, 10, 64)
129+
if err != nil {
130+
err := fmt.Errorf("invalid projectID: %v", err)
131+
return nil, err
132+
}
133+
quota, err = api.GetQuotaByRef(projectID)
134+
if err != nil {
135+
err := fmt.Errorf("failed to get quota: %v", err)
136+
return nil, err
137+
}
138+
} else {
139+
quotaID := prompt.GetQuotaIDFromUser()
140+
if quotaID == 0 {
141+
err := fmt.Errorf("failed to get quotaID from user")
142+
return nil, err
143+
}
144+
quota, err = api.GetQuota(quotaID)
145+
if err != nil {
146+
err := fmt.Errorf("failed to get quota: %v", err)
147+
return nil, err
148+
}
149+
}
150+
151+
return quota, nil
152+
}

cmd/harbor/root/quota/view.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright Project Harbor Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package quota
15+
16+
import (
17+
"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
18+
"github.com/goharbor/harbor-cli/pkg/api"
19+
"github.com/goharbor/harbor-cli/pkg/utils"
20+
"github.com/goharbor/harbor-cli/pkg/views/quota/list"
21+
log "github.com/sirupsen/logrus"
22+
"github.com/spf13/cobra"
23+
"github.com/spf13/viper"
24+
)
25+
26+
// View a specified quota
27+
func ViewQuotaCommand() *cobra.Command {
28+
var opts api.ListQuotaFlags
29+
cmd := &cobra.Command{
30+
Use: "view [quotaID]",
31+
Short: "get quota by quota ID",
32+
Args: cobra.MaximumNArgs(1),
33+
Run: func(cmd *cobra.Command, args []string) {
34+
var err error
35+
var quota *models.Quota
36+
37+
// get quota id with quota
38+
quota, err = GetQuotaFromUser(args, opts)
39+
if err != nil {
40+
log.Errorf("error: %v", err)
41+
return
42+
}
43+
quotas := []*models.Quota{quota}
44+
FormatFlag := viper.GetString("output-format")
45+
if FormatFlag != "" {
46+
err = utils.PrintFormat(quota, FormatFlag)
47+
if err != nil {
48+
log.Errorf("failed to get quota list: %v", err)
49+
return
50+
}
51+
} else {
52+
list.ListQuotas(quotas)
53+
}
54+
},
55+
}
56+
flags := cmd.Flags()
57+
flags.StringVarP(&opts.Reference, "project-name", "", "", "Get quota by project-name")
58+
flags.StringVarP(&opts.ReferenceID, "project-id", "", "", "Get quota by project ID")
59+
60+
return cmd
61+
}

doc/cli-docs/harbor-quota-list.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: harbor quota list
3+
weight: 85
4+
---
5+
## harbor quota list
6+
7+
### Description
8+
9+
##### list quotas
10+
11+
### Synopsis
12+
13+
list quotas specified for each project
14+
15+
```sh
16+
harbor quota list [flags]
17+
```
18+
19+
### Options
20+
21+
```sh
22+
-h, --help help for list
23+
--page int Page number (default 1)
24+
--page-size int Size of per page (use 0 to fetch all)
25+
--ref string Reference type of quota
26+
--refid string Reference ID of quota
27+
--sort string Sort the resource list in ascending or descending order
28+
```
29+
30+
### Options inherited from parent commands
31+
32+
```sh
33+
-c, --config string config file (default is $HOME/.config/harbor-cli/config.yaml)
34+
-o, --output-format string Output format. One of: json|yaml
35+
-v, --verbose verbose output
36+
```
37+
38+
### SEE ALSO
39+
40+
* [harbor quota](harbor-quota.md) - Manage quotas
41+

0 commit comments

Comments
 (0)