API Resource Quota return all storage classes if no quota is set for a namespace (#560)
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
@@ -29,6 +30,8 @@ import (
|
||||
// that are used within this project.
|
||||
type K8sClientI interface {
|
||||
getResourceQuota(ctx context.Context, namespace, resource string, opts metav1.GetOptions) (*v1.ResourceQuota, error)
|
||||
getNamespace(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Namespace, error)
|
||||
getStorageClasses(ctx context.Context, opts metav1.ListOptions) (*storagev1.StorageClassList, error)
|
||||
getSecret(ctx context.Context, namespace, secretName string, opts metav1.GetOptions) (*v1.Secret, error)
|
||||
getService(ctx context.Context, namespace, serviceName string, opts metav1.GetOptions) (*v1.Service, error)
|
||||
deletePodCollection(ctx context.Context, namespace string, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
|
||||
@@ -66,3 +69,11 @@ func (c *k8sClient) deleteSecret(ctx context.Context, namespace string, name str
|
||||
func (c *k8sClient) createSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error) {
|
||||
return c.client.CoreV1().Secrets(namespace).Create(ctx, secret, opts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) getNamespace(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Namespace, error) {
|
||||
return c.client.CoreV1().Namespaces().Get(ctx, name, opts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) getStorageClasses(ctx context.Context, opts metav1.ListOptions) (*storagev1.StorageClassList, error) {
|
||||
return c.client.StorageV1().StorageClasses().List(ctx, opts)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ package restapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
"github.com/minio/console/cluster"
|
||||
|
||||
@@ -43,6 +46,30 @@ func registerResourceQuotaHandlers(api *operations.ConsoleAPI) {
|
||||
func getResourceQuota(ctx context.Context, client K8sClientI, namespace, resourcequota string) (*models.ResourceQuota, error) {
|
||||
resourceQuota, err := client.getResourceQuota(ctx, namespace, resourcequota, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
// if there's no resource quotas
|
||||
if errors.IsNotFound(err) {
|
||||
// validate if at least the namespace is valid, if it is, return all storage classes with max capacity
|
||||
_, err := client.getNamespace(ctx, namespace, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storageClasses, err := client.getStorageClasses(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rq := models.ResourceQuota{Name: resourceQuota.Name}
|
||||
for _, sc := range storageClasses.Items {
|
||||
// Create Resource element with hard limit maxed out
|
||||
name := fmt.Sprintf("%s.storageclass.storage.k8s.io/requests.storage", sc.Name)
|
||||
element := models.ResourceQuotaElement{
|
||||
Name: name,
|
||||
Hard: 9223372036854775807,
|
||||
}
|
||||
rq.Elements = append(rq.Elements, &element)
|
||||
}
|
||||
return &rq, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
rq := models.ResourceQuota{Name: resourceQuota.Name}
|
||||
@@ -78,7 +105,6 @@ func getResourceQuotaResponse(session *models.Principal, params admin_api.GetRes
|
||||
resourceQuota, err := getResourceQuota(ctx, k8sClient, params.Namespace, params.ResourceQuotaName)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
|
||||
}
|
||||
return resourceQuota, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
@@ -16,12 +18,24 @@ import (
|
||||
type k8sClientMock struct{}
|
||||
|
||||
var k8sclientGetResourceQuotaMock func(ctx context.Context, namespace, resource string, opts metav1.GetOptions) (*v1.ResourceQuota, error)
|
||||
var k8sclientGetNameSpaceMock func(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Namespace, error)
|
||||
var k8sclientStorageClassesMock func(ctx context.Context, opts metav1.ListOptions) (*storagev1.StorageClassList, error)
|
||||
|
||||
// mock functions
|
||||
func (c k8sClientMock) getResourceQuota(ctx context.Context, namespace, resource string, opts metav1.GetOptions) (*v1.ResourceQuota, error) {
|
||||
return k8sclientGetResourceQuotaMock(ctx, namespace, resource, opts)
|
||||
}
|
||||
|
||||
// mock functions
|
||||
func (c k8sClientMock) getNamespace(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Namespace, error) {
|
||||
return k8sclientGetNameSpaceMock(ctx, name, opts)
|
||||
}
|
||||
|
||||
// mock functions
|
||||
func (c k8sClientMock) getStorageClasses(ctx context.Context, opts metav1.ListOptions) (*storagev1.StorageClassList, error) {
|
||||
return k8sclientStorageClassesMock(ctx, opts)
|
||||
}
|
||||
|
||||
func Test_ResourceQuota(t *testing.T) {
|
||||
mockHardResourceQuota := v1.ResourceList{
|
||||
"storage": resource.MustParse("1000"),
|
||||
|
||||
Reference in New Issue
Block a user