Skip to content

Commit

Permalink
Merge pull request #24247 from sdminonne/service_loadbalancer_quotas
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue

Adding loadBalancer services to quota system

@derekwaynecarr follow up to #22154.
  • Loading branch information
k8s-merge-robot committed Apr 23, 2016
2 parents e61e396 + f4ed499 commit de9c1a2
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 2 deletions.
2 changes: 2 additions & 0 deletions pkg/api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ var standardQuotaResources = sets.NewString(
string(ResourcePersistentVolumeClaims),
string(ResourceConfigMaps),
string(ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers),
)

// IsStandardQuotaResourceName returns true if the resource is known to
Expand Down Expand Up @@ -192,6 +193,7 @@ var integerResources = sets.NewString(
string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims),
string(ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers),
)

// IsIntegerResourceName returns true if the resource is measured in integer values
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2218,6 +2218,8 @@ const (
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
// ResourceServicesNodePorts, number
ResourceServicesNodePorts ResourceName = "services.nodeports"
// ResourceServicesLoadBalancers, number
ResourceServicesLoadBalancers ResourceName = "services.loadbalancers"
// CPU request, in cores. (500m = .5 cores)
ResourceRequestsCPU ResourceName = "requests.cpu"
// Memory request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2676,6 +2676,8 @@ const (
ResourcePersistentVolumeClaims ResourceName = "persistentvolumeclaims"
// ResourceServicesNodePorts, number
ResourceServicesNodePorts ResourceName = "services.nodeports"
// ResourceServicesLoadBalancers, number
ResourceServicesLoadBalancers ResourceName = "services.loadbalancers"
// CPU request, in cores. (500m = .5 cores)
ResourceCPURequest ResourceName = "cpu.request"
// CPU limit, in cores. (500m = .5 cores)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/resourcequota/replenishment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func ServiceReplenishmentUpdateFunc(options *ReplenishmentControllerOptions) fun
return func(oldObj, newObj interface{}) {
oldService := oldObj.(*api.Service)
newService := newObj.(*api.Service)
if core.QuotaServiceType(oldService) && !core.QuotaServiceType(newService) {
if core.QuotaServiceType(oldService) || core.QuotaServiceType(newService) {
options.ReplenishmentFunc(options.GroupKind, newService.Namespace, newService)
}
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/quota/evaluator/core/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func NewServiceEvaluator(kubeClient clientset.Interface) quota.Evaluator {
allResources := []api.ResourceName{
api.ResourceServices,
api.ResourceServicesNodePorts,
api.ResourceServicesLoadBalancers,
}
return &generic.GenericEvaluator{
Name: "Evaluator.Service",
Expand All @@ -56,6 +57,8 @@ func ServiceUsageFunc(object runtime.Object) api.ResourceList {
switch service.Spec.Type {
case api.ServiceTypeNodePort:
result[api.ResourceServicesNodePorts] = resource.MustParse("1")
case api.ServiceTypeLoadBalancer:
result[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
}
}
return result
Expand All @@ -64,7 +67,7 @@ func ServiceUsageFunc(object runtime.Object) api.ResourceList {
// QuotaServiceType returns true if the service type is eligible to track against a quota
func QuotaServiceType(service *api.Service) bool {
switch service.Spec.Type {
case api.ServiceTypeNodePort:
case api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer:
return true
}
return false
Expand Down
91 changes: 91 additions & 0 deletions test/e2e/resource_quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,96 @@ var _ = framework.KubeDescribe("ResourceQuota", func() {
Expect(err).NotTo(HaveOccurred())
})

It("should create a ResourceQuota and capture the life of a loadBalancer service.", 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 loadBalancer type Service")
service := newTestServiceForQuota("test-service", api.ServiceTypeLoadBalancer)
service, err = f.Client.Services(f.Namespace.Name).Create(service)
Expect(err).NotTo(HaveOccurred())

By("Ensuring resource quota status captures service creation")
usedResources = api.ResourceList{}
usedResources[api.ResourceQuotas] = resource.MustParse("1")
usedResources[api.ResourceServices] = resource.MustParse("1")
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
Expect(err).NotTo(HaveOccurred())

By("Deleting a Service")
err = f.Client.Services(f.Namespace.Name).Delete(service.Name)
Expect(err).NotTo(HaveOccurred())

By("Ensuring resource quota status released usage")
usedResources[api.ResourceServices] = resource.MustParse("0")
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
Expect(err).NotTo(HaveOccurred())
})

It("should create a ResourceQuota and capture the life of a nodePort service updated to loadBalancer.", 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 nodePort type Service")
service := newTestServiceForQuota("test-service", api.ServiceTypeNodePort)
service, err = f.Client.Services(f.Namespace.Name).Create(service)
Expect(err).NotTo(HaveOccurred())

By("Ensuring resource quota status captures service creation")
usedResources = api.ResourceList{}
usedResources[api.ResourceQuotas] = resource.MustParse("1")
usedResources[api.ResourceServices] = resource.MustParse("1")
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
usedResources[api.ResourceServicesNodePorts] = resource.MustParse("1")
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
Expect(err).NotTo(HaveOccurred())

By("Updating the service type to loadBalancer")
service.Spec.Type = api.ServiceTypeLoadBalancer
service.Spec.Ports[0].NodePort = 0
_, err = f.Client.Services(f.Namespace.Name).Update(service)
Expect(err).NotTo(HaveOccurred())

By("Checking resource quota status capture service update")
usedResources = api.ResourceList{}
usedResources[api.ResourceQuotas] = resource.MustParse("1")
usedResources[api.ResourceServices] = resource.MustParse("1")
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
usedResources[api.ResourceServicesNodePorts] = resource.MustParse("0")
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
Expect(err).NotTo(HaveOccurred())

By("Deleting a Service")
err = f.Client.Services(f.Namespace.Name).Delete(service.Name)
Expect(err).NotTo(HaveOccurred())

By("Ensuring resource quota status released usage")
usedResources[api.ResourceServices] = resource.MustParse("0")
usedResources[api.ResourceServicesLoadBalancers] = resource.MustParse("0")
err = waitForResourceQuota(f.Client, f.Namespace.Name, quotaName, usedResources)
Expect(err).NotTo(HaveOccurred())
})

It("should create a ResourceQuota and capture the life of a pod.", func() {
By("Creating a ResourceQuota")
quotaName := "test-quota"
Expand Down Expand Up @@ -578,6 +668,7 @@ func newTestResourceQuota(name string) *api.ResourceQuota {
hard[api.ResourcePods] = resource.MustParse("5")
hard[api.ResourceServices] = resource.MustParse("10")
hard[api.ResourceServicesNodePorts] = resource.MustParse("1")
hard[api.ResourceServicesLoadBalancers] = resource.MustParse("1")
hard[api.ResourceReplicationControllers] = resource.MustParse("10")
hard[api.ResourceQuotas] = resource.MustParse("1")
hard[api.ResourceCPU] = resource.MustParse("1")
Expand Down

1 comment on commit de9c1a2

@k8s-teamcity-mesosphere

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamCity OSS :: Kubernetes Mesos :: 4 - Smoke Tests Build 22446 outcome was FAILURE
Summary: Tests failed: 1, passed: 0, ignored: 279 Build time: 00:29:05

Failed tests

null: Kubernetes e2e suite.[k8s.io] Kubectl client [k8s.io] Guestbook application should create and stop a working application [Conformance]: <no details avaliable>

Please sign in to comment.