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
8a39e538
Commit
8a39e538
authored
May 07, 2018
by
Mehdy Bohlool
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CRD versioning validation and defaulting
parent
10c48ae5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
111 additions
and
7 deletions
+111
-7
helpers.go
...apiextensions-apiserver/pkg/apis/apiextensions/helpers.go
+31
-0
defaults.go
...ions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go
+20
-0
validation.go
...apiserver/pkg/apis/apiextensions/validation/validation.go
+60
-7
validation_test.go
...rver/pkg/apis/apiextensions/validation/validation_test.go
+0
-0
No files found.
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go
View file @
8a39e538
...
...
@@ -17,6 +17,7 @@ limitations under the License.
package
apiextensions
import
(
"fmt"
"time"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
...
...
@@ -116,3 +117,33 @@ func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) {
}
crd
.
Finalizers
=
newFinalizers
}
// HasServedCRDVersion returns true if `version` is in the list of CRD's versions and the Served flag is set.
func
HasServedCRDVersion
(
crd
*
CustomResourceDefinition
,
version
string
)
bool
{
for
_
,
v
:=
range
crd
.
Spec
.
Versions
{
if
v
.
Name
==
version
{
return
v
.
Served
}
}
return
false
}
// GetCRDStorageVersion returns the storage version for given CRD.
func
GetCRDStorageVersion
(
crd
*
CustomResourceDefinition
)
(
string
,
error
)
{
for
_
,
v
:=
range
crd
.
Spec
.
Versions
{
if
v
.
Storage
{
return
v
.
Name
,
nil
}
}
// This should not happened if crd is valid
return
""
,
fmt
.
Errorf
(
"invalid CustomResourceDefinition, no storage version"
)
}
func
IsStoredVersion
(
crd
*
CustomResourceDefinition
,
version
string
)
bool
{
for
_
,
v
:=
range
crd
.
Status
.
StoredVersions
{
if
version
==
v
{
return
true
}
}
return
false
}
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go
View file @
8a39e538
...
...
@@ -31,6 +31,14 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
func
SetDefaults_CustomResourceDefinition
(
obj
*
CustomResourceDefinition
)
{
SetDefaults_CustomResourceDefinitionSpec
(
&
obj
.
Spec
)
if
len
(
obj
.
Status
.
StoredVersions
)
==
0
{
for
_
,
v
:=
range
obj
.
Spec
.
Versions
{
if
v
.
Storage
{
obj
.
Status
.
StoredVersions
=
append
(
obj
.
Status
.
StoredVersions
,
v
.
Name
)
break
}
}
}
}
func
SetDefaults_CustomResourceDefinitionSpec
(
obj
*
CustomResourceDefinitionSpec
)
{
...
...
@@ -43,4 +51,16 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec)
if
len
(
obj
.
Names
.
ListKind
)
==
0
&&
len
(
obj
.
Names
.
Kind
)
>
0
{
obj
.
Names
.
ListKind
=
obj
.
Names
.
Kind
+
"List"
}
// If there is no list of versions, create on using deprecated Version field.
if
len
(
obj
.
Versions
)
==
0
&&
len
(
obj
.
Version
)
!=
0
{
obj
.
Versions
=
[]
CustomResourceDefinitionVersion
{{
Name
:
obj
.
Version
,
Storage
:
true
,
Served
:
true
,
}}
}
// For backward compatibility set the version field to the first item in versions list.
if
len
(
obj
.
Version
)
==
0
&&
len
(
obj
.
Versions
)
!=
0
{
obj
.
Version
=
obj
.
Versions
[
0
]
.
Name
}
}
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go
View file @
8a39e538
...
...
@@ -45,6 +45,7 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio
allErrs
:=
genericvalidation
.
ValidateObjectMeta
(
&
obj
.
ObjectMeta
,
false
,
nameValidationFn
,
field
.
NewPath
(
"metadata"
))
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionSpec
(
&
obj
.
Spec
,
field
.
NewPath
(
"spec"
))
...
)
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionStatus
(
&
obj
.
Status
,
field
.
NewPath
(
"status"
))
...
)
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionStoredVersions
(
obj
.
Status
.
StoredVersions
,
obj
.
Spec
.
Versions
,
field
.
NewPath
(
"status"
)
.
Child
(
"storedVersions"
))
...
)
return
allErrs
}
...
...
@@ -53,6 +54,34 @@ func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomRes
allErrs
:=
genericvalidation
.
ValidateObjectMetaUpdate
(
&
obj
.
ObjectMeta
,
&
oldObj
.
ObjectMeta
,
field
.
NewPath
(
"metadata"
))
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionSpecUpdate
(
&
obj
.
Spec
,
&
oldObj
.
Spec
,
apiextensions
.
IsCRDConditionTrue
(
oldObj
,
apiextensions
.
Established
),
field
.
NewPath
(
"spec"
))
...
)
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionStatus
(
&
obj
.
Status
,
field
.
NewPath
(
"status"
))
...
)
allErrs
=
append
(
allErrs
,
ValidateCustomResourceDefinitionStoredVersions
(
obj
.
Status
.
StoredVersions
,
obj
.
Spec
.
Versions
,
field
.
NewPath
(
"status"
)
.
Child
(
"storedVersions"
))
...
)
return
allErrs
}
// ValidateCustomResourceDefinitionStoredVersions statically validates
func
ValidateCustomResourceDefinitionStoredVersions
(
storedVersions
[]
string
,
versions
[]
apiextensions
.
CustomResourceDefinitionVersion
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
if
len
(
storedVersions
)
==
0
{
return
field
.
ErrorList
{
field
.
Invalid
(
fldPath
,
storedVersions
,
"must have at least one stored version"
)}
}
allErrs
:=
field
.
ErrorList
{}
storedVersionsMap
:=
map
[
string
]
int
{}
for
i
,
v
:=
range
storedVersions
{
storedVersionsMap
[
v
]
=
i
}
for
_
,
v
:=
range
versions
{
_
,
ok
:=
storedVersionsMap
[
v
.
Name
]
if
v
.
Storage
&&
!
ok
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
,
v
,
"must have the storage version "
+
v
.
Name
))
}
if
ok
{
delete
(
storedVersionsMap
,
v
.
Name
)
}
}
for
v
,
i
:=
range
storedVersionsMap
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Index
(
i
),
v
,
"must appear in spec.versions"
))
}
return
allErrs
}
...
...
@@ -75,12 +104,6 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"group"
),
spec
.
Group
,
"should be a domain with at least one dot"
))
}
if
len
(
spec
.
Version
)
==
0
{
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"version"
),
""
))
}
else
if
errs
:=
validationutil
.
IsDNS1035Label
(
spec
.
Version
);
len
(
errs
)
>
0
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"version"
),
spec
.
Version
,
strings
.
Join
(
errs
,
","
)))
}
switch
spec
.
Scope
{
case
""
:
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"scope"
),
""
))
...
...
@@ -89,6 +112,37 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
allErrs
=
append
(
allErrs
,
field
.
NotSupported
(
fldPath
.
Child
(
"scope"
),
spec
.
Scope
,
[]
string
{
string
(
apiextensions
.
ClusterScoped
),
string
(
apiextensions
.
NamespaceScoped
)}))
}
storageFlagCount
:=
0
versionsMap
:=
map
[
string
]
bool
{}
uniqueNames
:=
true
for
i
,
version
:=
range
spec
.
Versions
{
if
version
.
Storage
{
storageFlagCount
++
}
if
versionsMap
[
version
.
Name
]
{
uniqueNames
=
false
}
else
{
versionsMap
[
version
.
Name
]
=
true
}
if
errs
:=
validationutil
.
IsDNS1035Label
(
version
.
Name
);
len
(
errs
)
>
0
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"versions"
)
.
Index
(
i
)
.
Child
(
"name"
),
spec
.
Versions
[
i
]
.
Name
,
strings
.
Join
(
errs
,
","
)))
}
}
if
!
uniqueNames
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"versions"
),
spec
.
Versions
,
"must contain unique version names"
))
}
if
storageFlagCount
!=
1
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"versions"
),
spec
.
Versions
,
"must have exactly one version marked as storage version"
))
}
if
len
(
spec
.
Version
)
!=
0
{
if
errs
:=
validationutil
.
IsDNS1035Label
(
spec
.
Version
);
len
(
errs
)
>
0
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"version"
),
spec
.
Version
,
strings
.
Join
(
errs
,
","
)))
}
if
len
(
spec
.
Versions
)
>=
1
&&
spec
.
Versions
[
0
]
.
Name
!=
spec
.
Version
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"version"
),
spec
.
Version
,
"must match the first version in spec.versions"
))
}
}
// in addition to the basic name restrictions, some names are required for spec, but not for status
if
len
(
spec
.
Names
.
Plural
)
==
0
{
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"names"
,
"plural"
),
""
))
...
...
@@ -130,7 +184,6 @@ func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.Cus
if
established
{
// these effect the storage and cannot be changed therefore
allErrs
=
append
(
allErrs
,
genericvalidation
.
ValidateImmutableField
(
spec
.
Version
,
oldSpec
.
Version
,
fldPath
.
Child
(
"version"
))
...
)
allErrs
=
append
(
allErrs
,
genericvalidation
.
ValidateImmutableField
(
spec
.
Scope
,
oldSpec
.
Scope
,
fldPath
.
Child
(
"scope"
))
...
)
allErrs
=
append
(
allErrs
,
genericvalidation
.
ValidateImmutableField
(
spec
.
Names
.
Kind
,
oldSpec
.
Names
.
Kind
,
fldPath
.
Child
(
"names"
,
"kind"
))
...
)
}
...
...
staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go
View file @
8a39e538
This diff is collapsed.
Click to expand it.
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