Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
091cbe5f
Commit
091cbe5f
authored
Jan 22, 2015
by
derekwaynecarr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a limit range resource
parent
358ace61
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1208 additions
and
16 deletions
+1208
-16
register.go
pkg/api/register.go
+4
-0
types.go
pkg/api/types.go
+34
-0
conversion.go
pkg/api/v1beta1/conversion.go
+66
-1
register.go
pkg/api/v1beta1/register.go
+4
-0
types.go
pkg/api/v1beta1/types.go
+32
-0
conversion.go
pkg/api/v1beta2/conversion.go
+66
-1
register.go
pkg/api/v1beta2/register.go
+4
-0
types.go
pkg/api/v1beta2/types.go
+32
-0
register.go
pkg/api/v1beta3/register.go
+4
-0
types.go
pkg/api/v1beta3/types.go
+34
-0
validation.go
pkg/api/validation/validation.go
+26
-0
validation_test.go
pkg/api/validation/validation_test.go
+89
-0
client.go
pkg/client/client.go
+5
-0
fake.go
pkg/client/fake.go
+14
-9
fake_limit_ranges.go
pkg/client/fake_limit_ranges.go
+54
-0
limit_ranges.go
pkg/client/limit_ranges.go
+94
-0
limit_ranges_test.go
pkg/client/limit_ranges_test.go
+194
-0
describe.go
pkg/kubectl/describe.go
+56
-0
kubectl.go
pkg/kubectl/kubectl.go
+6
-5
resource_printer.go
pkg/kubectl/resource_printer.go
+21
-0
master.go
pkg/master/master.go
+5
-0
doc.go
pkg/registry/limitrange/doc.go
+19
-0
registry.go
pkg/registry/limitrange/registry.go
+48
-0
registry_test.go
pkg/registry/limitrange/registry_test.go
+121
-0
rest.go
pkg/registry/limitrange/rest.go
+159
-0
rest_test.go
pkg/registry/limitrange/rest_test.go
+17
-0
No files found.
pkg/api/register.go
View file @
091cbe5f
...
@@ -47,6 +47,8 @@ func init() {
...
@@ -47,6 +47,8 @@ func init() {
&
BoundPod
{},
&
BoundPod
{},
&
BoundPods
{},
&
BoundPods
{},
&
List
{},
&
List
{},
&
LimitRange
{},
&
LimitRangeList
{},
)
)
// Legacy names are supported
// Legacy names are supported
Scheme
.
AddKnownTypeWithName
(
""
,
"Minion"
,
&
Node
{})
Scheme
.
AddKnownTypeWithName
(
""
,
"Minion"
,
&
Node
{})
...
@@ -77,3 +79,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
...
@@ -77,3 +79,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
LimitRange
)
IsAnAPIObject
()
{}
func
(
*
LimitRangeList
)
IsAnAPIObject
()
{}
pkg/api/types.go
View file @
091cbe5f
...
@@ -1138,3 +1138,37 @@ type List struct {
...
@@ -1138,3 +1138,37 @@ type List struct {
Items
[]
runtime
.
Object
`json:"items"`
Items
[]
runtime
.
Object
`json:"items"`
}
}
// LimitRangeItem defines a min/max usage limit for any resource that matches on kind
type
LimitRangeItem
struct
{
// Kind is the resource kind that this limit range is applied (i.e. pods, etc.)
Kind
string
// 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"`
}
// 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"`
}
// LimitRange sets resource usage limits for each kind of resource in a Namespace
type
LimitRange
struct
{
TypeMeta
`json:",inline"`
ObjectMeta
`json:"metadata,omitempty"`
// Spec defines the limits enforced
Spec
LimitRangeSpec
`json:"spec,omitempty"`
}
// LimitRangeList is a list of LimitRange items.
type
LimitRangeList
struct
{
TypeMeta
`json:",inline"`
ListMeta
`json:"metadata,omitempty"`
// Items is a list of LimitRange objects
Items
[]
LimitRange
`json:"items"`
}
pkg/api/v1beta1/conversion.go
View file @
091cbe5f
...
@@ -568,7 +568,72 @@ func init() {
...
@@ -568,7 +568,72 @@ func init() {
out
.
Status
.
HostIP
=
in
.
HostIP
out
.
Status
.
HostIP
=
in
.
HostIP
return
s
.
Convert
(
&
in
.
NodeResources
.
Capacity
,
&
out
.
Spec
.
Capacity
,
0
)
return
s
.
Convert
(
&
in
.
NodeResources
.
Capacity
,
&
out
.
Spec
.
Capacity
,
0
)
},
},
func
(
in
*
newer
.
LimitRange
,
out
*
LimitRange
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
ObjectMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
LimitRange
,
out
*
newer
.
LimitRange
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
ObjectMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
LimitRangeSpec
,
out
*
LimitRangeSpec
,
s
conversion
.
Scope
)
error
{
*
out
=
LimitRangeSpec
{}
out
.
Limits
=
make
([]
LimitRangeItem
,
len
(
in
.
Limits
),
len
(
in
.
Limits
))
for
i
:=
range
in
.
Limits
{
if
err
:=
s
.
Convert
(
&
in
.
Limits
[
i
],
&
out
.
Limits
[
i
],
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
LimitRangeSpec
,
out
*
newer
.
LimitRangeSpec
,
s
conversion
.
Scope
)
error
{
*
out
=
newer
.
LimitRangeSpec
{}
out
.
Limits
=
make
([]
newer
.
LimitRangeItem
,
len
(
in
.
Limits
),
len
(
in
.
Limits
))
for
i
:=
range
in
.
Limits
{
if
err
:=
s
.
Convert
(
&
in
.
Limits
[
i
],
&
out
.
Limits
[
i
],
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
newer
.
LimitRangeItem
,
out
*
LimitRangeItem
,
s
conversion
.
Scope
)
error
{
*
out
=
LimitRangeItem
{}
out
.
Kind
=
in
.
Kind
if
err
:=
s
.
Convert
(
&
in
.
Max
,
&
out
.
Max
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Min
,
&
out
.
Min
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
LimitRangeItem
,
out
*
newer
.
LimitRangeItem
,
s
conversion
.
Scope
)
error
{
*
out
=
newer
.
LimitRangeItem
{}
out
.
Kind
=
in
.
Kind
if
err
:=
s
.
Convert
(
&
in
.
Max
,
&
out
.
Max
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Min
,
&
out
.
Min
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
// Object ID <-> Name
// Object ID <-> Name
// TODO: amend the conversion package to allow overriding specific fields.
// TODO: amend the conversion package to allow overriding specific fields.
func
(
in
*
ObjectReference
,
out
*
newer
.
ObjectReference
,
s
conversion
.
Scope
)
error
{
func
(
in
*
ObjectReference
,
out
*
newer
.
ObjectReference
,
s
conversion
.
Scope
)
error
{
...
...
pkg/api/v1beta1/register.go
View file @
091cbe5f
...
@@ -48,6 +48,8 @@ func init() {
...
@@ -48,6 +48,8 @@ func init() {
&
BoundPod
{},
&
BoundPod
{},
&
BoundPods
{},
&
BoundPods
{},
&
List
{},
&
List
{},
&
LimitRange
{},
&
LimitRangeList
{},
)
)
// Future names are supported
// Future names are supported
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta1"
,
"Node"
,
&
Minion
{})
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta1"
,
"Node"
,
&
Minion
{})
...
@@ -78,3 +80,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
...
@@ -78,3 +80,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
LimitRange
)
IsAnAPIObject
()
{}
func
(
*
LimitRangeList
)
IsAnAPIObject
()
{}
pkg/api/v1beta1/types.go
View file @
091cbe5f
...
@@ -904,3 +904,35 @@ type List struct {
...
@@ -904,3 +904,35 @@ type List struct {
TypeMeta
`json:",inline"`
TypeMeta
`json:",inline"`
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
}
}
// LimitRangeItem defines a min/max usage limit for any resource that matches on kind
type
LimitRangeItem
struct
{
// Kind is the resource kind that this limit range is applied (i.e. pods, etc.)
Kind
string
// 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"`
}
// 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"`
}
// LimitRange sets resource usage limits for each kind of resource in a Namespace
type
LimitRange
struct
{
TypeMeta
`json:",inline"`
// Spec defines the limits enforced
Spec
LimitRangeSpec
`json:"spec,omitempty"`
}
// LimitRangeList is a list of LimitRange items.
type
LimitRangeList
struct
{
TypeMeta
`json:",inline"`
// Items is a list of LimitRange objects
Items
[]
LimitRange
`json:"items"`
}
pkg/api/v1beta2/conversion.go
View file @
091cbe5f
...
@@ -485,7 +485,72 @@ func init() {
...
@@ -485,7 +485,72 @@ func init() {
out
.
Status
.
HostIP
=
in
.
HostIP
out
.
Status
.
HostIP
=
in
.
HostIP
return
s
.
Convert
(
&
in
.
NodeResources
.
Capacity
,
&
out
.
Spec
.
Capacity
,
0
)
return
s
.
Convert
(
&
in
.
NodeResources
.
Capacity
,
&
out
.
Spec
.
Capacity
,
0
)
},
},
func
(
in
*
newer
.
LimitRange
,
out
*
LimitRange
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
ObjectMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
LimitRange
,
out
*
newer
.
LimitRange
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
TypeMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
TypeMeta
,
&
out
.
ObjectMeta
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
LimitRangeSpec
,
out
*
LimitRangeSpec
,
s
conversion
.
Scope
)
error
{
*
out
=
LimitRangeSpec
{}
out
.
Limits
=
make
([]
LimitRangeItem
,
len
(
in
.
Limits
),
len
(
in
.
Limits
))
for
i
:=
range
in
.
Limits
{
if
err
:=
s
.
Convert
(
&
in
.
Limits
[
i
],
&
out
.
Limits
[
i
],
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
LimitRangeSpec
,
out
*
newer
.
LimitRangeSpec
,
s
conversion
.
Scope
)
error
{
*
out
=
newer
.
LimitRangeSpec
{}
out
.
Limits
=
make
([]
newer
.
LimitRangeItem
,
len
(
in
.
Limits
),
len
(
in
.
Limits
))
for
i
:=
range
in
.
Limits
{
if
err
:=
s
.
Convert
(
&
in
.
Limits
[
i
],
&
out
.
Limits
[
i
],
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
newer
.
LimitRangeItem
,
out
*
LimitRangeItem
,
s
conversion
.
Scope
)
error
{
*
out
=
LimitRangeItem
{}
out
.
Kind
=
in
.
Kind
if
err
:=
s
.
Convert
(
&
in
.
Max
,
&
out
.
Max
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Min
,
&
out
.
Min
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
LimitRangeItem
,
out
*
newer
.
LimitRangeItem
,
s
conversion
.
Scope
)
error
{
*
out
=
newer
.
LimitRangeItem
{}
out
.
Kind
=
in
.
Kind
if
err
:=
s
.
Convert
(
&
in
.
Max
,
&
out
.
Max
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Min
,
&
out
.
Min
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
// Object ID <-> Name
// Object ID <-> Name
// TODO: amend the conversion package to allow overriding specific fields.
// TODO: amend the conversion package to allow overriding specific fields.
func
(
in
*
ObjectReference
,
out
*
newer
.
ObjectReference
,
s
conversion
.
Scope
)
error
{
func
(
in
*
ObjectReference
,
out
*
newer
.
ObjectReference
,
s
conversion
.
Scope
)
error
{
...
...
pkg/api/v1beta2/register.go
View file @
091cbe5f
...
@@ -48,6 +48,8 @@ func init() {
...
@@ -48,6 +48,8 @@ func init() {
&
BoundPod
{},
&
BoundPod
{},
&
BoundPods
{},
&
BoundPods
{},
&
List
{},
&
List
{},
&
LimitRange
{},
&
LimitRangeList
{},
)
)
// Future names are supported
// Future names are supported
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta2"
,
"Node"
,
&
Minion
{})
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta2"
,
"Node"
,
&
Minion
{})
...
@@ -78,3 +80,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
...
@@ -78,3 +80,5 @@ func (*ContainerManifestList) IsAnAPIObject() {}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPod
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
BoundPods
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
LimitRange
)
IsAnAPIObject
()
{}
func
(
*
LimitRangeList
)
IsAnAPIObject
()
{}
pkg/api/v1beta2/types.go
View file @
091cbe5f
...
@@ -906,3 +906,35 @@ type List struct {
...
@@ -906,3 +906,35 @@ type List struct {
TypeMeta
`json:",inline"`
TypeMeta
`json:",inline"`
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
}
}
// LimitRangeItem defines a min/max usage limit for any resource that matches on kind
type
LimitRangeItem
struct
{
// Kind is the resource kind that this limit range is applied (i.e. pods, etc.)
Kind
string
// 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"`
}
// 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"`
}
// LimitRange sets resource usage limits for each kind of resource in a Namespace
type
LimitRange
struct
{
TypeMeta
`json:",inline"`
// Spec defines the limits enforced
Spec
LimitRangeSpec
`json:"spec,omitempty"`
}
// LimitRangeList is a list of LimitRange items.
type
LimitRangeList
struct
{
TypeMeta
`json:",inline"`
// Items is a list of LimitRange objects
Items
[]
LimitRange
`json:"items"`
}
pkg/api/v1beta3/register.go
View file @
091cbe5f
...
@@ -48,6 +48,8 @@ func init() {
...
@@ -48,6 +48,8 @@ func init() {
&
Event
{},
&
Event
{},
&
EventList
{},
&
EventList
{},
&
List
{},
&
List
{},
&
LimitRange
{},
&
LimitRangeList
{},
)
)
// Legacy names are supported
// Legacy names are supported
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta3"
,
"Minion"
,
&
Node
{})
api
.
Scheme
.
AddKnownTypeWithName
(
"v1beta3"
,
"Minion"
,
&
Node
{})
...
@@ -78,3 +80,5 @@ func (*OperationList) IsAnAPIObject() {}
...
@@ -78,3 +80,5 @@ func (*OperationList) IsAnAPIObject() {}
func
(
*
Event
)
IsAnAPIObject
()
{}
func
(
*
Event
)
IsAnAPIObject
()
{}
func
(
*
EventList
)
IsAnAPIObject
()
{}
func
(
*
EventList
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
List
)
IsAnAPIObject
()
{}
func
(
*
LimitRange
)
IsAnAPIObject
()
{}
func
(
*
LimitRangeList
)
IsAnAPIObject
()
{}
pkg/api/v1beta3/types.go
View file @
091cbe5f
...
@@ -1066,3 +1066,37 @@ type List struct {
...
@@ -1066,3 +1066,37 @@ type List struct {
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
Items
[]
runtime
.
RawExtension
`json:"items" description:"list of objects"`
}
}
// LimitRangeItem defines a min/max usage limit for any resource that matches on kind
type
LimitRangeItem
struct
{
// Kind is the resource kind that this limit range is applied (i.e. pods, etc.)
Kind
string
// 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"`
}
// 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"`
}
// LimitRange sets resource usage limits for each kind of resource in a Namespace
type
LimitRange
struct
{
TypeMeta
`json:",inline"`
ObjectMeta
`json:"metadata,omitempty"`
// Spec defines the limits enforced
Spec
LimitRangeSpec
`json:"spec,omitempty"`
}
// LimitRangeList is a list of LimitRange items.
type
LimitRangeList
struct
{
TypeMeta
`json:",inline"`
ListMeta
`json:"metadata,omitempty"`
// Items is a list of LimitRange objects
Items
[]
LimitRange
`json:"items"`
}
pkg/api/validation/validation.go
View file @
091cbe5f
...
@@ -640,3 +640,29 @@ func ValidateResourceName(str string) errs.ValidationErrorList {
...
@@ -640,3 +640,29 @@ func ValidateResourceName(str string) errs.ValidationErrorList {
return
errs
.
ValidationErrorList
{}
return
errs
.
ValidationErrorList
{}
}
}
// ValidateLimitRange tests if required fields in the LimitRange are set.
func
ValidateLimitRange
(
limitRange
*
api
.
LimitRange
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
len
(
limitRange
.
Name
)
==
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"name"
,
limitRange
.
Name
))
}
else
if
!
util
.
IsDNSSubdomain
(
limitRange
.
Name
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"name"
,
limitRange
.
Name
,
""
))
}
if
len
(
limitRange
.
Namespace
)
==
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"namespace"
,
limitRange
.
Namespace
))
}
else
if
!
util
.
IsDNSSubdomain
(
limitRange
.
Namespace
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"namespace"
,
limitRange
.
Namespace
,
""
))
}
// ensure resource names are properly qualified per docs/resources.md
for
i
:=
range
limitRange
.
Spec
.
Limits
{
limit
:=
limitRange
.
Spec
.
Limits
[
i
]
for
k
,
_
:=
range
limit
.
Max
{
allErrs
=
append
(
allErrs
,
ValidateResourceName
(
k
))
}
for
k
,
_
:=
range
limit
.
Min
{
allErrs
=
append
(
allErrs
,
ValidateResourceName
(
k
))
}
}
return
allErrs
}
pkg/api/validation/validation_test.go
View file @
091cbe5f
...
@@ -1552,3 +1552,92 @@ func TestValidateResourceNames(t *testing.T) {
...
@@ -1552,3 +1552,92 @@ func TestValidateResourceNames(t *testing.T) {
}
}
}
}
}
}
func
TestValidateLimitRange
(
t
*
testing
.
T
)
{
successCases
:=
[]
api
.
LimitRange
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
"foo"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
},
}
for
_
,
successCase
:=
range
successCases
{
if
errs
:=
ValidateLimitRange
(
&
successCase
);
len
(
errs
)
!=
0
{
t
.
Errorf
(
"expected success: %v"
,
errs
)
}
}
errorCases
:=
map
[
string
]
api
.
LimitRange
{
"zero-length Name"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
""
,
Namespace
:
"foo"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
},
"zero-length-namespace"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
""
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
},
}
for
k
,
v
:=
range
errorCases
{
errs
:=
ValidateLimitRange
(
&
v
)
if
len
(
errs
)
==
0
{
t
.
Errorf
(
"expected failure for %s"
,
k
)
}
for
i
:=
range
errs
{
field
:=
errs
[
i
]
.
(
*
errors
.
ValidationError
)
.
Field
if
field
!=
"name"
&&
field
!=
"namespace"
{
t
.
Errorf
(
"%s: missing prefix for: %v"
,
k
,
errs
[
i
])
}
}
}
}
pkg/client/client.go
View file @
091cbe5f
...
@@ -37,6 +37,7 @@ type Interface interface {
...
@@ -37,6 +37,7 @@ type Interface interface {
VersionInterface
VersionInterface
NodesInterface
NodesInterface
EventNamespacer
EventNamespacer
LimitRangesNamespacer
}
}
func
(
c
*
Client
)
ReplicationControllers
(
namespace
string
)
ReplicationControllerInterface
{
func
(
c
*
Client
)
ReplicationControllers
(
namespace
string
)
ReplicationControllerInterface
{
...
@@ -63,6 +64,10 @@ func (c *Client) Services(namespace string) ServiceInterface {
...
@@ -63,6 +64,10 @@ func (c *Client) Services(namespace string) ServiceInterface {
return
newServices
(
c
,
namespace
)
return
newServices
(
c
,
namespace
)
}
}
func
(
c
*
Client
)
LimitRanges
(
namespace
string
)
LimitRangeInterface
{
return
newLimitRanges
(
c
,
namespace
)
}
// VersionInterface has a method to retrieve the server version.
// VersionInterface has a method to retrieve the server version.
type
VersionInterface
interface
{
type
VersionInterface
interface
{
ServerVersion
()
(
*
version
.
Info
,
error
)
ServerVersion
()
(
*
version
.
Info
,
error
)
...
...
pkg/client/fake.go
View file @
091cbe5f
...
@@ -34,15 +34,20 @@ type FakeAction struct {
...
@@ -34,15 +34,20 @@ type FakeAction struct {
// Fake implements Interface. Meant to be embedded into a struct to get a default
// Fake implements Interface. Meant to be embedded into a struct to get a default
// implementation. This makes faking out just the method you want to test easier.
// implementation. This makes faking out just the method you want to test easier.
type
Fake
struct
{
type
Fake
struct
{
Actions
[]
FakeAction
Actions
[]
FakeAction
PodsList
api
.
PodList
PodsList
api
.
PodList
Ctrl
api
.
ReplicationController
Ctrl
api
.
ReplicationController
ServiceList
api
.
ServiceList
ServiceList
api
.
ServiceList
EndpointsList
api
.
EndpointsList
EndpointsList
api
.
EndpointsList
MinionsList
api
.
NodeList
MinionsList
api
.
NodeList
EventsList
api
.
EventList
EventsList
api
.
EventList
Err
error
LimitRangesList
api
.
LimitRangeList
Watch
watch
.
Interface
Err
error
Watch
watch
.
Interface
}
func
(
c
*
Fake
)
LimitRanges
(
namespace
string
)
LimitRangeInterface
{
return
&
FakeLimitRanges
{
Fake
:
c
,
Namespace
:
namespace
}
}
}
func
(
c
*
Fake
)
ReplicationControllers
(
namespace
string
)
ReplicationControllerInterface
{
func
(
c
*
Fake
)
ReplicationControllers
(
namespace
string
)
ReplicationControllerInterface
{
...
...
pkg/client/fake_limit_ranges.go
0 → 100644
View file @
091cbe5f
/*
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
client
import
(
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
)
// FakeLimitRanges implements PodsInterface. Meant to be embedded into a struct to get a default
// implementation. This makes faking out just the methods you want to test easier.
type
FakeLimitRanges
struct
{
Fake
*
Fake
Namespace
string
}
func
(
c
*
FakeLimitRanges
)
List
(
selector
labels
.
Selector
)
(
*
api
.
LimitRangeList
,
error
)
{
c
.
Fake
.
Actions
=
append
(
c
.
Fake
.
Actions
,
FakeAction
{
Action
:
"list-limitRanges"
})
return
api
.
Scheme
.
CopyOrDie
(
&
c
.
Fake
.
LimitRangesList
)
.
(
*
api
.
LimitRangeList
),
nil
}
func
(
c
*
FakeLimitRanges
)
Get
(
name
string
)
(
*
api
.
LimitRange
,
error
)
{
c
.
Fake
.
Actions
=
append
(
c
.
Fake
.
Actions
,
FakeAction
{
Action
:
"get-limitRange"
,
Value
:
name
})
return
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
name
,
Namespace
:
c
.
Namespace
}},
nil
}
func
(
c
*
FakeLimitRanges
)
Delete
(
name
string
)
error
{
c
.
Fake
.
Actions
=
append
(
c
.
Fake
.
Actions
,
FakeAction
{
Action
:
"delete-limitRange"
,
Value
:
name
})
return
nil
}
func
(
c
*
FakeLimitRanges
)
Create
(
limitRange
*
api
.
LimitRange
)
(
*
api
.
LimitRange
,
error
)
{
c
.
Fake
.
Actions
=
append
(
c
.
Fake
.
Actions
,
FakeAction
{
Action
:
"create-limitRange"
})
return
&
api
.
LimitRange
{},
nil
}
func
(
c
*
FakeLimitRanges
)
Update
(
limitRange
*
api
.
LimitRange
)
(
*
api
.
LimitRange
,
error
)
{
c
.
Fake
.
Actions
=
append
(
c
.
Fake
.
Actions
,
FakeAction
{
Action
:
"update-limitRange"
,
Value
:
limitRange
.
Name
})
return
&
api
.
LimitRange
{},
nil
}
pkg/client/limit_ranges.go
0 → 100644
View file @
091cbe5f
/*
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
client
import
(
"errors"
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
)
// LimitRangesNamespacer has methods to work with LimitRange resources in a namespace
type
LimitRangesNamespacer
interface
{
LimitRanges
(
namespace
string
)
LimitRangeInterface
}
// LimitRangeInterface has methods to work with LimitRange resources.
type
LimitRangeInterface
interface
{
List
(
selector
labels
.
Selector
)
(
*
api
.
LimitRangeList
,
error
)
Get
(
name
string
)
(
*
api
.
LimitRange
,
error
)
Delete
(
name
string
)
error
Create
(
limitRange
*
api
.
LimitRange
)
(
*
api
.
LimitRange
,
error
)
Update
(
limitRange
*
api
.
LimitRange
)
(
*
api
.
LimitRange
,
error
)
}
// limitRanges implements LimitRangesNamespacer interface
type
limitRanges
struct
{
r
*
Client
ns
string
}
// newLimitRanges returns a limitRanges
func
newLimitRanges
(
c
*
Client
,
namespace
string
)
*
limitRanges
{
return
&
limitRanges
{
r
:
c
,
ns
:
namespace
,
}
}
// List takes a selector, and returns the list of limitRanges that match that selector.
func
(
c
*
limitRanges
)
List
(
selector
labels
.
Selector
)
(
result
*
api
.
LimitRangeList
,
err
error
)
{
result
=
&
api
.
LimitRangeList
{}
err
=
c
.
r
.
Get
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"limitRanges"
)
.
SelectorParam
(
"labels"
,
selector
)
.
Do
()
.
Into
(
result
)
return
}
// Get takes the name of the limitRange, and returns the corresponding Pod object, and an error if it occurs
func
(
c
*
limitRanges
)
Get
(
name
string
)
(
result
*
api
.
LimitRange
,
err
error
)
{
if
len
(
name
)
==
0
{
return
nil
,
errors
.
New
(
"name is required parameter to Get"
)
}
result
=
&
api
.
LimitRange
{}
err
=
c
.
r
.
Get
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"limitRanges"
)
.
Name
(
name
)
.
Do
()
.
Into
(
result
)
return
}
// Delete takes the name of the limitRange, and returns an error if one occurs
func
(
c
*
limitRanges
)
Delete
(
name
string
)
error
{
return
c
.
r
.
Delete
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"limitRanges"
)
.
Name
(
name
)
.
Do
()
.
Error
()
}
// Create takes the representation of a limitRange. Returns the server's representation of the limitRange, and an error, if it occurs.
func
(
c
*
limitRanges
)
Create
(
limitRange
*
api
.
LimitRange
)
(
result
*
api
.
LimitRange
,
err
error
)
{
result
=
&
api
.
LimitRange
{}
err
=
c
.
r
.
Post
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"limitRanges"
)
.
Body
(
limitRange
)
.
Do
()
.
Into
(
result
)
return
}
// Update takes the representation of a limitRange to update. Returns the server's representation of the limitRange, and an error, if it occurs.
func
(
c
*
limitRanges
)
Update
(
limitRange
*
api
.
LimitRange
)
(
result
*
api
.
LimitRange
,
err
error
)
{
result
=
&
api
.
LimitRange
{}
if
len
(
limitRange
.
ResourceVersion
)
==
0
{
err
=
fmt
.
Errorf
(
"invalid update object, missing resource version: %v"
,
limitRange
)
return
}
err
=
c
.
r
.
Put
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"limitRanges"
)
.
Name
(
limitRange
.
Name
)
.
Body
(
limitRange
)
.
Do
()
.
Into
(
result
)
return
}
pkg/client/limit_ranges_test.go
0 → 100644
View file @
091cbe5f
/*
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
client
import
(
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
//"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func
TestLimitRangeCreate
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
limitRange
:=
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"POST"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges"
),
Query
:
buildQueryValues
(
ns
,
nil
),
Body
:
limitRange
,
},
Response
:
Response
{
StatusCode
:
200
,
Body
:
limitRange
},
}
response
,
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
Create
(
limitRange
)
c
.
Validate
(
t
,
response
,
err
)
}
func
TestLimitRangeGet
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
limitRange
:=
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"GET"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges/abc"
),
Query
:
buildQueryValues
(
ns
,
nil
),
Body
:
nil
,
},
Response
:
Response
{
StatusCode
:
200
,
Body
:
limitRange
},
}
response
,
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
Get
(
"abc"
)
c
.
Validate
(
t
,
response
,
err
)
}
func
TestLimitRangeList
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
limitRangeList
:=
&
api
.
LimitRangeList
{
Items
:
[]
api
.
LimitRange
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
},
},
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"GET"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges"
),
Query
:
buildQueryValues
(
ns
,
nil
),
Body
:
nil
,
},
Response
:
Response
{
StatusCode
:
200
,
Body
:
limitRangeList
},
}
response
,
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
List
(
labels
.
Everything
())
c
.
Validate
(
t
,
response
,
err
)
}
func
TestLimitRangeUpdate
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
limitRange
:=
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
ResourceVersion
:
"1"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"PUT"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges/abc"
),
Query
:
buildQueryValues
(
ns
,
nil
)},
Response
:
Response
{
StatusCode
:
200
,
Body
:
limitRange
},
}
response
,
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
Update
(
limitRange
)
c
.
Validate
(
t
,
response
,
err
)
}
func
TestInvalidLimitRangeUpdate
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
limitRange
:=
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"PUT"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges/abc"
),
Query
:
buildQueryValues
(
ns
,
nil
)},
Response
:
Response
{
StatusCode
:
200
,
Body
:
limitRange
},
}
_
,
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
Update
(
limitRange
)
if
err
==
nil
{
t
.
Errorf
(
"Expected an error due to missing ResourceVersion"
)
}
}
func
TestLimitRangeDelete
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"DELETE"
,
Path
:
buildResourcePath
(
ns
,
"/limitRanges/foo"
),
Query
:
buildQueryValues
(
ns
,
nil
)},
Response
:
Response
{
StatusCode
:
200
},
}
err
:=
c
.
Setup
()
.
LimitRanges
(
ns
)
.
Delete
(
"foo"
)
c
.
Validate
(
t
,
nil
,
err
)
}
pkg/kubectl/describe.go
View file @
091cbe5f
...
@@ -47,10 +47,66 @@ func DescriberFor(kind string, c *client.Client) (Describer, bool) {
...
@@ -47,10 +47,66 @@ func DescriberFor(kind string, c *client.Client) (Describer, bool) {
return
&
ServiceDescriber
{
c
},
true
return
&
ServiceDescriber
{
c
},
true
case
"Minion"
,
"Node"
:
case
"Minion"
,
"Node"
:
return
&
MinionDescriber
{
c
},
true
return
&
MinionDescriber
{
c
},
true
case
"LimitRange"
:
return
&
LimitRangeDescriber
{
c
},
true
}
}
return
nil
,
false
return
nil
,
false
}
}
// LimitRangeDescriber generates information about a limit range
type
LimitRangeDescriber
struct
{
client
.
Interface
}
func
(
d
*
LimitRangeDescriber
)
Describe
(
namespace
,
name
string
)
(
string
,
error
)
{
lr
:=
d
.
LimitRanges
(
namespace
)
limitRange
,
err
:=
lr
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
return
tabbedString
(
func
(
out
io
.
Writer
)
error
{
fmt
.
Fprintf
(
out
,
"Name:
\t
%s
\n
"
,
limitRange
.
Name
)
fmt
.
Fprintf
(
out
,
"Kind
\t
Resource
\t
Min
\t
Max
\n
"
)
fmt
.
Fprintf
(
out
,
"----
\t
--------
\t
---
\t
---
\n
"
)
for
i
,
_
:=
range
limitRange
.
Spec
.
Limits
{
item
:=
limitRange
.
Spec
.
Limits
[
i
]
kind
:=
item
.
Kind
maxResources
:=
item
.
Max
minResources
:=
item
.
Min
set
:=
map
[
api
.
ResourceName
]
bool
{}
for
k
,
_
:=
range
maxResources
{
set
[
k
]
=
true
}
for
k
,
_
:=
range
minResources
{
set
[
k
]
=
true
}
for
k
,
_
:=
range
set
{
// if no value is set, we output -
maxValue
:=
"-"
minValue
:=
"-"
maxQuantity
,
maxQuantityFound
:=
maxResources
[
k
]
if
maxQuantityFound
{
maxValue
=
maxQuantity
.
String
()
}
minQuantity
,
minQuantityFound
:=
minResources
[
k
]
if
minQuantityFound
{
minValue
=
minQuantity
.
String
()
}
msg
:=
"%v
\t
%v
\t
%v
\t
%v
\n
"
fmt
.
Fprintf
(
out
,
msg
,
kind
,
k
,
minValue
,
maxValue
)
}
}
return
nil
})
}
// PodDescriber generates information about a pod and the replication controllers that
// PodDescriber generates information about a pod and the replication controllers that
// create it.
// create it.
type
PodDescriber
struct
{
type
PodDescriber
struct
{
...
...
pkg/kubectl/kubectl.go
View file @
091cbe5f
...
@@ -143,11 +143,12 @@ func (e ShortcutExpander) VersionAndKindForResource(resource string) (defaultVer
...
@@ -143,11 +143,12 @@ func (e ShortcutExpander) VersionAndKindForResource(resource string) (defaultVer
// indeed a shortcut. Otherwise, will return resource unmodified.
// indeed a shortcut. Otherwise, will return resource unmodified.
func
expandResourceShortcut
(
resource
string
)
string
{
func
expandResourceShortcut
(
resource
string
)
string
{
shortForms
:=
map
[
string
]
string
{
shortForms
:=
map
[
string
]
string
{
"po"
:
"pods"
,
"po"
:
"pods"
,
"rc"
:
"replicationcontrollers"
,
"rc"
:
"replicationcontrollers"
,
"se"
:
"services"
,
"se"
:
"services"
,
"mi"
:
"minions"
,
"mi"
:
"minions"
,
"ev"
:
"events"
,
"ev"
:
"events"
,
"limits"
:
"limitRanges"
,
}
}
if
expanded
,
ok
:=
shortForms
[
resource
];
ok
{
if
expanded
,
ok
:=
shortForms
[
resource
];
ok
{
return
expanded
return
expanded
...
...
pkg/kubectl/resource_printer.go
View file @
091cbe5f
...
@@ -221,6 +221,7 @@ var serviceColumns = []string{"NAME", "LABELS", "SELECTOR", "IP", "PORT"}
...
@@ -221,6 +221,7 @@ var serviceColumns = []string{"NAME", "LABELS", "SELECTOR", "IP", "PORT"}
var
minionColumns
=
[]
string
{
"NAME"
,
"LABELS"
,
"STATUS"
}
var
minionColumns
=
[]
string
{
"NAME"
,
"LABELS"
,
"STATUS"
}
var
statusColumns
=
[]
string
{
"STATUS"
}
var
statusColumns
=
[]
string
{
"STATUS"
}
var
eventColumns
=
[]
string
{
"TIME"
,
"NAME"
,
"KIND"
,
"SUBOBJECT"
,
"REASON"
,
"SOURCE"
,
"MESSAGE"
}
var
eventColumns
=
[]
string
{
"TIME"
,
"NAME"
,
"KIND"
,
"SUBOBJECT"
,
"REASON"
,
"SOURCE"
,
"MESSAGE"
}
var
limitRangeColumns
=
[]
string
{
"NAME"
}
// addDefaultHandlers adds print handlers for default Kubernetes types.
// addDefaultHandlers adds print handlers for default Kubernetes types.
func
(
h
*
HumanReadablePrinter
)
addDefaultHandlers
()
{
func
(
h
*
HumanReadablePrinter
)
addDefaultHandlers
()
{
...
@@ -235,6 +236,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
...
@@ -235,6 +236,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h
.
Handler
(
statusColumns
,
printStatus
)
h
.
Handler
(
statusColumns
,
printStatus
)
h
.
Handler
(
eventColumns
,
printEvent
)
h
.
Handler
(
eventColumns
,
printEvent
)
h
.
Handler
(
eventColumns
,
printEventList
)
h
.
Handler
(
eventColumns
,
printEventList
)
h
.
Handler
(
limitRangeColumns
,
printLimitRange
)
h
.
Handler
(
limitRangeColumns
,
printLimitRangeList
)
}
}
func
(
h
*
HumanReadablePrinter
)
unknown
(
data
[]
byte
,
w
io
.
Writer
)
error
{
func
(
h
*
HumanReadablePrinter
)
unknown
(
data
[]
byte
,
w
io
.
Writer
)
error
{
...
@@ -409,6 +412,24 @@ func printEventList(list *api.EventList, w io.Writer) error {
...
@@ -409,6 +412,24 @@ func printEventList(list *api.EventList, w io.Writer) error {
return
nil
return
nil
}
}
func
printLimitRange
(
limitRange
*
api
.
LimitRange
,
w
io
.
Writer
)
error
{
_
,
err
:=
fmt
.
Fprintf
(
w
,
"%s
\n
"
,
limitRange
.
Name
,
)
return
err
}
// Prints the LimitRangeList in a human-friendly format.
func
printLimitRangeList
(
list
*
api
.
LimitRangeList
,
w
io
.
Writer
)
error
{
for
i
:=
range
list
.
Items
{
if
err
:=
printLimitRange
(
&
list
.
Items
[
i
],
w
);
err
!=
nil
{
return
err
}
}
return
nil
}
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
func
(
h
*
HumanReadablePrinter
)
PrintObj
(
obj
runtime
.
Object
,
output
io
.
Writer
)
error
{
func
(
h
*
HumanReadablePrinter
)
PrintObj
(
obj
runtime
.
Object
,
output
io
.
Writer
)
error
{
w
:=
tabwriter
.
NewWriter
(
output
,
20
,
5
,
3
,
' '
,
0
)
w
:=
tabwriter
.
NewWriter
(
output
,
20
,
5
,
3
,
' '
,
0
)
...
...
pkg/master/master.go
View file @
091cbe5f
...
@@ -47,6 +47,7 @@ import (
...
@@ -47,6 +47,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/event"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/event"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/limitrange"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
...
@@ -109,6 +110,7 @@ type Master struct {
...
@@ -109,6 +110,7 @@ type Master struct {
minionRegistry
minion
.
Registry
minionRegistry
minion
.
Registry
bindingRegistry
binding
.
Registry
bindingRegistry
binding
.
Registry
eventRegistry
generic
.
Registry
eventRegistry
generic
.
Registry
limitRangeRegistry
generic
.
Registry
storage
map
[
string
]
apiserver
.
RESTStorage
storage
map
[
string
]
apiserver
.
RESTStorage
client
*
client
.
Client
client
*
client
.
Client
portalNet
*
net
.
IPNet
portalNet
*
net
.
IPNet
...
@@ -248,6 +250,7 @@ func New(c *Config) *Master {
...
@@ -248,6 +250,7 @@ func New(c *Config) *Master {
bindingRegistry
:
etcd
.
NewRegistry
(
c
.
EtcdHelper
,
boundPodFactory
),
bindingRegistry
:
etcd
.
NewRegistry
(
c
.
EtcdHelper
,
boundPodFactory
),
eventRegistry
:
event
.
NewEtcdRegistry
(
c
.
EtcdHelper
,
uint64
(
c
.
EventTTL
.
Seconds
())),
eventRegistry
:
event
.
NewEtcdRegistry
(
c
.
EtcdHelper
,
uint64
(
c
.
EventTTL
.
Seconds
())),
minionRegistry
:
minionRegistry
,
minionRegistry
:
minionRegistry
,
limitRangeRegistry
:
limitrange
.
NewEtcdRegistry
(
c
.
EtcdHelper
),
client
:
c
.
Client
,
client
:
c
.
Client
,
portalNet
:
c
.
PortalNet
,
portalNet
:
c
.
PortalNet
,
rootWebService
:
new
(
restful
.
WebService
),
rootWebService
:
new
(
restful
.
WebService
),
...
@@ -361,6 +364,8 @@ func (m *Master) init(c *Config) {
...
@@ -361,6 +364,8 @@ func (m *Master) init(c *Config) {
// TODO: should appear only in scheduler API group.
// TODO: should appear only in scheduler API group.
"bindings"
:
binding
.
NewREST
(
m
.
bindingRegistry
),
"bindings"
:
binding
.
NewREST
(
m
.
bindingRegistry
),
"limitRanges"
:
limitrange
.
NewREST
(
m
.
limitRangeRegistry
),
}
}
apiVersions
:=
[]
string
{
"v1beta1"
,
"v1beta2"
}
apiVersions
:=
[]
string
{
"v1beta1"
,
"v1beta2"
}
...
...
pkg/registry/limitrange/doc.go
0 → 100644
View file @
091cbe5f
/*
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 limitrange provides Registry interface and it's REST
// implementation for storing LimitRange api objects.
package
limitrange
pkg/registry/limitrange/registry.go
0 → 100644
View file @
091cbe5f
/*
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
limitrange
import
(
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
etcdgeneric
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
)
// registry implements custom changes to generic.Etcd.
type
registry
struct
{
*
etcdgeneric
.
Etcd
}
// NewEtcdRegistry returns a registry which will store LimitRange in the given helper
func
NewEtcdRegistry
(
h
tools
.
EtcdHelper
)
generic
.
Registry
{
return
registry
{
Etcd
:
&
etcdgeneric
.
Etcd
{
NewFunc
:
func
()
runtime
.
Object
{
return
&
api
.
LimitRange
{}
},
NewListFunc
:
func
()
runtime
.
Object
{
return
&
api
.
LimitRangeList
{}
},
EndpointName
:
"limitranges"
,
KeyRootFunc
:
func
(
ctx
api
.
Context
)
string
{
return
etcdgeneric
.
NamespaceKeyRootFunc
(
ctx
,
"/registry/limitranges"
)
},
KeyFunc
:
func
(
ctx
api
.
Context
,
id
string
)
(
string
,
error
)
{
return
etcdgeneric
.
NamespaceKeyFunc
(
ctx
,
"/registry/limitranges"
,
id
)
},
Helper
:
h
,
},
}
}
pkg/registry/limitrange/registry_test.go
0 → 100644
View file @
091cbe5f
/*
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
limitrange
import
(
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
etcdgeneric
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/coreos/go-etcd/etcd"
)
func
NewTestLimitRangeEtcdRegistry
(
t
*
testing
.
T
)
(
*
tools
.
FakeEtcdClient
,
generic
.
Registry
)
{
f
:=
tools
.
NewFakeEtcdClient
(
t
)
f
.
TestIndex
=
true
h
:=
tools
.
EtcdHelper
{
f
,
testapi
.
Codec
(),
tools
.
RuntimeVersionAdapter
{
testapi
.
MetadataAccessor
()}}
return
f
,
NewEtcdRegistry
(
h
)
}
func
TestLimitRangeCreate
(
t
*
testing
.
T
)
{
limitRange
:=
&
api
.
LimitRange
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
"foo"
,
},
Spec
:
api
.
LimitRangeSpec
{
Limits
:
[]
api
.
LimitRangeItem
{
{
Kind
:
"pods"
,
Max
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"100"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"10000"
),
},
Min
:
api
.
ResourceList
{
api
.
ResourceCPU
:
resource
.
MustParse
(
"0"
),
api
.
ResourceMemory
:
resource
.
MustParse
(
"100"
),
},
},
},
},
}
nodeWithLimitRange
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Codec
(),
limitRange
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
emptyNode
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{},
E
:
tools
.
EtcdErrorNotFound
,
}
ctx
:=
api
.
NewDefaultContext
()
key
:=
"foo"
path
,
err
:=
etcdgeneric
.
NamespaceKeyFunc
(
ctx
,
"/registry/limitranges"
,
key
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
table
:=
map
[
string
]
struct
{
existing
tools
.
EtcdResponseWithError
expect
tools
.
EtcdResponseWithError
toCreate
runtime
.
Object
errOK
func
(
error
)
bool
}{
"normal"
:
{
existing
:
emptyNode
,
expect
:
nodeWithLimitRange
,
toCreate
:
limitRange
,
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"preExisting"
:
{
existing
:
nodeWithLimitRange
,
expect
:
nodeWithLimitRange
,
toCreate
:
limitRange
,
errOK
:
errors
.
IsAlreadyExists
,
},
}
for
name
,
item
:=
range
table
{
fakeClient
,
registry
:=
NewTestLimitRangeEtcdRegistry
(
t
)
fakeClient
.
Data
[
path
]
=
item
.
existing
err
:=
registry
.
Create
(
ctx
,
key
,
item
.
toCreate
)
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
}
if
e
,
a
:=
item
.
expect
,
fakeClient
.
Data
[
path
];
!
reflect
.
DeepEqual
(
e
,
a
)
{
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
pkg/registry/limitrange/rest.go
0 → 100644
View file @
091cbe5f
/*
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
limitrange
import
(
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
)
// REST provides the RESTStorage access patterns to work with LimitRange objects.
type
REST
struct
{
registry
generic
.
Registry
}
// NewREST returns a new REST. You must use a registry created by
// NewEtcdRegistry unless you're testing.
func
NewREST
(
registry
generic
.
Registry
)
*
REST
{
return
&
REST
{
registry
:
registry
,
}
}
// Create a LimitRange object
func
(
rs
*
REST
)
Create
(
ctx
api
.
Context
,
obj
runtime
.
Object
)
(
<-
chan
apiserver
.
RESTResult
,
error
)
{
limitRange
,
ok
:=
obj
.
(
*
api
.
LimitRange
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"invalid object type"
)
}
if
!
api
.
ValidNamespace
(
ctx
,
&
limitRange
.
ObjectMeta
)
{
return
nil
,
errors
.
NewConflict
(
"limitRange"
,
limitRange
.
Namespace
,
fmt
.
Errorf
(
"LimitRange.Namespace does not match the provided context"
))
}
if
len
(
limitRange
.
Name
)
==
0
{
limitRange
.
Name
=
string
(
util
.
NewUUID
())
}
if
errs
:=
validation
.
ValidateLimitRange
(
limitRange
);
len
(
errs
)
>
0
{
return
nil
,
errors
.
NewInvalid
(
"limitRange"
,
limitRange
.
Name
,
errs
)
}
api
.
FillObjectMetaSystemFields
(
ctx
,
&
limitRange
.
ObjectMeta
)
return
apiserver
.
MakeAsync
(
func
()
(
runtime
.
Object
,
error
)
{
err
:=
rs
.
registry
.
Create
(
ctx
,
limitRange
.
Name
,
limitRange
)
if
err
!=
nil
{
return
nil
,
err
}
return
rs
.
registry
.
Get
(
ctx
,
limitRange
.
Name
)
}),
nil
}
// Update updates a LimitRange object.
func
(
rs
*
REST
)
Update
(
ctx
api
.
Context
,
obj
runtime
.
Object
)
(
<-
chan
apiserver
.
RESTResult
,
error
)
{
limitRange
,
ok
:=
obj
.
(
*
api
.
LimitRange
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"invalid object type"
)
}
if
!
api
.
ValidNamespace
(
ctx
,
&
limitRange
.
ObjectMeta
)
{
return
nil
,
errors
.
NewConflict
(
"limitRange"
,
limitRange
.
Namespace
,
fmt
.
Errorf
(
"LimitRange.Namespace does not match the provided context"
))
}
oldObj
,
err
:=
rs
.
registry
.
Get
(
ctx
,
limitRange
.
Name
)
if
err
!=
nil
{
return
nil
,
err
}
editLimitRange
:=
oldObj
.
(
*
api
.
LimitRange
)
// set the editable fields on the existing object
editLimitRange
.
Labels
=
limitRange
.
Labels
editLimitRange
.
ResourceVersion
=
limitRange
.
ResourceVersion
editLimitRange
.
Annotations
=
limitRange
.
Annotations
editLimitRange
.
Spec
=
limitRange
.
Spec
if
errs
:=
validation
.
ValidateLimitRange
(
editLimitRange
);
len
(
errs
)
>
0
{
return
nil
,
errors
.
NewInvalid
(
"limitRange"
,
editLimitRange
.
Name
,
errs
)
}
return
apiserver
.
MakeAsync
(
func
()
(
runtime
.
Object
,
error
)
{
err
:=
rs
.
registry
.
Update
(
ctx
,
editLimitRange
.
Name
,
editLimitRange
)
if
err
!=
nil
{
return
nil
,
err
}
return
rs
.
registry
.
Get
(
ctx
,
editLimitRange
.
Name
)
}),
nil
}
// Delete deletes the LimitRange with the specified name
func
(
rs
*
REST
)
Delete
(
ctx
api
.
Context
,
name
string
)
(
<-
chan
apiserver
.
RESTResult
,
error
)
{
obj
,
err
:=
rs
.
registry
.
Get
(
ctx
,
name
)
if
err
!=
nil
{
return
nil
,
err
}
_
,
ok
:=
obj
.
(
*
api
.
LimitRange
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"invalid object type"
)
}
return
apiserver
.
MakeAsync
(
func
()
(
runtime
.
Object
,
error
)
{
return
&
api
.
Status
{
Status
:
api
.
StatusSuccess
},
rs
.
registry
.
Delete
(
ctx
,
name
)
}),
nil
}
// Get gets a LimitRange with the specified name
func
(
rs
*
REST
)
Get
(
ctx
api
.
Context
,
name
string
)
(
runtime
.
Object
,
error
)
{
obj
,
err
:=
rs
.
registry
.
Get
(
ctx
,
name
)
if
err
!=
nil
{
return
nil
,
err
}
limitRange
,
ok
:=
obj
.
(
*
api
.
LimitRange
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"invalid object type"
)
}
return
limitRange
,
err
}
func
(
rs
*
REST
)
getAttrs
(
obj
runtime
.
Object
)
(
objLabels
,
objFields
labels
.
Set
,
err
error
)
{
return
labels
.
Set
{},
labels
.
Set
{},
nil
}
func
(
rs
*
REST
)
List
(
ctx
api
.
Context
,
label
,
field
labels
.
Selector
)
(
runtime
.
Object
,
error
)
{
return
rs
.
registry
.
List
(
ctx
,
&
generic
.
SelectionPredicate
{
label
,
field
,
rs
.
getAttrs
})
}
func
(
rs
*
REST
)
Watch
(
ctx
api
.
Context
,
label
,
field
labels
.
Selector
,
resourceVersion
string
)
(
watch
.
Interface
,
error
)
{
return
rs
.
registry
.
Watch
(
ctx
,
&
generic
.
SelectionPredicate
{
label
,
field
,
rs
.
getAttrs
},
resourceVersion
)
}
// New returns a new api.LimitRange
func
(
*
REST
)
New
()
runtime
.
Object
{
return
&
api
.
LimitRange
{}
}
func
(
*
REST
)
NewList
()
runtime
.
Object
{
return
&
api
.
LimitRangeList
{}
}
pkg/registry/limitrange/rest_test.go
0 → 100644
View file @
091cbe5f
/*
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
limitrange
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment