Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LimitRange updates for Resource Requirements Requests #12492

Merged
merged 6 commits into from
Aug 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion api/swagger-spec/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -11575,7 +11575,15 @@
},
"default": {
"type": "any",
"description": "Default usage constraints on this kind by resource name. Default values on this kind by resource name if omitted."
"description": "Default resource requirement limit value by resource name if resource limit is omitted."
},
"defaultRequest": {
"type": "any",
"description": "DefaultRequest is the default resource requirement request value by resource name if resource request is omitted."
},
"maxLimitRequestRatio": {
"type": "any",
"description": "MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource."
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ metadata:
spec:
limits:
- type: "Container"
default:
defaultRequest:
cpu: "100m"
64 changes: 35 additions & 29 deletions docs/design/admission_control_limit_range.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ The **LimitRange** resource is scoped to a **Namespace**.
### Type

```go
// A type of object that is limited
// LimitType is a type of object that is limited
type LimitType string

const (
Expand All @@ -63,52 +63,58 @@ const (
LimitTypeContainer LimitType = "Container"
)

// LimitRangeItem defines a min/max usage limit for any resource that matches on kind
// LimitRangeItem defines a min/max usage limit for any resource that matches on kind.
type LimitRangeItem struct {
// Type of resource that this limit applies to
Type LimitType `json:"type,omitempty" description:"type of resource that this limit applies to"`
// Max usage constraints on this kind by resource name
Max ResourceList `json:"max,omitempty" description:"max usage constraints on this kind by resource name"`
// Min usage constraints on this kind by resource name
Min ResourceList `json:"min,omitempty" description:"min usage constraints on this kind by resource name"`
// Default resource limits on this kind by resource name
Default ResourceList `json:"default,omitempty" description:"default resource limits values on this kind by resource name if omitted"`
// DefaultRequests resource requests on this kind by resource name
DefaultRequests ResourceList `json:"defaultRequests,omitempty" description:"default resource requests values on this kind by resource name if omitted"`
// LimitRequestRatio is the ratio of limit over request that is the maximum allowed burst for the named resource
LimitRequestRatio ResourceList `json:"limitRequestRatio,omitempty" description:"the ratio of limit over request that is the maximum allowed burst for the named resource. if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value"`
// Type of resource that this limit applies to.
Type LimitType `json:"type,omitempty"`
// Max usage constraints on this kind by resource name.
Max ResourceList `json:"max,omitempty"`
// Min usage constraints on this kind by resource name.
Min ResourceList `json:"min,omitempty"`
// Default resource requirement limit value by resource name if resource limit is omitted.
Default ResourceList `json:"default,omitempty"`
// DefaultRequest is the default resource requirement request value by resource name if resource request is omitted.
DefaultRequest ResourceList `json:"defaultRequest,omitempty"`
// MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource.
MaxLimitRequestRatio ResourceList `json:"maxLimitRequestRatio,omitempty"`
}

// LimitRangeSpec defines a min/max usage limit for resources that match on kind
// LimitRangeSpec defines a min/max usage limit for resources that match on kind.
type LimitRangeSpec struct {
// Limits is the list of LimitRangeItem objects that are enforced
Limits []LimitRangeItem `json:"limits" description:"limits is the list of LimitRangeItem objects that are enforced"`
// Limits is the list of LimitRangeItem objects that are enforced.
Limits []LimitRangeItem `json:"limits"`
}

// LimitRange sets resource usage limits for each kind of resource in a Namespace
// LimitRange sets resource usage limits for each kind of resource in a Namespace.
type LimitRange struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty" description:"standard object metadata; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"`
TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
ObjectMeta `json:"metadata,omitempty"`

// Spec defines the limits enforced
Spec LimitRangeSpec `json:"spec,omitempty" description:"spec defines the limits enforced; http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status"`
// Spec defines the limits enforced.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
Spec LimitRangeSpec `json:"spec,omitempty"`
}

// LimitRangeList is a list of LimitRange items.
type LimitRangeList struct {
TypeMeta `json:",inline"`
ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"`
// Standard list metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
ListMeta `json:"metadata,omitempty"`

// Items is a list of LimitRange objects
Items []LimitRange `json:"items" description:"items is a list of LimitRange objects; see http://releases.k8s.io/HEAD/docs/design/admission_control_limit_range.md"`
// Items is a list of LimitRange objects.
// More info: http://releases.k8s.io/HEAD/docs/design/admission_control_limit_range.md
Items []LimitRange `json:"items"`
}
```

### Validation

Validation of a **LimitRange** enforces that for a given named resource the following rules apply:

Min (if specified) <= DefaultRequests (if specified) <= Default (if specified) <= Max (if specified)
Min (if specified) <= DefaultRequest (if specified) <= Default (if specified) <= Max (if specified)

### Default Value Behavior

Expand All @@ -121,11 +127,11 @@ if LimitRangeItem.Default[resourceName] is undefined
```

