open-nomad/api/quota.go
Michael Schurter 35d65c7c7e
Dynamic Node Metadata (#15844)
Fixes #14617
Dynamic Node Metadata allows Nomad users, and their jobs, to update Node metadata through an API. Currently Node metadata is only reloaded when a Client agent is restarted.

Includes new UI for editing metadata as well.

---------

Co-authored-by: Phil Renaud <phil.renaud@hashicorp.com>
2023-02-07 14:42:25 -08:00

192 lines
5 KiB
Go

package api
import (
"fmt"
"sort"
)
// Quotas is used to query the quotas endpoints.
type Quotas struct {
client *Client
}
// Quotas returns a new handle on the quotas.
func (c *Client) Quotas() *Quotas {
return &Quotas{client: c}
}
// List is used to dump all of the quota specs
func (q *Quotas) List(qo *QueryOptions) ([]*QuotaSpec, *QueryMeta, error) {
var resp []*QuotaSpec
qm, err := q.client.query("/v1/quotas", &resp, qo)
if err != nil {
return nil, nil, err
}
sort.Sort(QuotaSpecIndexSort(resp))
return resp, qm, nil
}
// PrefixList is used to do a PrefixList search over quota specs
func (q *Quotas) PrefixList(prefix string, qo *QueryOptions) ([]*QuotaSpec, *QueryMeta, error) {
if qo == nil {
qo = &QueryOptions{Prefix: prefix}
} else {
qo.Prefix = prefix
}
return q.List(qo)
}
// ListUsage is used to dump all of the quota usages
func (q *Quotas) ListUsage(qo *QueryOptions) ([]*QuotaUsage, *QueryMeta, error) {
var resp []*QuotaUsage
qm, err := q.client.query("/v1/quota-usages", &resp, qo)
if err != nil {
return nil, nil, err
}
sort.Sort(QuotaUsageIndexSort(resp))
return resp, qm, nil
}
// PrefixList is used to do a PrefixList search over quota usages
func (q *Quotas) PrefixListUsage(prefix string, qo *QueryOptions) ([]*QuotaUsage, *QueryMeta, error) {
if qo == nil {
qo = &QueryOptions{Prefix: prefix}
} else {
qo.Prefix = prefix
}
return q.ListUsage(qo)
}
// Info is used to query a single quota spec by its name.
func (q *Quotas) Info(name string, qo *QueryOptions) (*QuotaSpec, *QueryMeta, error) {
var resp QuotaSpec
qm, err := q.client.query("/v1/quota/"+name, &resp, qo)
if err != nil {
return nil, nil, err
}
return &resp, qm, nil
}
// Usage is used to query a single quota usage by its name.
func (q *Quotas) Usage(name string, qo *QueryOptions) (*QuotaUsage, *QueryMeta, error) {
var resp QuotaUsage
qm, err := q.client.query("/v1/quota/usage/"+name, &resp, qo)
if err != nil {
return nil, nil, err
}
return &resp, qm, nil
}
// Register is used to register a quota spec.
func (q *Quotas) Register(spec *QuotaSpec, qo *WriteOptions) (*WriteMeta, error) {
wm, err := q.client.put("/v1/quota", spec, nil, qo)
if err != nil {
return nil, err
}
return wm, nil
}
// Delete is used to delete a quota spec
func (q *Quotas) Delete(quota string, qo *WriteOptions) (*WriteMeta, error) {
wm, err := q.client.delete(fmt.Sprintf("/v1/quota/%s", quota), nil, nil, qo)
if err != nil {
return nil, err
}
return wm, nil
}
// QuotaSpec specifies the allowed resource usage across regions.
type QuotaSpec struct {
// Name is the name for the quota object
Name string
// Description is an optional description for the quota object
Description string
// Limits is the set of quota limits encapsulated by this quota object. Each
// limit applies quota in a particular region and in the future over a
// particular priority range and datacenter set.
Limits []*QuotaLimit
// Raft indexes to track creation and modification
CreateIndex uint64
ModifyIndex uint64
}
// QuotaLimit describes the resource limit in a particular region.
type QuotaLimit struct {
// Region is the region in which this limit has affect
Region string
// RegionLimit is the quota limit that applies to any allocation within a
// referencing namespace in the region. A value of zero is treated as
// unlimited and a negative value is treated as fully disallowed. This is
// useful for once we support GPUs
RegionLimit *Resources
// VariablesLimit is the maximum total size of all variables
// Variable.EncryptedData. A value of zero is treated as unlimited and a
// negative value is treated as fully disallowed.
VariablesLimit *int `mapstructure:"variables_limit" hcl:"variables_limit,optional"`
// Hash is the hash of the object and is used to make replication efficient.
Hash []byte
}
// QuotaUsage is the resource usage of a Quota
type QuotaUsage struct {
Name string
Used map[string]*QuotaLimit
CreateIndex uint64
ModifyIndex uint64
}
// QuotaSpecIndexSort is a wrapper to sort QuotaSpecs by CreateIndex. We
// reverse the test so that we get the highest index first.
type QuotaSpecIndexSort []*QuotaSpec
func (q QuotaSpecIndexSort) Len() int {
return len(q)
}
func (q QuotaSpecIndexSort) Less(i, j int) bool {
return q[i].CreateIndex > q[j].CreateIndex
}
func (q QuotaSpecIndexSort) Swap(i, j int) {
q[i], q[j] = q[j], q[i]
}
// QuotaUsageIndexSort is a wrapper to sort QuotaUsages by CreateIndex. We
// reverse the test so that we get the highest index first.
type QuotaUsageIndexSort []*QuotaUsage
func (q QuotaUsageIndexSort) Len() int {
return len(q)
}
func (q QuotaUsageIndexSort) Less(i, j int) bool {
return q[i].CreateIndex > q[j].CreateIndex
}
func (q QuotaUsageIndexSort) Swap(i, j int) {
q[i], q[j] = q[j], q[i]
}
// QuotaLimitSort is a wrapper to sort QuotaLimits
type QuotaLimitSort []*QuotaLimit
func (q QuotaLimitSort) Len() int {
return len(q)
}
func (q QuotaLimitSort) Less(i, j int) bool {
return q[i].Region < q[j].Region
}
func (q QuotaLimitSort) Swap(i, j int) {
q[i], q[j] = q[j], q[i]
}