mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Implement LimitRanger plugin
This commit is contained in:
		
							
								
								
									
										31
									
								
								examples/limitrange/limitrange.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								examples/limitrange/limitrange.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
{
 | 
			
		||||
  "id": "limits",
 | 
			
		||||
  "kind": "LimitRange",
 | 
			
		||||
  "apiVersion": "v1beta1",
 | 
			
		||||
  "spec": {
 | 
			
		||||
    "limits": [
 | 
			
		||||
    {
 | 
			
		||||
      "kind": "pods",
 | 
			
		||||
      "max": {
 | 
			
		||||
        "memory": "1073741824",
 | 
			
		||||
        "cpu": "2",
 | 
			
		||||
      },
 | 
			
		||||
      "min": {
 | 
			
		||||
        "memory": "1048576",
 | 
			
		||||
        "cpu": "0.25"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "kind": "containers",
 | 
			
		||||
      "max": {
 | 
			
		||||
        "memory": "1073741824",
 | 
			
		||||
        "cpu": "2",
 | 
			
		||||
      },
 | 
			
		||||
      "min": {
 | 
			
		||||
        "memory": "1048576",
 | 
			
		||||
        "cpu": "0.25"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    ],
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										190
									
								
								plugin/pkg/admission/limitranger/admission.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								plugin/pkg/admission/limitranger/admission.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. 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 limitranger
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
 | 
			
		||||
		return NewLimitRanger(client, PodLimitFunc), nil
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// limitRanger enforces usage limits on a per resource basis in the namespace
 | 
			
		||||
type limitRanger struct {
 | 
			
		||||
	client    client.Interface
 | 
			
		||||
	limitFunc LimitFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Admit admits resources into cluster that do not violate any defined LimitRange in the namespace
 | 
			
		||||
func (l *limitRanger) Admit(a admission.Attributes) (err error) {
 | 
			
		||||
	// ignore deletes
 | 
			
		||||
	if a.GetOperation() == "DELETE" {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// look for a limit range in current namespace that requires enforcement
 | 
			
		||||
	items, err := l.client.LimitRanges(a.GetNamespace()).List(labels.Everything())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ensure it meets each prescribed min/max
 | 
			
		||||
	for i := range items.Items {
 | 
			
		||||
		limitRange := &items.Items[i]
 | 
			
		||||
		err = l.limitFunc(limitRange, a.GetKind(), a.GetObject())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewLimitRanger returns an object that enforces limits based on the supplied limit function
 | 
			
		||||
func NewLimitRanger(client client.Interface, limitFunc LimitFunc) admission.Interface {
 | 
			
		||||
	return &limitRanger{client: client, limitFunc: limitFunc}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Min(a int64, b int64) int64 {
 | 
			
		||||
	if a < b {
 | 
			
		||||
		return a
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Max(a int64, b int64) int64 {
 | 
			
		||||
	if a > b {
 | 
			
		||||
		return a
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PodLimitFunc enforces that a pod spec does not exceed any limits specified on the supplied limit range
 | 
			
		||||
func PodLimitFunc(limitRange *api.LimitRange, kind string, obj runtime.Object) error {
 | 
			
		||||
	if kind != "pods" {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pod := obj.(*api.Pod)
 | 
			
		||||
 | 
			
		||||
	podCPU := int64(0)
 | 
			
		||||
	podMem := int64(0)
 | 
			
		||||
 | 
			
		||||
	minContainerCPU := int64(0)
 | 
			
		||||
	minContainerMem := int64(0)
 | 
			
		||||
	maxContainerCPU := int64(0)
 | 
			
		||||
	maxContainerMem := int64(0)
 | 
			
		||||
 | 
			
		||||
	for i := range pod.Spec.Containers {
 | 
			
		||||
		container := pod.Spec.Containers[i]
 | 
			
		||||
		containerCPU := container.CPU.MilliValue()
 | 
			
		||||
		containerMem := container.Memory.Value()
 | 
			
		||||
 | 
			
		||||
		if i == 0 {
 | 
			
		||||
			minContainerCPU = containerCPU
 | 
			
		||||
			minContainerMem = containerMem
 | 
			
		||||
			maxContainerCPU = containerCPU
 | 
			
		||||
			maxContainerMem = containerMem
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		podCPU = podCPU + container.CPU.MilliValue()
 | 
			
		||||
		podMem = podMem + container.Memory.Value()
 | 
			
		||||
 | 
			
		||||
		minContainerCPU = Min(containerCPU, minContainerCPU)
 | 
			
		||||
		minContainerMem = Min(containerMem, minContainerMem)
 | 
			
		||||
		maxContainerCPU = Max(containerCPU, maxContainerCPU)
 | 
			
		||||
		maxContainerMem = Max(containerMem, maxContainerMem)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range limitRange.Spec.Limits {
 | 
			
		||||
		limit := limitRange.Spec.Limits[i]
 | 
			
		||||
		// enforce max
 | 
			
		||||
		for k, v := range limit.Max {
 | 
			
		||||
			observed := int64(0)
 | 
			
		||||
			enforced := int64(0)
 | 
			
		||||
			var err error
 | 
			
		||||
			switch k {
 | 
			
		||||
			case api.ResourceMemory:
 | 
			
		||||
				enforced = v.Value()
 | 
			
		||||
				switch limit.Kind {
 | 
			
		||||
				case "pods":
 | 
			
		||||
					observed = podMem
 | 
			
		||||
					err = fmt.Errorf("Maximum memory usage per pod is %s", v.String())
 | 
			
		||||
				case "containers":
 | 
			
		||||
					observed = maxContainerMem
 | 
			
		||||
					err = fmt.Errorf("Maximum memory usage per container is %s", v.String())
 | 
			
		||||
				}
 | 
			
		||||
			case api.ResourceCPU:
 | 
			
		||||
				enforced = v.MilliValue()
 | 
			
		||||
				switch limit.Kind {
 | 
			
		||||
				case "pods":
 | 
			
		||||
					observed = podCPU
 | 
			
		||||
					err = fmt.Errorf("Maximum CPU usage per pod is %s, but requested %s", v.String(), resource.NewMilliQuantity(observed, resource.DecimalSI))
 | 
			
		||||
				case "containers":
 | 
			
		||||
					observed = maxContainerCPU
 | 
			
		||||
					err = fmt.Errorf("Maximum CPU usage per container is %s", v.String())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if observed > enforced {
 | 
			
		||||
				return apierrors.NewForbidden(kind, pod.Name, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for k, v := range limit.Min {
 | 
			
		||||
			observed := int64(0)
 | 
			
		||||
			enforced := int64(0)
 | 
			
		||||
			var err error
 | 
			
		||||
			switch k {
 | 
			
		||||
			case api.ResourceMemory:
 | 
			
		||||
				enforced = v.Value()
 | 
			
		||||
				switch limit.Kind {
 | 
			
		||||
				case "pods":
 | 
			
		||||
					observed = podMem
 | 
			
		||||
					err = fmt.Errorf("Minimum memory usage per pod is %s", v.String())
 | 
			
		||||
				case "containers":
 | 
			
		||||
					observed = maxContainerMem
 | 
			
		||||
					err = fmt.Errorf("Minimum memory usage per container is %s", v.String())
 | 
			
		||||
				}
 | 
			
		||||
			case api.ResourceCPU:
 | 
			
		||||
				enforced = v.MilliValue()
 | 
			
		||||
				switch limit.Kind {
 | 
			
		||||
				case "pods":
 | 
			
		||||
					observed = podCPU
 | 
			
		||||
					err = fmt.Errorf("Minimum CPU usage per pod is %s", v.String())
 | 
			
		||||
				case "containers":
 | 
			
		||||
					observed = maxContainerCPU
 | 
			
		||||
					err = fmt.Errorf("Minimum CPU usage per container is %s", v.String())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if observed < enforced {
 | 
			
		||||
				return apierrors.NewForbidden(kind, pod.Name, err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										238
									
								
								plugin/pkg/admission/limitranger/admission_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								plugin/pkg/admission/limitranger/admission_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,238 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. 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 limitranger
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestPodLimitFunc(t *testing.T) {
 | 
			
		||||
	limitRange := &api.LimitRange{
 | 
			
		||||
		ObjectMeta: api.ObjectMeta{
 | 
			
		||||
			Name: "abc",
 | 
			
		||||
		},
 | 
			
		||||
		Spec: api.LimitRangeSpec{
 | 
			
		||||
			Limits: []api.LimitRangeItem{
 | 
			
		||||
				{
 | 
			
		||||
					Kind: "pods",
 | 
			
		||||
					Max: api.ResourceList{
 | 
			
		||||
						api.ResourceCPU:    resource.MustParse("200m"),
 | 
			
		||||
						api.ResourceMemory: resource.MustParse("4Gi"),
 | 
			
		||||
					},
 | 
			
		||||
					Min: api.ResourceList{
 | 
			
		||||
						api.ResourceCPU:    resource.MustParse("50m"),
 | 
			
		||||
						api.ResourceMemory: resource.MustParse("2Mi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Kind: "containers",
 | 
			
		||||
					Max: api.ResourceList{
 | 
			
		||||
						api.ResourceCPU:    resource.MustParse("100m"),
 | 
			
		||||
						api.ResourceMemory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
					Min: api.ResourceList{
 | 
			
		||||
						api.ResourceCPU:    resource.MustParse("25m"),
 | 
			
		||||
						api.ResourceMemory: resource.MustParse("1Mi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	successCases := []api.Pod{
 | 
			
		||||
		{
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "foo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("100m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("100m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "bar"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("100m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	errorCases := map[string]api.Pod{
 | 
			
		||||
		"min-container-cpu": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("25m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"max-container-cpu": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("110m"),
 | 
			
		||||
						Memory: resource.MustParse("1Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"min-container-mem": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("30m"),
 | 
			
		||||
						Memory: resource.MustParse("0"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"max-container-mem": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("30m"),
 | 
			
		||||
						Memory: resource.MustParse("3Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"min-pod-cpu": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("40m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"max-pod-cpu": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("1Mi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V2",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("1Mi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V3",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("1Mi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V4",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("1Mi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"max-pod-memory": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V2",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V3",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("2Gi"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"min-pod-memory": {
 | 
			
		||||
			ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
			
		||||
			Spec: api.PodSpec{
 | 
			
		||||
				Containers: []api.Container{
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V1",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("0"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V2",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("0"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						Image:  "boo:V3",
 | 
			
		||||
						CPU:    resource.MustParse("60m"),
 | 
			
		||||
						Memory: resource.MustParse("0"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range successCases {
 | 
			
		||||
		err := PodLimitFunc(limitRange, "pods", &successCases[i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Unexpected error for valid pod: %v, %v", successCases[i].Name, err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k, v := range errorCases {
 | 
			
		||||
		err := PodLimitFunc(limitRange, "pods", &v)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			t.Errorf("Expected error for %s", k)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								plugin/pkg/admission/limitranger/interfaces.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plugin/pkg/admission/limitranger/interfaces.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2014 Google Inc. 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 limitranger
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
			
		||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LimitFunc is a pluggable function to enforce limits on the object
 | 
			
		||||
type LimitFunc func(limitRange *api.LimitRange, kind string, obj runtime.Object) error
 | 
			
		||||
		Reference in New Issue
	
	Block a user