```
if LimitRangeItem.DefaultRequests[resourceName] is undefined
if LimitRangeItem.DefaultRequest[resourceName] is undefined
if LimitRangeItem.Default[resourceName] is defined
LimitRangeItem.DefaultRequests[resourceName] = LimitRangeItem.Default[resourceName]
LimitRangeItem.DefaultRequest[resourceName] = LimitRangeItem.Default[resourceName]
else if LimitRangeItem.Min[resourceName] is defined
LimitRangeItem.DefaultRequests[resourceName] = LimitRangeItem.Min[resourceName]
LimitRangeItem.DefaultRequest[resourceName] = LimitRangeItem.Min[resourceName]
```

## AdmissionControl plugin: LimitRanger
Expand Down
16 changes: 16 additions & 0 deletions docs/devel/api_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,22 @@ generator to create it from scratch.
Unsurprisingly, adding manually written conversion also requires you to add tests to
`pkg/api/<version>/conversion_test.go`.

## Edit deep copy files

At this point you have both the versioned API changes and the internal
structure changes done. You now need to generate code to handle deep copy
of your versioned api objects.

The deep copy code resides with each versioned API:
- `pkg/api/<version>/deep_copy_generated.go` containing auto-generated copy functions

To regenerate them:
- run

```sh
hack/update-generated-deep-copies.sh
```

## Update the fuzzer

Part of our testing regimen for APIs is to "fuzz" (fill with random values) API
Expand Down
24 changes: 24 additions & 0 deletions pkg/api/deep_copy_generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,30 @@ func deepCopy_api_LimitRangeItem(in LimitRangeItem, out *LimitRangeItem, c *conv
} else {
out.Default = nil
}
if in.DefaultRequest != nil {
out.DefaultRequest = make(ResourceList)
for key, val := range in.DefaultRequest {
newVal := new(resource.Quantity)
if err := deepCopy_resource_Quantity(val, newVal, c); err != nil {
return err
}
out.DefaultRequest[key] = *newVal
}
} else {
out.DefaultRequest = nil
}
if in.MaxLimitRequestRatio != nil {
out.MaxLimitRequestRatio = make(ResourceList)
for key, val := range in.MaxLimitRequestRatio {
newVal := new(resource.Quantity)
if err := deepCopy_resource_Quantity(val, newVal, c); err != nil {
return err
}
out.MaxLimitRequestRatio[key] = *newVal
}
} else {
out.MaxLimitRequestRatio = nil
}
return nil
}

Expand Down
22 changes: 22 additions & 0 deletions pkg/api/testing/fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,28 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
q.Limits[api.ResourceStorage] = *storageLimit.Copy()
q.Requests[api.ResourceStorage] = *storageLimit.Copy()
},
func(q *api.LimitRangeItem, c fuzz.Continue) {
Copy link
Member

Choose a reason for hiding this comment

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

include LimitRequestRatio?

randomQuantity := func() resource.Quantity {
return *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
}
cpuLimit := randomQuantity()

q.Type = api.LimitTypeContainer
q.Default = make(api.ResourceList)
q.Default[api.ResourceCPU] = *(cpuLimit.Copy())

q.DefaultRequest = make(api.ResourceList)
q.DefaultRequest[api.ResourceCPU] = *(cpuLimit.Copy())

q.Max = make(api.ResourceList)
q.Max[api.ResourceCPU] = *(cpuLimit.Copy())

q.Min = make(api.ResourceList)
q.Min[api.ResourceCPU] = *(cpuLimit.Copy())

q.MaxLimitRequestRatio = make(api.ResourceList)
q.MaxLimitRequestRatio[api.ResourceCPU] = resource.MustParse("10")
},
func(p *api.PullPolicy, c fuzz.Continue) {
policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent}
*p = policies[c.Rand.Intn(len(policies))]
Expand Down
6 changes: 5 additions & 1 deletion pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1942,8 +1942,12 @@ type LimitRangeItem struct {
Max ResourceList `json:"max,omitempty"`
// Min usage constraints on this kind by resource name
Min ResourceList `json:"min,omitempty"`
// Default usage constraints on this kind by resource name
// Default resource requirement limit value by resource name.
Default ResourceList `json:"default,omitempty"`
// DefaultRequest resource requirement request value by resource name.
DefaultRequest ResourceList `json:"defaultRequest,omitempty"`
// MaxLimitRequestRatio represents the max burst value for the named resource
MaxLimitRequestRatio ResourceList `json:"maxLimitRequestRatio,omitempty"`
}

