github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/client/quota.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2021 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package client 21 22 import ( 23 "bytes" 24 "encoding/json" 25 "fmt" 26 27 "github.com/snapcore/snapd/gadget/quantity" 28 "golang.org/x/xerrors" 29 ) 30 31 type postQuotaData struct { 32 Action string `json:"action"` 33 GroupName string `json:"group-name"` 34 Parent string `json:"parent,omitempty"` 35 Snaps []string `json:"snaps,omitempty"` 36 Constraints *QuotaValues `json:"constraints,omitempty"` 37 } 38 39 type QuotaGroupResult struct { 40 GroupName string `json:"group-name"` 41 Parent string `json:"parent,omitempty"` 42 Subgroups []string `json:"subgroups,omitempty"` 43 Snaps []string `json:"snaps,omitempty"` 44 Constraints *QuotaValues `json:"constraints,omitempty"` 45 Current *QuotaValues `json:"current,omitempty"` 46 } 47 48 type QuotaValues struct { 49 Memory quantity.Size `json:"memory,omitempty"` 50 } 51 52 // EnsureQuota creates a quota group or updates an existing group. 53 // The list of snaps can be empty. 54 func (client *Client) EnsureQuota(groupName string, parent string, snaps []string, maxMemory quantity.Size) (changeID string, err error) { 55 if groupName == "" { 56 return "", xerrors.Errorf("cannot create or update quota group without a name") 57 } 58 // TODO: use naming.ValidateQuotaGroup() 59 60 data := &postQuotaData{ 61 Action: "ensure", 62 GroupName: groupName, 63 Parent: parent, 64 Snaps: snaps, 65 Constraints: &QuotaValues{ 66 Memory: maxMemory, 67 }, 68 } 69 70 var body bytes.Buffer 71 if err := json.NewEncoder(&body).Encode(data); err != nil { 72 return "", err 73 } 74 chgID, err := client.doAsync("POST", "/v2/quotas", nil, nil, &body) 75 76 if err != nil { 77 return "", err 78 } 79 return chgID, nil 80 } 81 82 func (client *Client) GetQuotaGroup(groupName string) (*QuotaGroupResult, error) { 83 if groupName == "" { 84 return nil, xerrors.Errorf("cannot get quota group without a name") 85 } 86 87 var res *QuotaGroupResult 88 path := fmt.Sprintf("/v2/quotas/%s", groupName) 89 if _, err := client.doSync("GET", path, nil, nil, nil, &res); err != nil { 90 return nil, err 91 } 92 93 return res, nil 94 } 95 96 func (client *Client) RemoveQuotaGroup(groupName string) (changeID string, err error) { 97 if groupName == "" { 98 return "", xerrors.Errorf("cannot remove quota group without a name") 99 } 100 data := &postQuotaData{ 101 Action: "remove", 102 GroupName: groupName, 103 } 104 105 var body bytes.Buffer 106 if err := json.NewEncoder(&body).Encode(data); err != nil { 107 return "", err 108 } 109 chgID, err := client.doAsync("POST", "/v2/quotas", nil, nil, &body) 110 if err != nil { 111 fmt := "cannot remove quota group: %w" 112 return "", xerrors.Errorf(fmt, err) 113 } 114 115 return chgID, nil 116 } 117 118 func (client *Client) Quotas() ([]*QuotaGroupResult, error) { 119 var res []*QuotaGroupResult 120 if _, err := client.doSync("GET", "/v2/quotas", nil, nil, nil, &res); err != nil { 121 return nil, err 122 } 123 124 return res, nil 125 }