feat: add globalresourcequota api (#2068)

* feat: add globalresourcequota api

Signed-off-by: Oliver Baehler <oliver@sudo-i.net>
This commit is contained in:
Oliver Bähler
2026-08-10 21:25:10 +02:00
committed by GitHub
parent d92453427c
commit bdcdcefe63
60 changed files with 6804 additions and 107 deletions
+43
View File
@@ -21,6 +21,8 @@ func ValidateRuleStatusBody(
mapper k8smeta.RESTMapper,
bodies []*rules.NamespaceRuleBodyNamespace,
) error {
quotaNames := make(map[string]string)
for i, rule := range bodies {
if rule == nil {
continue
@@ -30,6 +32,10 @@ func ValidateRuleStatusBody(
return err
}
if err := validateQuotaRules(i, rule.Quota, quotaNames); err != nil {
return err
}
if rule.Enforce == nil {
continue
}
@@ -54,6 +60,43 @@ func ValidateRuleStatusBody(
return nil
}
func validateQuotaRules(ruleIndex int, quotas []rules.ResourceQuotaRule, names map[string]string) error {
for quotaIndex, quota := range quotas {
path := fmt.Sprintf("rules[%d].quota[%d]", ruleIndex, quotaIndex)
if errs := k8svalidation.IsDNS1123Label(quota.Name); len(errs) > 0 {
return fmt.Errorf("%s.name %q is invalid: %s", path, quota.Name, strings.Join(errs, "; "))
}
if previous, found := names[quota.Name]; found {
return fmt.Errorf(
"%s.name %q is invalid: quota name is already used by %s",
path,
quota.Name,
previous,
)
}
names[quota.Name] = path
if len(quota.Hard) == 0 {
return fmt.Errorf("%s.hard is invalid: at least one resource is required", path)
}
for name, quantity := range quota.Hard {
if quantity.Sign() < 0 {
return fmt.Errorf(
"rules[%d].quota[%d].hard[%q] is invalid: quantity must not be negative",
ruleIndex,
quotaIndex,
name,
)
}
}
}
return nil
}
func validateIngressRules(
ruleIndex int,
ingress rules.NamespaceRuleEnforceIngressBody,
+69
View File
@@ -7,7 +7,9 @@ import (
"strings"
"testing"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/utils/ptr"
@@ -37,6 +39,73 @@ func TestValidateRuleStatusBody(t *testing.T) {
},
},
},
{
name: "valid quota-only rule",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{{
Quota: []rules.ResourceQuotaRule{{
Name: "shared-compute",
ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{
corev1.ResourceRequestsCPU: resource.MustParse("8"),
}},
}},
}},
},
{
name: "quota name is required",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{{
Quota: []rules.ResourceQuotaRule{{
ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{
corev1.ResourceRequestsCPU: resource.MustParse("8"),
}},
}},
}},
wantErr: "rules[0].quota[0].name",
},
{
name: "quota name must be a DNS label",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{{
Quota: []rules.ResourceQuotaRule{{
Name: "Shared_Compute",
ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{
corev1.ResourceRequestsCPU: resource.MustParse("8"),
}},
}},
}},
wantErr: `rules[0].quota[0].name "Shared_Compute" is invalid`,
},
{
name: "quota hard must not be empty",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{{
Quota: []rules.ResourceQuotaRule{{Name: "shared-compute"}},
}},
wantErr: "rules[0].quota[0].hard is invalid",
},
{
name: "quota hard must not be negative",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{{
Quota: []rules.ResourceQuotaRule{{
Name: "shared-compute",
ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{
corev1.ResourceRequestsCPU: resource.MustParse("-1"),
}},
}},
}},
wantErr: `rules[0].quota[0].hard["requests.cpu"] is invalid`,
},
{
name: "quota names must be unique across rules",
mapper: mapper,
bodies: []*rules.NamespaceRuleBodyNamespace{
{Quota: []rules.ResourceQuotaRule{{Name: "shared-compute", ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("1")}}}}},
{Quota: []rules.ResourceQuotaRule{{Name: "shared-compute", ResourceQuotaSpec: corev1.ResourceQuotaSpec{Hard: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}}}}},
},
wantErr: `rules[1].quota[0].name "shared-compute" is invalid: quota name is already used by rules[0].quota[0]`,
},
{
name: "valid workload service and metadata rules",
mapper: mapper,