github.com/ubuntu-core/snappy@v0.0.0-20210827154228-9e584df982bb/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 ) 29 30 type postQuotaData struct { 31 Action string `json:"action"` 32 GroupName string `json:"group-name"` 33 Parent string `json:"parent,omitempty"` 34 Snaps []string `json:"snaps,omitempty"` 35 Constraints *QuotaValues `json:"constraints,omitempty"` 36 } 37 38 type QuotaGroupResult struct { 39 GroupName string `json:"group-name"` 40 Parent string `json:"parent,omitempty"` 41 Subgroups []string `json:"subgroups,omitempty"` 42 Snaps []string `json:"snaps,omitempty"` 43 Constraints *QuotaValues `json:"constraints,omitempty"` 44 Current *QuotaValues `json:"current,omitempty"` 45 } 46 47 type QuotaValues struct { 48 Memory quantity.Size `json:"memory,omitempty"` 49 } 50 51 // EnsureQuota creates a quota group or updates an existing group. 52 // The list of snaps can be empty. 53 func (client *Client) EnsureQuota(groupName string, parent string, snaps []string, maxMemory quantity.Size) (changeID string, err error) { 54 if groupName == "" { 55 return "", fmt.Errorf("cannot create or update quota group without a name") 56 } 57 // TODO: use naming.ValidateQuotaGroup() 58 59 data := &postQuotaData{ 60 Action: "ensure", 61 GroupName: groupName, 62 Parent: parent, 63 Snaps: snaps, 64 Constraints: &QuotaValues{ 65 Memory: maxMemory, 66 }, 67 } 68 69 var body bytes.Buffer 70 if err := json.NewEncoder(&body).Encode(data); err != nil { 71 return "", err 72 } 73 chgID, err := client.doAsync("POST", "/v2/quotas", nil, nil, &body) 74 75 if err != nil { 76 return "", err 77 } 78 return chgID, nil 79 } 80 81 func (client *Client) GetQuotaGroup(groupName string) (*QuotaGroupResult, error) { 82 if groupName == "" { 83 return nil, fmt.Errorf("cannot get quota group without a name") 84 } 85 86 var res *QuotaGroupResult 87 path := fmt.Sprintf("/v2/quotas/%s", groupName) 88 if _, err := client.doSync("GET", path, nil, nil, nil, &res); err != nil { 89 return nil, err 90 } 91 92 return res, nil 93 } 94 95 func (client *Client) RemoveQuotaGroup(groupName string) (changeID string, err error) { 96 if groupName == "" { 97 return "", fmt.Errorf("cannot remove quota group without a name") 98 } 99 data := &postQuotaData{ 100 Action: "remove", 101 GroupName: groupName, 102 } 103 104 var body bytes.Buffer 105 if err := json.NewEncoder(&body).Encode(data); err != nil { 106 return "", err 107 } 108 chgID, err := client.doAsync("POST", "/v2/quotas", nil, nil, &body) 109 if err != nil { 110 return "", fmt.Errorf("cannot remove quota group: %w", err) 111 } 112 113 return chgID, nil 114 } 115 116 func (client *Client) Quotas() ([]*QuotaGroupResult, error) { 117 var res []*QuotaGroupResult 118 if _, err := client.doSync("GET", "/v2/quotas", nil, nil, nil, &res); err != nil { 119 return nil, err 120 } 121 122 return res, nil 123 }