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
e5ac4133
Commit
e5ac4133
authored
Aug 28, 2015
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13286 from nikhiljindal/validateDeployment
Auto commit by PR queue bot
parents
c49466a7
92f373a4
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
369 additions
and
133 deletions
+369
-133
validation.go
pkg/api/validation/validation.go
+52
-24
validation_test.go
pkg/api/validation/validation_test.go
+0
-5
deep_copy_generated.go
pkg/expapi/deep_copy_generated.go
+1
-6
types.go
pkg/expapi/types.go
+2
-3
conversion.go
pkg/expapi/v1/conversion.go
+87
-0
conversion_generated.go
pkg/expapi/v1/conversion_generated.go
+0
-95
validation.go
pkg/expapi/validation/validation.go
+101
-0
validation_test.go
pkg/expapi/validation/validation_test.go
+118
-0
validation.go
pkg/util/validation.go
+8
-0
No files found.
pkg/api/validation/validation.go
View file @
e5ac4133
...
...
@@ -53,13 +53,19 @@ var portNameErrorMsg string = fmt.Sprintf(`must be an IANA_SVC_NAME (at most 15
const
totalAnnotationSizeLimitB
int
=
64
*
(
1
<<
10
)
// 64 kB
func
ValidateLabelName
(
labelName
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
!
util
.
IsQualifiedName
(
labelName
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
,
labelName
,
qualifiedNameErrorMsg
))
}
return
allErrs
}
// ValidateLabels validates that a set of labels are correctly defined.
func
ValidateLabels
(
labels
map
[
string
]
string
,
field
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
for
k
,
v
:=
range
labels
{
if
!
util
.
IsQualifiedName
(
k
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
field
,
k
,
qualifiedNameErrorMsg
))
}
allErrs
=
append
(
allErrs
,
ValidateLabelName
(
k
,
field
)
...
)
if
!
util
.
IsValidLabelValue
(
v
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
field
,
v
,
labelValueErrorMsg
))
}
...
...
@@ -202,6 +208,15 @@ func NameIsDNS952Label(name string, prefix bool) (bool, string) {
return
false
,
DNS952LabelErrorMsg
}
// Validates that given value is not negative.
func
ValidatePositiveField
(
value
int64
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
value
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
,
value
,
isNegativeErrorMsg
))
}
return
allErrs
}
// ValidateObjectMeta validates an object's metadata on creation. It expects that name generation has already
// been performed.
func
ValidateObjectMeta
(
meta
*
api
.
ObjectMeta
,
requiresNamespace
bool
,
nameFn
ValidateNameFunc
)
errs
.
ValidationErrorList
{
...
...
@@ -224,9 +239,7 @@ func ValidateObjectMeta(meta *api.ObjectMeta, requiresNamespace bool, nameFn Val
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"name"
,
meta
.
Name
,
qualifier
))
}
}
if
meta
.
Generation
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"generation"
,
meta
.
Generation
,
isNegativeErrorMsg
))
}
allErrs
=
append
(
allErrs
,
ValidatePositiveField
(
meta
.
Generation
,
"generation"
)
...
)
if
requiresNamespace
{
if
len
(
meta
.
Namespace
)
==
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"namespace"
))
...
...
@@ -1206,37 +1219,52 @@ func ValidateReplicationControllerUpdate(oldController, controller *api.Replicat
return
allErrs
}
// Validate
ReplicationControllerSpec tests if required fields in the replication controller spec are set
.
func
Validate
ReplicationControllerSpec
(
spec
*
api
.
ReplicationControllerSpec
)
errs
.
ValidationErrorList
{
// Validate
s that the given selector is non-empty
.
func
Validate
NonEmptySelector
(
selectorMap
map
[
string
]
string
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
selector
:=
labels
.
Set
(
spec
.
Selector
)
.
AsSelector
()
selector
:=
labels
.
Set
(
selectorMap
)
.
AsSelector
()
if
selector
.
Empty
()
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"selector"
))
}
if
spec
.
Replicas
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"replicas"
,
spec
.
Replicas
,
isNegativeErrorMsg
))
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
fieldName
))
}
return
allErrs
}
if
spec
.
Template
==
nil
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"template"
))
// Validates the given template and ensures that it is in accordance with the desrired selector and replicas.
func
ValidatePodTemplateSpecForRC
(
template
*
api
.
PodTemplateSpec
,
selectorMap
map
[
string
]
string
,
replicas
int
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
template
==
nil
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
fieldName
))
}
else
{
labels
:=
labels
.
Set
(
spec
.
Template
.
Labels
)
if
!
selector
.
Matches
(
labels
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"template.metadata.labels"
,
spec
.
Template
.
Labels
,
"selector does not match template"
))
selector
:=
labels
.
Set
(
selectorMap
)
.
AsSelector
()
if
!
selector
.
Empty
()
{
// Verify that the RC selector matches the labels in template.
labels
:=
labels
.
Set
(
template
.
Labels
)
if
!
selector
.
Matches
(
labels
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
+
".metadata.labels"
,
template
.
Labels
,
"selector does not match labels in "
+
fieldName
))
}
}
allErrs
=
append
(
allErrs
,
ValidatePodTemplateSpec
(
spec
.
Template
)
.
Prefix
(
"template"
)
...
)
if
spec
.
R
eplicas
>
1
{
allErrs
=
append
(
allErrs
,
ValidateReadOnlyPersistentDisks
(
spec
.
Template
.
Spec
.
Volumes
)
.
Prefix
(
"template
.spec.volumes"
)
...
)
allErrs
=
append
(
allErrs
,
ValidatePodTemplateSpec
(
template
)
.
Prefix
(
fieldName
)
...
)
if
r
eplicas
>
1
{
allErrs
=
append
(
allErrs
,
ValidateReadOnlyPersistentDisks
(
template
.
Spec
.
Volumes
)
.
Prefix
(
fieldName
+
"
.spec.volumes"
)
...
)
}
// RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec().
if
spec
.
T
emplate
.
Spec
.
RestartPolicy
!=
api
.
RestartPolicyAlways
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldValueNotSupported
(
"template.spec.restartPolicy"
,
spec
.
T
emplate
.
Spec
.
RestartPolicy
,
[]
string
{
string
(
api
.
RestartPolicyAlways
)}))
if
t
emplate
.
Spec
.
RestartPolicy
!=
api
.
RestartPolicyAlways
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldValueNotSupported
(
fieldName
+
".spec.restartPolicy"
,
t
emplate
.
Spec
.
RestartPolicy
,
[]
string
{
string
(
api
.
RestartPolicyAlways
)}))
}
}
return
allErrs
}
// ValidateReplicationControllerSpec tests if required fields in the replication controller spec are set.
func
ValidateReplicationControllerSpec
(
spec
*
api
.
ReplicationControllerSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
ValidateNonEmptySelector
(
spec
.
Selector
,
"selector"
)
...
)
allErrs
=
append
(
allErrs
,
ValidatePositiveField
(
int64
(
spec
.
Replicas
),
"replicas"
)
...
)
allErrs
=
append
(
allErrs
,
ValidatePodTemplateSpecForRC
(
spec
.
Template
,
spec
.
Selector
,
spec
.
Replicas
,
"template"
)
...
)
return
allErrs
}
// ValidatePodTemplateSpec validates the spec of a pod template
func
ValidatePodTemplateSpec
(
spec
*
api
.
PodTemplateSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
...
...
pkg/api/validation/validation_test.go
View file @
e5ac4133
...
...
@@ -234,7 +234,6 @@ func TestValidateAnnotations(t *testing.T) {
}
func
testVolume
(
name
string
,
namespace
string
,
spec
api
.
PersistentVolumeSpec
)
*
api
.
PersistentVolume
{
objMeta
:=
api
.
ObjectMeta
{
Name
:
name
}
if
namespace
!=
""
{
objMeta
.
Namespace
=
namespace
...
...
@@ -247,7 +246,6 @@ func testVolume(name string, namespace string, spec api.PersistentVolumeSpec) *a
}
func
TestValidatePersistentVolumes
(
t
*
testing
.
T
)
{
scenarios
:=
map
[
string
]
struct
{
isExpectedFailure
bool
volume
*
api
.
PersistentVolume
...
...
@@ -358,7 +356,6 @@ func testVolumeClaim(name string, namespace string, spec api.PersistentVolumeCla
}
func
TestValidatePersistentVolumeClaim
(
t
*
testing
.
T
)
{
scenarios
:=
map
[
string
]
struct
{
isExpectedFailure
bool
claim
*
api
.
PersistentVolumeClaim
...
...
@@ -802,7 +799,6 @@ func TestValidatePullPolicy(t *testing.T) {
t
.
Errorf
(
"case[%s] expected policy %v, got %v"
,
k
,
v
.
ExpectedPolicy
,
ctr
.
ImagePullPolicy
)
}
}
}
func
getResourceLimits
(
cpu
,
memory
string
)
api
.
ResourceList
{
...
...
@@ -2144,7 +2140,6 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
t
.
Errorf
(
"expected failure: %s"
,
testName
)
}
}
}
func
TestValidateReplicationController
(
t
*
testing
.
T
)
{
...
...
pkg/expapi/deep_copy_generated.go
View file @
e5ac4133
...
...
@@ -787,12 +787,7 @@ func deepCopy_expapi_DeploymentList(in DeploymentList, out *DeploymentList, c *c
}
func
deepCopy_expapi_DeploymentSpec
(
in
DeploymentSpec
,
out
*
DeploymentSpec
,
c
*
conversion
.
Cloner
)
error
{
if
in
.
Replicas
!=
nil
{
out
.
Replicas
=
new
(
int
)
*
out
.
Replicas
=
*
in
.
Replicas
}
else
{
out
.
Replicas
=
nil
}
out
.
Replicas
=
in
.
Replicas
if
in
.
Selector
!=
nil
{
out
.
Selector
=
make
(
map
[
string
]
string
)
for
key
,
val
:=
range
in
.
Selector
{
...
...
pkg/expapi/types.go
View file @
e5ac4133
...
...
@@ -179,9 +179,8 @@ type Deployment struct {
}
type
DeploymentSpec
struct
{
// Number of desired pods. This is a pointer to distinguish between explicit
// zero and not specified. Defaults to 1.
Replicas
*
int
`json:"replicas,omitempty"`
// Number of desired pods.
Replicas
int
`json:"replicas,omitempty"`
// Label selector for pods. Existing ReplicationControllers whose pods are
// selected by this will be scaled down.
...
...
pkg/expapi/v1/conversion.go
View file @
e5ac4133
...
...
@@ -22,6 +22,7 @@ import (
"k8s.io/kubernetes/pkg/api"
v1
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/expapi"
)
func
addConversionFuncs
()
{
...
...
@@ -29,6 +30,9 @@ func addConversionFuncs() {
err
:=
api
.
Scheme
.
AddConversionFuncs
(
convert_api_PodSpec_To_v1_PodSpec
,
convert_v1_PodSpec_To_api_PodSpec
,
convert_expapi_DeploymentSpec_To_v1_DeploymentSpec
,
convert_v1_DeploymentSpec_To_expapi_DeploymentSpec
,
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
,
)
if
err
!=
nil
{
// If one of the conversion functions is malformed, detect it immediately.
...
...
@@ -169,3 +173,86 @@ func convert_v1_PodSpec_To_api_PodSpec(in *v1.PodSpec, out *api.PodSpec, s conve
}
return
nil
}
func
convert_expapi_DeploymentSpec_To_v1_DeploymentSpec
(
in
*
expapi
.
DeploymentSpec
,
out
*
DeploymentSpec
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
expapi
.
DeploymentSpec
))(
in
)
}
out
.
Replicas
=
new
(
int
)
*
out
.
Replicas
=
in
.
Replicas
if
in
.
Selector
!=
nil
{
out
.
Selector
=
make
(
map
[
string
]
string
)
for
key
,
val
:=
range
in
.
Selector
{
out
.
Selector
[
key
]
=
val
}
}
else
{
out
.
Selector
=
nil
}
if
in
.
Template
!=
nil
{
out
.
Template
=
new
(
v1
.
PodTemplateSpec
)
if
err
:=
convert_api_PodTemplateSpec_To_v1_PodTemplateSpec
(
in
.
Template
,
out
.
Template
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
Template
=
nil
}
if
err
:=
convert_expapi_DeploymentStrategy_To_v1_DeploymentStrategy
(
&
in
.
Strategy
,
&
out
.
Strategy
,
s
);
err
!=
nil
{
return
err
}
if
in
.
UniqueLabelKey
!=
nil
{
out
.
UniqueLabelKey
=
new
(
string
)
*
out
.
UniqueLabelKey
=
*
in
.
UniqueLabelKey
}
else
{
out
.
UniqueLabelKey
=
nil
}
return
nil
}
func
convert_v1_DeploymentSpec_To_expapi_DeploymentSpec
(
in
*
DeploymentSpec
,
out
*
expapi
.
DeploymentSpec
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
DeploymentSpec
))(
in
)
}
out
.
Replicas
=
*
in
.
Replicas
if
in
.
Selector
!=
nil
{
out
.
Selector
=
make
(
map
[
string
]
string
)
for
key
,
val
:=
range
in
.
Selector
{
out
.
Selector
[
key
]
=
val
}
}
else
{
out
.
Selector
=
nil
}
if
in
.
Template
!=
nil
{
out
.
Template
=
new
(
api
.
PodTemplateSpec
)
if
err
:=
convert_v1_PodTemplateSpec_To_api_PodTemplateSpec
(
in
.
Template
,
out
.
Template
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
Template
=
nil
}
if
err
:=
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
(
&
in
.
Strategy
,
&
out
.
Strategy
,
s
);
err
!=
nil
{
return
err
}
if
in
.
UniqueLabelKey
!=
nil
{
out
.
UniqueLabelKey
=
new
(
string
)
*
out
.
UniqueLabelKey
=
*
in
.
UniqueLabelKey
}
else
{
out
.
UniqueLabelKey
=
nil
}
return
nil
}
func
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
(
in
*
DeploymentStrategy
,
out
*
expapi
.
DeploymentStrategy
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
DeploymentStrategy
))(
in
)
}
out
.
Type
=
expapi
.
DeploymentType
(
in
.
Type
)
if
in
.
RollingUpdate
!=
nil
{
out
.
RollingUpdate
=
new
(
expapi
.
RollingUpdateDeployment
)
if
err
:=
convert_v1_RollingUpdateDeployment_To_expapi_RollingUpdateDeployment
(
in
.
RollingUpdate
,
out
.
RollingUpdate
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
RollingUpdate
=
nil
}
return
nil
}
pkg/expapi/v1/conversion_generated.go
View file @
e5ac4133
...
...
@@ -1512,44 +1512,6 @@ func convert_expapi_DeploymentList_To_v1_DeploymentList(in *expapi.DeploymentLis
return
nil
}
func
convert_expapi_DeploymentSpec_To_v1_DeploymentSpec
(
in
*
expapi
.
DeploymentSpec
,
out
*
DeploymentSpec
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
expapi
.
DeploymentSpec
))(
in
)
}
if
in
.
Replicas
!=
nil
{
out
.
Replicas
=
new
(
int
)
*
out
.
Replicas
=
*
in
.
Replicas
}
else
{
out
.
Replicas
=
nil
}
if
in
.
Selector
!=
nil
{
out
.
Selector
=
make
(
map
[
string
]
string
)
for
key
,
val
:=
range
in
.
Selector
{
out
.
Selector
[
key
]
=
val
}
}
else
{
out
.
Selector
=
nil
}
if
in
.
Template
!=
nil
{
out
.
Template
=
new
(
v1
.
PodTemplateSpec
)
if
err
:=
convert_api_PodTemplateSpec_To_v1_PodTemplateSpec
(
in
.
Template
,
out
.
Template
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
Template
=
nil
}
if
err
:=
convert_expapi_DeploymentStrategy_To_v1_DeploymentStrategy
(
&
in
.
Strategy
,
&
out
.
Strategy
,
s
);
err
!=
nil
{
return
err
}
if
in
.
UniqueLabelKey
!=
nil
{
out
.
UniqueLabelKey
=
new
(
string
)
*
out
.
UniqueLabelKey
=
*
in
.
UniqueLabelKey
}
else
{
out
.
UniqueLabelKey
=
nil
}
return
nil
}
func
convert_expapi_DeploymentStatus_To_v1_DeploymentStatus
(
in
*
expapi
.
DeploymentStatus
,
out
*
DeploymentStatus
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
expapi
.
DeploymentStatus
))(
in
)
...
...
@@ -1929,44 +1891,6 @@ func convert_v1_DeploymentList_To_expapi_DeploymentList(in *DeploymentList, out
return
nil
}
func
convert_v1_DeploymentSpec_To_expapi_DeploymentSpec
(
in
*
DeploymentSpec
,
out
*
expapi
.
DeploymentSpec
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
DeploymentSpec
))(
in
)
}
if
in
.
Replicas
!=
nil
{
out
.
Replicas
=
new
(
int
)
*
out
.
Replicas
=
*
in
.
Replicas
}
else
{
out
.
Replicas
=
nil
}
if
in
.
Selector
!=
nil
{
out
.
Selector
=
make
(
map
[
string
]
string
)
for
key
,
val
:=
range
in
.
Selector
{
out
.
Selector
[
key
]
=
val
}
}
else
{
out
.
Selector
=
nil
}
if
in
.
Template
!=
nil
{
out
.
Template
=
new
(
api
.
PodTemplateSpec
)
if
err
:=
convert_v1_PodTemplateSpec_To_api_PodTemplateSpec
(
in
.
Template
,
out
.
Template
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
Template
=
nil
}
if
err
:=
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
(
&
in
.
Strategy
,
&
out
.
Strategy
,
s
);
err
!=
nil
{
return
err
}
if
in
.
UniqueLabelKey
!=
nil
{
out
.
UniqueLabelKey
=
new
(
string
)
*
out
.
UniqueLabelKey
=
*
in
.
UniqueLabelKey
}
else
{
out
.
UniqueLabelKey
=
nil
}
return
nil
}
func
convert_v1_DeploymentStatus_To_expapi_DeploymentStatus
(
in
*
DeploymentStatus
,
out
*
expapi
.
DeploymentStatus
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
DeploymentStatus
))(
in
)
...
...
@@ -1976,22 +1900,6 @@ func convert_v1_DeploymentStatus_To_expapi_DeploymentStatus(in *DeploymentStatus
return
nil
}
func
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
(
in
*
DeploymentStrategy
,
out
*
expapi
.
DeploymentStrategy
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
DeploymentStrategy
))(
in
)
}
out
.
Type
=
expapi
.
DeploymentType
(
in
.
Type
)
if
in
.
RollingUpdate
!=
nil
{
out
.
RollingUpdate
=
new
(
expapi
.
RollingUpdateDeployment
)
if
err
:=
convert_v1_RollingUpdateDeployment_To_expapi_RollingUpdateDeployment
(
in
.
RollingUpdate
,
out
.
RollingUpdate
,
s
);
err
!=
nil
{
return
err
}
}
else
{
out
.
RollingUpdate
=
nil
}
return
nil
}
func
convert_v1_HorizontalPodAutoscaler_To_expapi_HorizontalPodAutoscaler
(
in
*
HorizontalPodAutoscaler
,
out
*
expapi
.
HorizontalPodAutoscaler
,
s
conversion
.
Scope
)
error
{
if
defaulting
,
found
:=
s
.
DefaultingInterface
(
reflect
.
TypeOf
(
*
in
));
found
{
defaulting
.
(
func
(
*
HorizontalPodAutoscaler
))(
in
)
...
...
@@ -2262,7 +2170,6 @@ func init() {
convert_expapi_DaemonStatus_To_v1_DaemonStatus
,
convert_expapi_Daemon_To_v1_Daemon
,
convert_expapi_DeploymentList_To_v1_DeploymentList
,
convert_expapi_DeploymentSpec_To_v1_DeploymentSpec
,
convert_expapi_DeploymentStatus_To_v1_DeploymentStatus
,
convert_expapi_DeploymentStrategy_To_v1_DeploymentStrategy
,
convert_expapi_Deployment_To_v1_Deployment
,
...
...
@@ -2289,9 +2196,7 @@ func init() {
convert_v1_DaemonStatus_To_expapi_DaemonStatus
,
convert_v1_Daemon_To_expapi_Daemon
,
convert_v1_DeploymentList_To_expapi_DeploymentList
,
convert_v1_DeploymentSpec_To_expapi_DeploymentSpec
,
convert_v1_DeploymentStatus_To_expapi_DeploymentStatus
,
convert_v1_DeploymentStrategy_To_expapi_DeploymentStrategy
,
convert_v1_Deployment_To_expapi_Deployment
,
convert_v1_EmptyDirVolumeSource_To_api_EmptyDirVolumeSource
,
convert_v1_EnvVarSource_To_api_EnvVarSource
,
...
...
pkg/expapi/validation/validation.go
View file @
e5ac4133
...
...
@@ -17,6 +17,8 @@ limitations under the License.
package
validation
import
(
"strconv"
"k8s.io/kubernetes/pkg/api"
apivalidation
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/expapi"
...
...
@@ -156,3 +158,102 @@ func ValidateDaemonSpec(spec *expapi.DaemonSpec) errs.ValidationErrorList {
func
ValidateDaemonName
(
name
string
,
prefix
bool
)
(
bool
,
string
)
{
return
apivalidation
.
NameIsDNSSubdomain
(
name
,
prefix
)
}
// Validates that the given name can be used as a deployment name.
func
ValidateDeploymentName
(
name
string
,
prefix
bool
)
(
bool
,
string
)
{
return
apivalidation
.
NameIsDNSSubdomain
(
name
,
prefix
)
}
func
ValidatePositiveIntOrPercent
(
intOrPercent
util
.
IntOrString
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
intOrPercent
.
Kind
==
util
.
IntstrString
{
if
!
util
.
IsValidPercent
(
intOrPercent
.
StrVal
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
,
intOrPercent
,
"value should be int(5) or percentage(5%)"
))
}
}
else
if
intOrPercent
.
Kind
==
util
.
IntstrInt
{
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
intOrPercent
.
IntVal
),
fieldName
)
...
)
}
return
allErrs
}
func
getPercentValue
(
intOrStringValue
util
.
IntOrString
)
(
int
,
bool
)
{
if
intOrStringValue
.
Kind
!=
util
.
IntstrString
||
!
util
.
IsValidPercent
(
intOrStringValue
.
StrVal
)
{
return
0
,
false
}
value
,
_
:=
strconv
.
Atoi
(
intOrStringValue
.
StrVal
[
:
len
(
intOrStringValue
.
StrVal
)
-
1
])
return
value
,
true
}
func
getIntOrPercentValue
(
intOrStringValue
util
.
IntOrString
)
int
{
value
,
isPercent
:=
getPercentValue
(
intOrStringValue
)
if
isPercent
{
return
value
}
return
intOrStringValue
.
IntVal
}
func
IsNotMoreThan100Percent
(
intOrStringValue
util
.
IntOrString
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
value
,
isPercent
:=
getPercentValue
(
intOrStringValue
)
if
!
isPercent
||
value
<=
100
{
return
nil
}
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
,
intOrStringValue
,
"should not be more than 100%"
))
return
allErrs
}
func
ValidateRollingUpdateDeployment
(
rollingUpdate
*
expapi
.
RollingUpdateDeployment
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
ValidatePositiveIntOrPercent
(
rollingUpdate
.
MaxUnavailable
,
fieldName
+
"maxUnavailable"
)
...
)
allErrs
=
append
(
allErrs
,
ValidatePositiveIntOrPercent
(
rollingUpdate
.
MaxSurge
,
fieldName
+
".maxSurge"
)
...
)
if
getIntOrPercentValue
(
rollingUpdate
.
MaxUnavailable
)
==
0
&&
getIntOrPercentValue
(
rollingUpdate
.
MaxSurge
)
==
0
{
// Both MaxSurge and MaxUnavailable cannot be zero.
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
fieldName
+
".maxUnavailable"
,
rollingUpdate
.
MaxUnavailable
,
"cannot be 0 when maxSurge is 0 as well"
))
}
// Validate that MaxUnavailable is not more than 100%.
allErrs
=
append
(
allErrs
,
IsNotMoreThan100Percent
(
rollingUpdate
.
MaxUnavailable
,
fieldName
+
".maxUnavailable"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
rollingUpdate
.
MinReadySeconds
),
fieldName
+
".minReadySeconds"
)
...
)
return
allErrs
}
func
ValidateDeploymentStrategy
(
strategy
*
expapi
.
DeploymentStrategy
,
fieldName
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
strategy
.
RollingUpdate
==
nil
{
return
allErrs
}
switch
strategy
.
Type
{
case
expapi
.
DeploymentRecreate
:
allErrs
=
append
(
allErrs
,
errs
.
NewFieldForbidden
(
"rollingUpdate"
,
"rollingUpdate should be nil when strategy type is "
+
expapi
.
DeploymentRecreate
))
case
expapi
.
DeploymentRollingUpdate
:
allErrs
=
append
(
allErrs
,
ValidateRollingUpdateDeployment
(
strategy
.
RollingUpdate
,
"rollingUpdate"
)
...
)
}
return
allErrs
}
// Validates given deployment spec.
func
ValidateDeploymentSpec
(
spec
*
expapi
.
DeploymentSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidateNonEmptySelector
(
spec
.
Selector
,
"selector"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
spec
.
Replicas
),
"replicas"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePodTemplateSpecForRC
(
spec
.
Template
,
spec
.
Selector
,
spec
.
Replicas
,
"template"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateDeploymentStrategy
(
&
spec
.
Strategy
,
"strategy"
)
...
)
if
spec
.
UniqueLabelKey
!=
nil
{
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidateLabelName
(
*
spec
.
UniqueLabelKey
,
"uniqueLabel"
)
...
)
}
return
allErrs
}
func
ValidateDeploymentUpdate
(
old
,
update
*
expapi
.
Deployment
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidateObjectMetaUpdate
(
&
update
.
ObjectMeta
,
&
old
.
ObjectMeta
)
.
Prefix
(
"metadata"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateDeploymentSpec
(
&
update
.
Spec
)
.
Prefix
(
"spec"
)
...
)
return
allErrs
}
func
ValidateDeployment
(
obj
*
expapi
.
Deployment
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidateObjectMeta
(
&
obj
.
ObjectMeta
,
true
,
ValidateDeploymentName
)
.
Prefix
(
"metadata"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateDeploymentSpec
(
&
obj
.
Spec
)
.
Prefix
(
"spec"
)
...
)
return
allErrs
}
pkg/expapi/validation/validation_test.go
View file @
e5ac4133
...
...
@@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/expapi"
"k8s.io/kubernetes/pkg/util"
errors
"k8s.io/kubernetes/pkg/util/fielderrors"
)
...
...
@@ -540,3 +541,120 @@ func TestValidateDaemon(t *testing.T) {
}
}
}
func
validDeployment
()
*
expapi
.
Deployment
{
return
&
expapi
.
Deployment
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
,
},
Spec
:
expapi
.
DeploymentSpec
{
Selector
:
map
[
string
]
string
{
"name"
:
"abc"
,
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
,
Labels
:
map
[
string
]
string
{
"name"
:
"abc"
,
},
},
Spec
:
api
.
PodSpec
{
RestartPolicy
:
api
.
RestartPolicyAlways
,
DNSPolicy
:
api
.
DNSDefault
,
Containers
:
[]
api
.
Container
{
{
Name
:
"nginx"
,
Image
:
"image"
,
ImagePullPolicy
:
api
.
PullNever
,
},
},
},
},
},
}
}
func
TestValidateDeployment
(
t
*
testing
.
T
)
{
successCases
:=
[]
*
expapi
.
Deployment
{
validDeployment
(),
}
for
_
,
successCase
:=
range
successCases
{
if
errs
:=
ValidateDeployment
(
successCase
);
len
(
errs
)
!=
0
{
t
.
Errorf
(
"expected success: %v"
,
errs
)
}
}
errorCases
:=
map
[
string
]
*
expapi
.
Deployment
{}
errorCases
[
"metadata.name: required value"
]
=
&
expapi
.
Deployment
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
api
.
NamespaceDefault
,
},
}
// selector should match the labels in pod template.
invalidSelectorDeployment
:=
validDeployment
()
invalidSelectorDeployment
.
Spec
.
Selector
=
map
[
string
]
string
{
"name"
:
"def"
,
}
errorCases
[
"selector does not match labels"
]
=
invalidSelectorDeployment
// RestartPolicy should be always.
invalidRestartPolicyDeployment
:=
validDeployment
()
invalidRestartPolicyDeployment
.
Spec
.
Template
.
Spec
.
RestartPolicy
=
api
.
RestartPolicyNever
errorCases
[
"unsupported value 'Never'"
]
=
invalidRestartPolicyDeployment
// invalid unique label key.
invalidUniqueLabelDeployment
:=
validDeployment
()
invalidUniqueLabel
:=
"abc/def/ghi"
invalidUniqueLabelDeployment
.
Spec
.
UniqueLabelKey
=
&
invalidUniqueLabel
errorCases
[
"spec.uniqueLabel: invalid value"
]
=
invalidUniqueLabelDeployment
// rollingUpdate should be nil for recreate.
invalidRecreateDeployment
:=
validDeployment
()
invalidRecreateDeployment
.
Spec
.
Strategy
=
expapi
.
DeploymentStrategy
{
Type
:
expapi
.
DeploymentRecreate
,
RollingUpdate
:
&
expapi
.
RollingUpdateDeployment
{},
}
errorCases
[
"rollingUpdate should be nil when strategy type is Recreate"
]
=
invalidRecreateDeployment
// MaxSurge should be in the form of 20%.
invalidMaxSurgeDeployment
:=
validDeployment
()
invalidMaxSurgeDeployment
.
Spec
.
Strategy
=
expapi
.
DeploymentStrategy
{
Type
:
expapi
.
DeploymentRollingUpdate
,
RollingUpdate
:
&
expapi
.
RollingUpdateDeployment
{
MaxSurge
:
util
.
NewIntOrStringFromString
(
"20Percent"
),
},
}
errorCases
[
"value should be int(5) or percentage(5%)"
]
=
invalidMaxSurgeDeployment
// MaxSurge and MaxUnavailable cannot both be zero.
invalidRollingUpdateDeployment
:=
validDeployment
()
invalidRollingUpdateDeployment
.
Spec
.
Strategy
=
expapi
.
DeploymentStrategy
{
Type
:
expapi
.
DeploymentRollingUpdate
,
RollingUpdate
:
&
expapi
.
RollingUpdateDeployment
{
MaxSurge
:
util
.
NewIntOrStringFromString
(
"0%"
),
MaxUnavailable
:
util
.
NewIntOrStringFromInt
(
0
),
},
}
errorCases
[
"cannot be 0 when maxSurge is 0 as well"
]
=
invalidRollingUpdateDeployment
// MaxUnavailable should not be more than 100%.
invalidMaxUnavailableDeployment
:=
validDeployment
()
invalidMaxUnavailableDeployment
.
Spec
.
Strategy
=
expapi
.
DeploymentStrategy
{
Type
:
expapi
.
DeploymentRollingUpdate
,
RollingUpdate
:
&
expapi
.
RollingUpdateDeployment
{
MaxUnavailable
:
util
.
NewIntOrStringFromString
(
"110%"
),
},
}
errorCases
[
"should not be more than 100%"
]
=
invalidMaxUnavailableDeployment
for
k
,
v
:=
range
errorCases
{
errs
:=
ValidateDeployment
(
v
)
if
len
(
errs
)
==
0
{
t
.
Errorf
(
"expected failure for %s"
,
k
)
}
else
if
!
strings
.
Contains
(
errs
[
0
]
.
Error
(),
k
)
{
t
.
Errorf
(
"unexpected error: %v, expected: %s"
,
errs
[
0
],
k
)
}
}
}
pkg/util/validation.go
View file @
e5ac4133
...
...
@@ -139,3 +139,11 @@ func IsValidPortName(port string) bool {
func
IsValidIPv4
(
value
string
)
bool
{
return
net
.
ParseIP
(
value
)
!=
nil
&&
net
.
ParseIP
(
value
)
.
To4
()
!=
nil
}
const
percentFmt
string
=
"[0-9]+%"
var
percentRegexp
=
regexp
.
MustCompile
(
"^"
+
percentFmt
+
"$"
)
func
IsValidPercent
(
percent
string
)
bool
{
return
percentRegexp
.
MatchString
(
percent
)
}
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