mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-02-22 07:03:28 +00:00
Merge pull request #134389 from thockin/takeover-130780
Add resourcequota WarningsOnCreate when request > limits
This commit is contained in:
@@ -18,6 +18,7 @@ package resourcequota
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
@@ -74,9 +75,36 @@ func (resourcequotaStrategy) Validate(ctx context.Context, obj runtime.Object) f
|
||||
return validation.ValidateResourceQuota(resourcequota)
|
||||
}
|
||||
|
||||
// all known resource names that we want to check for request <= limit
|
||||
var knownResourceNames = []api.ResourceName{
|
||||
api.ResourceCPU,
|
||||
api.ResourceMemory,
|
||||
api.ResourceStorage,
|
||||
api.ResourceEphemeralStorage,
|
||||
}
|
||||
|
||||
// WarningsOnCreate returns warnings for the creation of the given object.
|
||||
func (resourcequotaStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
|
||||
return nil
|
||||
resourcequota := obj.(*api.ResourceQuota)
|
||||
var allWarnings []string
|
||||
for _, resourceName := range knownResourceNames {
|
||||
requestResourceName := api.ResourceName(fmt.Sprintf("requests.%s", resourceName))
|
||||
request, requestOK := resourcequota.Spec.Hard[requestResourceName]
|
||||
if !requestOK && (resourceName == api.ResourceCPU || resourceName == api.ResourceMemory) {
|
||||
// try the bare name for cpu and memory
|
||||
request, requestOK = resourcequota.Spec.Hard[resourceName]
|
||||
if requestOK {
|
||||
requestResourceName = resourceName
|
||||
}
|
||||
}
|
||||
limitResourceName := api.ResourceName(fmt.Sprintf("limits.%s", resourceName))
|
||||
limit, limitOK := resourcequota.Spec.Hard[limitResourceName]
|
||||
if requestOK && limitOK && request.Cmp(limit) > 0 {
|
||||
allWarnings = append(allWarnings, fmt.Sprintf("ResourceQuota %s (%s) should be less than %s (%s)",
|
||||
requestResourceName, request.String(), limitResourceName, limit.String()))
|
||||
}
|
||||
}
|
||||
return allWarnings
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
|
||||
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package resourcequota
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
@@ -58,3 +60,84 @@ func TestResourceQuotaStrategy(t *testing.T) {
|
||||
t.Errorf("ResourceQuota does not allow setting status on create")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_WarningsOnCreate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args *api.ResourceQuota
|
||||
wantWarnings []string
|
||||
}{
|
||||
{
|
||||
name: "Empty Hard Spec",
|
||||
args: &api.ResourceQuota{},
|
||||
wantWarnings: []string{},
|
||||
},
|
||||
{
|
||||
name: "Request less than limit",
|
||||
args: &api.ResourceQuota{
|
||||
Spec: api.ResourceQuotaSpec{
|
||||
Hard: api.ResourceList{
|
||||
api.ResourceName("requests.cpu"): resource.MustParse("500m"),
|
||||
api.ResourceName("limits.cpu"): resource.MustParse("1"),
|
||||
api.ResourceName("requests.memory"): resource.MustParse("1Gi"),
|
||||
api.ResourceName("limits.memory"): resource.MustParse("2Gi"),
|
||||
api.ResourceName("requests.storage"): resource.MustParse("1Gi"),
|
||||
api.ResourceName("limits.storage"): resource.MustParse("2Gi"),
|
||||
api.ResourceName("requests.ephemeral-storage"): resource.MustParse("1Gi"),
|
||||
api.ResourceName("limits.ephemeral-storage"): resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantWarnings: []string{},
|
||||
},
|
||||
{
|
||||
name: "Request greater than limit",
|
||||
args: &api.ResourceQuota{
|
||||
Spec: api.ResourceQuotaSpec{
|
||||
Hard: api.ResourceList{
|
||||
api.ResourceName("requests.cpu"): resource.MustParse("2"),
|
||||
api.ResourceName("limits.cpu"): resource.MustParse("1"),
|
||||
api.ResourceName("requests.memory"): resource.MustParse("3Gi"),
|
||||
api.ResourceName("limits.memory"): resource.MustParse("2Gi"),
|
||||
api.ResourceName("requests.storage"): resource.MustParse("3Gi"),
|
||||
api.ResourceName("limits.storage"): resource.MustParse("2Gi"),
|
||||
api.ResourceName("requests.ephemeral-storage"): resource.MustParse("3Gi"),
|
||||
api.ResourceName("limits.ephemeral-storage"): resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantWarnings: []string{
|
||||
"ResourceQuota requests.cpu (2) should be less than limits.cpu (1)",
|
||||
"ResourceQuota requests.memory (3Gi) should be less than limits.memory (2Gi)",
|
||||
"ResourceQuota requests.storage (3Gi) should be less than limits.storage (2Gi)",
|
||||
"ResourceQuota requests.ephemeral-storage (3Gi) should be less than limits.ephemeral-storage (2Gi)",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Request greater than limit, bare names",
|
||||
args: &api.ResourceQuota{
|
||||
Spec: api.ResourceQuotaSpec{
|
||||
Hard: api.ResourceList{
|
||||
api.ResourceName("cpu"): resource.MustParse("2"),
|
||||
api.ResourceName("limits.cpu"): resource.MustParse("1"),
|
||||
api.ResourceName("memory"): resource.MustParse("3Gi"),
|
||||
api.ResourceName("limits.memory"): resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantWarnings: []string{
|
||||
"ResourceQuota cpu (2) should be less than limits.cpu (1)",
|
||||
"ResourceQuota memory (3Gi) should be less than limits.memory (2Gi)",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
warnings := Strategy.WarningsOnCreate(context.Background(), tt.args)
|
||||
if len(warnings)+len(tt.wantWarnings) > 0 && !reflect.DeepEqual(warnings, tt.wantWarnings) {
|
||||
t.Errorf("WarningsOnCreate()\n got: %q\n want: %q", warnings, tt.wantWarnings)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user