Commit 0e3469dc authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #22183 from pmorie/config-quota

Auto commit by PR queue bot
parents 3b4ce5ed 834776aa
......@@ -237,6 +237,7 @@ func StartControllers(s *options.CMServer, kubeClient *client.Client, kubeconfig
api.Kind("ReplicationController"),
api.Kind("PersistentVolumeClaim"),
api.Kind("Secret"),
api.Kind("ConfigMap"),
}
resourceQuotaControllerOptions := &resourcequotacontroller.ResourceQuotaControllerOptions{
KubeClient: resourceQuotaControllerClient,
......
......@@ -140,6 +140,7 @@ var standardQuotaResources = sets.NewString(
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourcePersistentVolumeClaims),
string(ResourceConfigMaps),
)
// IsStandardQuotaResourceName returns true if the resource is known to
......@@ -160,6 +161,7 @@ var standardResources = sets.NewString(
string(ResourceServices),
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims),
string(ResourceStorage),
)
......@@ -175,6 +177,7 @@ var integerResources = sets.NewString(
string(ResourceServices),
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims),
)
......
......@@ -2187,6 +2187,8 @@ const (
ResourceQuotas ResourceName = "resourcequotas"
// ResourceSecrets, number
ResourceSecrets ResourceName = "secrets"
// ResourceConfigMaps, number
ResourceConfigMaps ResourceName = "configmaps"
// ResourcePersistentVolumeClaims, number
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
// CPU request, in cores. (500m = .5 cores)
......
......@@ -2644,6 +2644,8 @@ const (
ResourceQuotas ResourceName = "resourcequotas"
// ResourceSecrets, number
ResourceSecrets ResourceName = "secrets"
// ResourceConfigMaps, number
ResourceConfigMaps ResourceName = "configmaps"
// ResourcePersistentVolumeClaims, number
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
// CPU request, in cores. (500m = .5 cores)
......
......@@ -4082,6 +4082,8 @@ func TestValidateResourceQuota(t *testing.T) {
api.ResourceServices: resource.MustParse("0"),
api.ResourceReplicationControllers: 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.ResourceReplicationControllers: 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),
},
)
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:
return nil, fmt.Errorf("no replenishment controller available for %s", options.GroupKind)
}
......
/*
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)
resourceQuota := NewResourceQuotaEvaluator(kubeClient)
secret := NewSecretEvaluator(kubeClient)
configMap := NewConfigMapEvaluator(kubeClient)
persistentVolumeClaim := NewPersistentVolumeClaimEvaluator(kubeClient)
return &generic.GenericRegistry{
InternalEvaluators: map[unversioned.GroupKind]quota.Evaluator{
......@@ -37,6 +38,7 @@ func NewRegistry(kubeClient clientset.Interface) quota.Registry {
service.GroupKind(): service,
replicationController.GroupKind(): replicationController,
secret.GroupKind(): secret,
configMap.GroupKind(): configMap,
resourceQuota.GroupKind(): resourceQuota,
persistentVolumeClaim.GroupKind(): persistentVolumeClaim,
},
......
......@@ -182,6 +182,41 @@ var _ = Describe("ResourceQuota", func() {
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() {
By("Creating a ResourceQuota with terminating scope")
quotaTerminatingName := "quota-terminating"
......@@ -387,6 +422,8 @@ func newTestResourceQuota(name string) *api.ResourceQuota {
hard[api.ResourceQuotas] = resource.MustParse("1")
hard[api.ResourceCPU] = resource.MustParse("1")
hard[api.ResourceMemory] = resource.MustParse("500Mi")
hard[api.ResourceConfigMaps] = resource.MustParse("2")
hard[api.ResourceSecrets] = resource.MustParse("2")
return &api.ResourceQuota{
ObjectMeta: api.ObjectMeta{Name: name},
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 {
return &api.Secret{
ObjectMeta: api.ObjectMeta{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment