mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-22 05:57:02 +00:00
* chore: save progress Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> * feat: requests and limit policies Signed-off-by: Oliver Baehler <oliver@sudo-i.net> --------- Signed-off-by: Oliver Baehler <oliver@sudo-i.net>
146 lines
4.7 KiB
Go
146 lines
4.7 KiB
Go
// Copyright 2020-2026 Project Capsule Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package ruleengine
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
|
|
"github.com/projectcapsule/capsule/pkg/api/rules"
|
|
)
|
|
|
|
func TestValidateRuleStatusBodyWorkloadResources(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
body *rules.NamespaceRuleBodyNamespace
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "valid",
|
|
body: workloadResourceRuleForValidation(
|
|
[]rules.WorkloadValidationTarget{rules.ValidateContainers},
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyDefault, Value: validationQuantity("1Gi")},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("1.5")},
|
|
),
|
|
},
|
|
{
|
|
name: "omitted target permits container-only resource names",
|
|
body: workloadResourceRuleForValidationWithName(
|
|
nil,
|
|
corev1.ResourceEphemeralStorage,
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyPreserve},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("1.5")},
|
|
),
|
|
},
|
|
{
|
|
name: "ratio below one",
|
|
body: workloadResourceRuleForValidation(
|
|
nil,
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyPreserve},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("0.5")},
|
|
),
|
|
wantErr: "Ratio must be greater than or equal to 1",
|
|
},
|
|
{
|
|
name: "ratio missing value",
|
|
body: workloadResourceRuleForValidation(
|
|
nil,
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyPreserve},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio},
|
|
),
|
|
wantErr: "Ratio requires a value",
|
|
},
|
|
{
|
|
name: "unsupported target",
|
|
body: workloadResourceRuleForValidation(
|
|
[]rules.WorkloadValidationTarget{rules.ValidateEphemeralContainers},
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyPreserve},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("1.5")},
|
|
),
|
|
wantErr: "does not support resource policies",
|
|
},
|
|
{
|
|
name: "pod-level ephemeral storage",
|
|
body: workloadResourceRuleForValidation(
|
|
[]rules.WorkloadValidationTarget{rules.ValidatePod},
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyPreserve},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("1.5")},
|
|
),
|
|
wantErr: "is not supported by pod-level resources",
|
|
},
|
|
{
|
|
name: "ratio request removed",
|
|
body: workloadResourceRuleForValidation(
|
|
nil,
|
|
rules.WorkloadResourceRequestPolicy{Policy: rules.WorkloadResourceRequestPolicyRemove},
|
|
rules.WorkloadResourceLimitPolicy{Policy: rules.WorkloadResourceLimitPolicyRatio, Value: validationQuantity("1.5")},
|
|
),
|
|
wantErr: "requires a request which is removed",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := ValidateRuleStatusBody(nil, []*rules.NamespaceRuleBodyNamespace{tt.body})
|
|
if tt.wantErr == "" {
|
|
if err != nil {
|
|
t.Fatalf("ValidateRuleStatusBody() error = %v", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
|
t.Fatalf("ValidateRuleStatusBody() error = %v, want containing %q", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func workloadResourceRuleForValidation(
|
|
targets []rules.WorkloadValidationTarget,
|
|
requestPolicy rules.WorkloadResourceRequestPolicy,
|
|
limitPolicy rules.WorkloadResourceLimitPolicy,
|
|
) *rules.NamespaceRuleBodyNamespace {
|
|
name := corev1.ResourceMemory
|
|
if len(targets) == 1 && targets[0] == rules.ValidatePod {
|
|
name = corev1.ResourceEphemeralStorage
|
|
}
|
|
|
|
return workloadResourceRuleForValidationWithName(targets, name, requestPolicy, limitPolicy)
|
|
}
|
|
|
|
func workloadResourceRuleForValidationWithName(
|
|
targets []rules.WorkloadValidationTarget,
|
|
name corev1.ResourceName,
|
|
requestPolicy rules.WorkloadResourceRequestPolicy,
|
|
limitPolicy rules.WorkloadResourceLimitPolicy,
|
|
) *rules.NamespaceRuleBodyNamespace {
|
|
|
|
return &rules.NamespaceRuleBodyNamespace{
|
|
Enforce: &rules.NamespaceRuleEnforceBody{
|
|
Workloads: rules.NamespaceRuleEnforceWorkloadsBody{
|
|
Targets: targets,
|
|
Resources: &rules.WorkloadResourceRules{
|
|
Requests: map[corev1.ResourceName]rules.WorkloadResourceRequestPolicy{name: requestPolicy},
|
|
Limits: map[corev1.ResourceName]rules.WorkloadResourceLimitPolicy{name: limitPolicy},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func validationQuantity(value string) *resource.Quantity {
|
|
quantity := resource.MustParse(value)
|
|
|
|
return &quantity
|
|
}
|