// LimitRangeSpec defines a min/max usage limit for resources that match on kind
Expand Down
48 changes: 48 additions & 0 deletions pkg/api/v1/conversion_generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,30 @@ func convert_api_LimitRangeItem_To_v1_LimitRangeItem(in *api.LimitRangeItem, out
} else {
out.Default = nil
}
if in.DefaultRequest != nil {
out.DefaultRequest = make(ResourceList)
for key, val := range in.DefaultRequest {
newVal := resource.Quantity{}
if err := s.Convert(&val, &newVal, 0); err != nil {
return err
}
out.DefaultRequest[ResourceName(key)] = newVal
}
} else {
out.DefaultRequest = nil
}
if in.MaxLimitRequestRatio != nil {
out.MaxLimitRequestRatio = make(ResourceList)
for key, val := range in.MaxLimitRequestRatio {
newVal := resource.Quantity{}
if err := s.Convert(&val, &newVal, 0); err != nil {
return err
}
out.MaxLimitRequestRatio[ResourceName(key)] = newVal
}
} else {
out.MaxLimitRequestRatio = nil
}
return nil
}

Expand Down Expand Up @@ -3170,6 +3194,30 @@ func convert_v1_LimitRangeItem_To_api_LimitRangeItem(in *LimitRangeItem, out *ap
} else {
out.Default = nil
}
if in.DefaultRequest != nil {
out.DefaultRequest = make(api.ResourceList)
for key, val := range in.DefaultRequest {
newVal := resource.Quantity{}
if err := s.Convert(&val, &newVal, 0); err != nil {
return err
}
out.DefaultRequest[api.ResourceName(key)] = newVal
}
} else {
out.DefaultRequest = nil
}
if in.MaxLimitRequestRatio != nil {
out.MaxLimitRequestRatio = make(api.ResourceList)
for key, val := range in.MaxLimitRequestRatio {
newVal := resource.Quantity{}
if err := s.Convert(&val, &newVal, 0); err != nil {
return err
}
out.MaxLimitRequestRatio[api.ResourceName(key)] = newVal
}
} else {
out.MaxLimitRequestRatio = nil
}
return nil
}

Expand Down
24 changes: 24 additions & 0 deletions pkg/api/v1/deep_copy_generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,30 @@ func deepCopy_v1_LimitRangeItem(in LimitRangeItem, out *LimitRangeItem, c *conve
} else {
out.Default = nil
}
if in.DefaultRequest != nil {
out.DefaultRequest = make(ResourceList)
for key, val := range in.DefaultRequest {
newVal := new(resource.Quantity)
if err := deepCopy_resource_Quantity(val, newVal, c); err != nil {
return err
}
out.DefaultRequest[key] = *newVal
}
} else {
out.DefaultRequest = nil
}
if in.MaxLimitRequestRatio != nil {
out.MaxLimitRequestRatio = make(ResourceList)
for key, val := range in.MaxLimitRequestRatio {
newVal := new(resource.Quantity)
if err := deepCopy_resource_Quantity(val, newVal, c); err != nil {
return err
}
out.MaxLimitRequestRatio[key] = *newVal
}
} else {
out.MaxLimitRequestRatio = nil
}
return nil
}

Expand Down
31 changes: 31 additions & 0 deletions pkg/api/v1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,37 @@ func addDefaultingFuncs() {
}
}
},
func(obj *LimitRangeItem) {
// for container limits, we apply default values
if obj.Type == LimitTypeContainer {

if obj.Default == nil {
obj.Default = make(ResourceList)
}
if obj.DefaultRequest == nil {
obj.DefaultRequest = make(ResourceList)
}

// If a default limit is unspecified, but the max is specified, default the limit to the max
for key, value := range obj.Max {
if _, exists := obj.Default[key]; !exists {
obj.Default[key] = *(value.Copy())
}
}
// If a default limit is specified, but the default request is not, default request to limit
for key, value := range obj.Default {
if _, exists := obj.DefaultRequest[key]; !exists {
obj.DefaultRequest[key] = *(value.Copy())
}
}
// If a default request is not specified, but the min is provided, default request to the min
for key, value := range obj.Min {
if _, exists := obj.DefaultRequest[key]; !exists {
obj.DefaultRequest[key] = *(value.Copy())
}
}
}
},
)
}

Expand Down