mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #22183 from pmorie/config-quota
Auto commit by PR queue bot
This commit is contained in:
commit
0e3469dce3
@ -237,6 +237,7 @@ func StartControllers(s *options.CMServer, kubeClient *client.Client, kubeconfig
|
|||||||
api.Kind("ReplicationController"),
|
api.Kind("ReplicationController"),
|
||||||
api.Kind("PersistentVolumeClaim"),
|
api.Kind("PersistentVolumeClaim"),
|
||||||
api.Kind("Secret"),
|
api.Kind("Secret"),
|
||||||
|
api.Kind("ConfigMap"),
|
||||||
}
|
}
|
||||||
resourceQuotaControllerOptions := &resourcequotacontroller.ResourceQuotaControllerOptions{
|
resourceQuotaControllerOptions := &resourcequotacontroller.ResourceQuotaControllerOptions{
|
||||||
KubeClient: resourceQuotaControllerClient,
|
KubeClient: resourceQuotaControllerClient,
|
||||||
|
@ -140,6 +140,7 @@ var standardQuotaResources = sets.NewString(
|
|||||||
string(ResourceReplicationControllers),
|
string(ResourceReplicationControllers),
|
||||||
string(ResourceSecrets),
|
string(ResourceSecrets),
|
||||||
string(ResourcePersistentVolumeClaims),
|
string(ResourcePersistentVolumeClaims),
|
||||||
|
string(ResourceConfigMaps),
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsStandardQuotaResourceName returns true if the resource is known to
|
// IsStandardQuotaResourceName returns true if the resource is known to
|
||||||
@ -160,6 +161,7 @@ var standardResources = sets.NewString(
|
|||||||
string(ResourceServices),
|
string(ResourceServices),
|
||||||
string(ResourceReplicationControllers),
|
string(ResourceReplicationControllers),
|
||||||
string(ResourceSecrets),
|
string(ResourceSecrets),
|
||||||
|
string(ResourceConfigMaps),
|
||||||
string(ResourcePersistentVolumeClaims),
|
string(ResourcePersistentVolumeClaims),
|
||||||
string(ResourceStorage),
|
string(ResourceStorage),
|
||||||
)
|
)
|
||||||
@ -175,6 +177,7 @@ var integerResources = sets.NewString(
|
|||||||
string(ResourceServices),
|
string(ResourceServices),
|
||||||
string(ResourceReplicationControllers),
|
string(ResourceReplicationControllers),
|
||||||
string(ResourceSecrets),
|
string(ResourceSecrets),
|
||||||
|
string(ResourceConfigMaps),
|
||||||
string(ResourcePersistentVolumeClaims),
|
string(ResourcePersistentVolumeClaims),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2187,6 +2187,8 @@ const (
|
|||||||
ResourceQuotas ResourceName = "resourcequotas"
|
ResourceQuotas ResourceName = "resourcequotas"
|
||||||
// ResourceSecrets, number
|
// ResourceSecrets, number
|
||||||
ResourceSecrets ResourceName = "secrets"
|
ResourceSecrets ResourceName = "secrets"
|
||||||
|
// ResourceConfigMaps, number
|
||||||
|
ResourceConfigMaps ResourceName = "configmaps"
|
||||||
// ResourcePersistentVolumeClaims, number
|
// ResourcePersistentVolumeClaims, number
|
||||||
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
||||||
// CPU request, in cores. (500m = .5 cores)
|
// CPU request, in cores. (500m = .5 cores)
|
||||||
|
@ -2644,6 +2644,8 @@ const (
|
|||||||
ResourceQuotas ResourceName = "resourcequotas"
|
ResourceQuotas ResourceName = "resourcequotas"
|
||||||
// ResourceSecrets, number
|
// ResourceSecrets, number
|
||||||
ResourceSecrets ResourceName = "secrets"
|
ResourceSecrets ResourceName = "secrets"
|
||||||
|
// ResourceConfigMaps, number
|
||||||
|
ResourceConfigMaps ResourceName = "configmaps"
|
||||||
// ResourcePersistentVolumeClaims, number
|
// ResourcePersistentVolumeClaims, number
|
||||||
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
|
||||||
// CPU request, in cores. (500m = .5 cores)
|
// CPU request, in cores. (500m = .5 cores)
|
||||||
|
@ -4082,6 +4082,8 @@ func TestValidateResourceQuota(t *testing.T) {
|
|||||||
api.ResourceServices: resource.MustParse("0"),
|
api.ResourceServices: resource.MustParse("0"),
|
||||||
api.ResourceReplicationControllers: resource.MustParse("10"),
|
api.ResourceReplicationControllers: resource.MustParse("10"),
|
||||||
api.ResourceQuotas: resource.MustParse("10"),
|
api.ResourceQuotas: resource.MustParse("10"),
|
||||||
|
api.ResourceConfigMaps: resource.MustParse("10"),
|
||||||
|
api.ResourceSecrets: resource.MustParse("10"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4129,6 +4131,8 @@ func TestValidateResourceQuota(t *testing.T) {
|
|||||||
api.ResourceServices: resource.MustParse("-10"),
|
api.ResourceServices: resource.MustParse("-10"),
|
||||||
api.ResourceReplicationControllers: resource.MustParse("-10"),
|
api.ResourceReplicationControllers: resource.MustParse("-10"),
|
||||||
api.ResourceQuotas: resource.MustParse("-10"),
|
api.ResourceQuotas: resource.MustParse("-10"),
|
||||||
|
api.ResourceConfigMaps: resource.MustParse("-10"),
|
||||||
|
api.ResourceSecrets: resource.MustParse("-10"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +187,22 @@ func (r *replenishmentControllerFactory) NewController(options *ReplenishmentCon
|
|||||||
DeleteFunc: ObjectReplenishmentDeleteFunc(options),
|
DeleteFunc: ObjectReplenishmentDeleteFunc(options),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
case api.Kind("ConfigMap"):
|
||||||
|
_, result = framework.NewInformer(
|
||||||
|
&cache.ListWatch{
|
||||||
|
ListFunc: func(options api.ListOptions) (runtime.Object, error) {
|
||||||
|
return r.kubeClient.Core().ConfigMaps(api.NamespaceAll).List(options)
|
||||||
|
},
|
||||||
|
WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
|
||||||
|
return r.kubeClient.Core().ConfigMaps(api.NamespaceAll).Watch(options)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&api.ConfigMap{},
|
||||||
|
options.ResyncPeriod(),
|
||||||
|
framework.ResourceEventHandlerFuncs{
|
||||||
|
DeleteFunc: ObjectReplenishmentDeleteFunc(options),
|
||||||
|
},
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("no replenishment controller available for %s", options.GroupKind)
|
return nil, fmt.Errorf("no replenishment controller available for %s", options.GroupKind)
|
||||||
}
|
}
|
||||||
|
45
pkg/quota/evaluator/core/configmap.go
Normal file
45
pkg/quota/evaluator/core/configmap.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
|
"k8s.io/kubernetes/pkg/quota"
|
||||||
|
"k8s.io/kubernetes/pkg/quota/generic"
|
||||||
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewConfigMapEvaluator returns an evaluator that can evaluate configMaps
|
||||||
|
func NewConfigMapEvaluator(kubeClient clientset.Interface) quota.Evaluator {
|
||||||
|
allResources := []api.ResourceName{api.ResourceConfigMaps}
|
||||||
|
return &generic.GenericEvaluator{
|
||||||
|
Name: "Evaluator.ConfigMap",
|
||||||
|
InternalGroupKind: api.Kind("ConfigMap"),
|
||||||
|
InternalOperationResources: map[admission.Operation][]api.ResourceName{
|
||||||
|
admission.Create: allResources,
|
||||||
|
},
|
||||||
|
MatchedResourceNames: allResources,
|
||||||
|
MatchesScopeFunc: generic.MatchesNoScopeFunc,
|
||||||
|
ConstraintsFunc: generic.ObjectCountConstraintsFunc(api.ResourceConfigMaps),
|
||||||
|
UsageFunc: generic.ObjectCountUsageFunc(api.ResourceConfigMaps),
|
||||||
|
ListFuncByNamespace: func(namespace string, options api.ListOptions) (runtime.Object, error) {
|
||||||
|
return kubeClient.Core().ConfigMaps(namespace).List(options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ func NewRegistry(kubeClient clientset.Interface) quota.Registry {
|
|||||||
replicationController := NewReplicationControllerEvaluator(kubeClient)
|
replicationController := NewReplicationControllerEvaluator(kubeClient)
|
||||||
resourceQuota := NewResourceQuotaEvaluator(kubeClient)
|
resourceQuota := NewResourceQuotaEvaluator(kubeClient)
|
||||||
secret := NewSecretEvaluator(kubeClient)
|
secret := NewSecretEvaluator(kubeClient)
|
||||||
|
configMap := NewConfigMapEvaluator(kubeClient)
|
||||||
persistentVolumeClaim := NewPersistentVolumeClaimEvaluator(kubeClient)
|
persistentVolumeClaim := NewPersistentVolumeClaimEvaluator(kubeClient)
|
||||||
return &generic.GenericRegistry{
|
return &generic.GenericRegistry{
|
||||||
InternalEvaluators: map[unversioned.GroupKind]quota.Evaluator{
|
InternalEvaluators: map[unversioned.GroupKind]quota.Evaluator{
|
||||||
@ -37,6 +38,7 @@ func NewRegistry(kubeClient clientset.Interface) quota.Registry {
|
|||||||
service.GroupKind(): service,
|
service.GroupKind(): service,
|
||||||
replicationController.GroupKind(): replicationController,
|
replicationController.GroupKind(): replicationController,
|
||||||
secret.GroupKind(): secret,
|
secret.GroupKind(): secret,
|
||||||
|
configMap.GroupKind(): configMap,
|
||||||
resourceQuota.GroupKind(): resourceQuota,
|
resourceQuota.GroupKind(): resourceQuota,
|
||||||
persistentVolumeClaim.GroupKind(): persistentVolumeClaim,
|
persistentVolumeClaim.GroupKind(): persistentVolumeClaim,
|
||||||
},
|
},
|
||||||
|
@ -182,6 +182,41 @@ var _ = Describe("ResourceQuota", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should create a ResourceQuota and capture the life of a configMap.", func() {
|
||||||
|
By("Creating a ResourceQuota")
|
||||||
|
quotaName := "test-quota"
|
||||||
|
resourceQuota := newTestResourceQuota(quotaName)
|
||||||
|
resourceQuota, err := createResourceQuota(f.Client, f.Namespace.Name, resourceQuota)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status is calculated")
|
||||||
|
usedResources := api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Creating a ConfigMap")
|
||||||
|
configMap := newTestConfigMapForQuota("test-configmap")
|
||||||
|
configMap, err = f.Client.ConfigMaps(f.Namespace.Name).Create(configMap)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status captures configMap creation")
|
||||||
|
usedResources = api.ResourceList{}
|
||||||
|
usedResources[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
|
usedResources[api.ResourceConfigMaps] = resource.MustParse("1")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Deleting a ConfigMap")
|
||||||
|
err = f.Client.ConfigMaps(f.Namespace.Name).Delete(configMap.Name)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Ensuring resource quota status released usage")
|
||||||
|
usedResources[api.ResourceConfigMaps] = resource.MustParse("0")
|
||||||
|
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
It("should verify ResourceQuota with terminating scopes.", func() {
|
It("should verify ResourceQuota with terminating scopes.", func() {
|
||||||
By("Creating a ResourceQuota with terminating scope")
|
By("Creating a ResourceQuota with terminating scope")
|
||||||
quotaTerminatingName := "quota-terminating"
|
quotaTerminatingName := "quota-terminating"
|
||||||
@ -387,6 +422,8 @@ func newTestResourceQuota(name string) *api.ResourceQuota {
|
|||||||
hard[api.ResourceQuotas] = resource.MustParse("1")
|
hard[api.ResourceQuotas] = resource.MustParse("1")
|
||||||
hard[api.ResourceCPU] = resource.MustParse("1")
|
hard[api.ResourceCPU] = resource.MustParse("1")
|
||||||
hard[api.ResourceMemory] = resource.MustParse("500Mi")
|
hard[api.ResourceMemory] = resource.MustParse("500Mi")
|
||||||
|
hard[api.ResourceConfigMaps] = resource.MustParse("2")
|
||||||
|
hard[api.ResourceSecrets] = resource.MustParse("2")
|
||||||
return &api.ResourceQuota{
|
return &api.ResourceQuota{
|
||||||
ObjectMeta: api.ObjectMeta{Name: name},
|
ObjectMeta: api.ObjectMeta{Name: name},
|
||||||
Spec: api.ResourceQuotaSpec{Hard: hard},
|
Spec: api.ResourceQuotaSpec{Hard: hard},
|
||||||
@ -429,6 +466,17 @@ func newTestServiceForQuota(name string) *api.Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newTestConfigMapForQuota(name string) *api.ConfigMap {
|
||||||
|
return &api.ConfigMap{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"a": "b",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newTestSecretForQuota(name string) *api.Secret {
|
func newTestSecretForQuota(name string) *api.Secret {
|
||||||
return &api.Secret{
|
return &api.Secret{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Loading…
Reference in New Issue
Block a user